Психология убеждения. Как убеждать других и уметь распознавать манипуляции


Эта статья — некраткий конспект книги Роберта Чалдини «Психология убеждения». Будет полезна всем, кто имеет дело с людьми, продажами и бизнесом. Книга настолько полезна, что должна оказаться на полке каждого. Помимо того, что мы хотим влиять на окружающих, очень полезно знать, когда окружающие пытаются повлиять на нас. Внутри вы найдёте множество способов убеждения и, сразу после прочтения, будете с лёгкостью замечать, когда вами пытаются манипулировать.



1. Создайте у аудитории трудности

Измените фразу: «Операторы ждут, звоните прямо сейчас на такую: «Если операторы заняты, пожалуйста, перезвоните». Таким образом вы создадите ощущение дефицита: раз операторы часто заняты, — значит товар хорошо берут. Фактически, вы пользуетесь социальным доказательством, сообщая потенциальным покупателям, что ваш товар уже проверен и нравится множеству людей.
Хорошо, когда вы адресуете сообщение конкретной аудитории. Например, постояльцам конкретного номера гостиницы или жителям своего дома. Напишите на двери подъезда: «У нас самый некурящий подъезд в доме и у нас всегда хорошо пахнет. Добро пожаловать!».

2. Социальное доказательство


Социальным доказательством вы можете достичь в рекламе обратного эффекта. Например, когда вы показываете зрителям, неприемлемое поведение и что так делают многие, зрители подумают так: «раз многие так делают, — значит буду и я». Когда в одном из парков США установили табличку с надписью: «Многие посетители парка уносили кусочки окаменелого дерева, что меняет естественное состояние леса», количество краж увеличилось по сравнению с состоянием, когда таблички вообще не было. Используйте положительное социальное доказательство.

3. Чем меньше выбор — тем лучше

Вместо линейки из 20 похожих продуктов предложите пять или три. Людям будет проще выбирать. Когда линейку шампуней «Head & Shoulders» сократили с 26 разновидностей до 15, — продажи увеличились до 15 процентов.
Домашнее задание: если перевести название «Head & Shoulders» на русский, — получится в высшей степени идиотское название. Воспользуйтесь словарём.

4. Подарок в виде вашего продукта вредит продукту

В дьюти-фри часто продают вонючие вредные жидкости в бутылках. Это виски, коньяк и прочая дрянь. Если в качестве подарка к дорогой вонючей бутылке вам будут дарить браслет с жемчугом, — ваша оценка стоимости этого браслета упадёт на 35%, чем если бы вы его оценили отдельно.
Никогда не давайте свою услугу в качестве бонуса к чему-то ещё. Это снижает её стоимость в глазах потребителя. Перестаньте давать бесплатные советы, чтобы ваше мнение не обесценилось. Один час моего рабочего времени стоит 750 рублей и когда я провожу в школах бесплатные занятия, я всегда говорю о стоимости. Таким образом, школьники начитают больше ценить ту информацию, которую я им даю.

5. Три продукта для продаж компромиссного решения


Если у вас есть только один продукт, — у ваших потребителей нет выбора. Если же появляется второй, более качественный продукт, одно его наличие повысит продажи первого. Когда клиент просит у вас разработать софт, просчитайте три варианта: минимальный, средний и максимальный. Минимальный вариант вы можете сделать заведомо неприемлемым по причине отсутствия ключевых функций. Средний будет тем вариантом, который вы хотите продать. И максимальный — это вариант со свистелками, без которых можно обойтись первый год эксплуатации вашего продукта. Вы не рассчитываете продать максимальный вариант, но, если вдруг клиент его купит вы не обидитесь.

6. Страх с инструкцией по преодолению опасности положительно мотивирует

Напугайте людей и предложите решение проблемы. Если решение не будет предложено, — вы просто вгоните людей в ступор. Расскажите детям пару страшных историй о том, как плох алкоголь и предложите альтернативу: чем заняться в свободное время с друзьями. Важно: это работает только если вы сами не совсем-совсем не пьёте и социально активны.
Подобным приёмом часто пользуются безопасники и антивирусники. Они рассказывают о том, как кругом всё плохо и ненавязчиво сообщают о том, как нужно противодействовать угрозам.
Докладывая руководству о проблемах, придумайте план действий для нейтрализации. Рассказывая пациенту о вреде лишнего веса дайте комплекс упражнений и три банки гербалайфа.

7. Принцип взаимности

Сделайте что-то для человека, и он с большой вероятностью ответит вам тем же. Начните диалог с подарка. Подарком может быть доброе слово или небольшая услуга. Недавно я звонил по телефону в одну из турбаз и в качестве подарка рассказал им как они много теряют, что отсутствуют на booking.com и как им быть. В результате руководитель турбазы приготовилась купить у меня всё что угодно =)
Когда в Череповец пришёл СберТех и высосал всех разработчиков, нам пришлось открыть школу джавистов «Программатики». Получилась бесплатная услуга, которую мы предоставляем кандидатам, и благодаря которой некоторые студенты испытывают чувство благодарности и остаются у нас работать.

8. Пишите лично и от руки

Язык роботов выдаёт вас с головой: «Уважаемый(ая) Владимир Николаевич! Просим вас…». Выглядит некрасиво и крайне глупо.
Когда я делаю рассылку о мероприятиях через Вконтакт, я делаю три разных варианта обращения для разных групп: тех, с кем я на «ты», тех, с кем я на «вы» и тех, с кем я общаюсь довольно близко. Каждое сообщение, если возможно дополняю личностными деталями: «Привет! Я помню, что тебе понравился предыдущий Ведафест. В эту субботу будет …»
Сообщение, приклеенное на клавиатуру и написанное от руки работает лучше, чем электрописьмо. Люди видят дополнительно затраченные усилия и ценят это. При этом исследование показало, что просьба выполняется качественнее, если она вы применяете личностный подход.

9. Сначала подарок

Рестораны ставят чаши с леденцами на выходе и, наверное, это хорошо. Но куда лучше работает бонус на входе. В череповецком кафе «бон-аппетит» вместе с копорским чаем подают печеньку с вареньем. Она почти ничего не стоит для заведения, зато очень радует посетителей и увеличивает размер чаевых. Это всё тот же принцип взаимности: вы УЖЕ сделали первый шаг и вам платят тем же.

10. Ценность оказанной услуги снижается со временем

Если вы помогли другу перевезти мебель, — наибольшее желание ответить взаимностью он будет испытывать в течение короткого времени. И, наоборот, вы будете хорошо помнить об оказанной услуге в течение длительного времени. Причём, первое ощущение благодарности у вашего друга будет ослабевать и в конце значимость оказанной услуги сойдёт на нет. У вас же, наоборот, будет усиливаться ощущение значимости вашего беспримерного подвига.
Помните об этом, когда обращаетесь за помощью. Если с момента переезда прошло уже четверть века, — возможно, ваш друг уже об этом подзабыл.

11. Просите сначала мало, потом много


Эта стратегия называется «нога в двери». Попросите сначала о небольшой услуге, которую несложно оказать. Затем можно попросить что-то побольше.
В книге описано исследование, где домовладельцев просили водрузить на свой красивый газон уродский баннер о безопасности дорожного движения. В первой выборке согласились 17%, а во второй 76%. В чём отличие? За неделю до второй выборки к людям пришли и попросили наклеить небольшую наклейку на стекло с тем же посылом. Люди за это время почувствовали себя ответственными за безопасность дорожного движения.
В продажах это значит, что большому заказу предшествует маленький. Продайте сначала конфету, а потом сможете продать и коробку.

12. Похвалите человека

Полезно бывает немного прославить человека. Думайте о нём хорошо и скажите что-то типа: «у тебя есть все способности, чтобы справиться с этой, безусловно сложной, задачей». Если называть человека свиньёй, он, рано или поздно, хрюкнет. Если поступать наоборот и говорить о нём как о хорошем человеке (хотя он может не соответствовать), — он будет стремится оправдать ваше доверие и начнёт соответствовать мнению.

13. Задайте предварительный вопрос и получите положительный ответ

Пример. Я предварительно звоню и спрашиваю: «Как вы относитесь к онлайн-заказам через интернет? Будет ли их доля в вашей отрасли снижаться или увеличиваться?». Если позвонить этим же людям и сделать персональное предложение на создание интернет-магазина, — вероятность согласия на встречу будет на 25% выше.
Ключевой момент состоит именно в положительном ответе на первый вопрос. «Сможете ли вы позвонить, если вам потребуется отменить заказ столика?». Если клиент отвечает «Да», в вашем ресторане число неявок снизится с 30 до 10 процентов. Когда ваш собеседник говорит «да», он принимает на себя обязательство и стремится его выполнить.

14. Активно взятые обязательства

Запишите свою цель и сделайте это на видном месте. Если вы хотите добиться от ребёнка, чтобы он чего-то достиг, узнайте его цель и запишите её тоже. Это активно взятое обязательство, которое может стать мерилом: полезно/вредно, нужно/не нужно.
Заполненная от руки анкета работает лучше, чем автоматическая.
ЗАДАНИЕ НА ОБДУМЫВАНИЕ: Соискатель устно изъявил желание пройти обучение в «Программатиках». Как повысить вероятность его участия и успешного прохождения курса? Какие приёмы из этой статьи можно применить? Напишите об этом в комментариях.

15. Просите об одолжении

Тот, кто сделал вам одолжение однажды, с большим удовольствием сделает это ещё раз. Франклин попросил у своего оппонента редкую книгу и этот человек стал его другом.
Одолжение должно быть небольшим. И эта система хорошо работает в сфере благотворительности. Сообщите, для нужд детского дома подойдёт любой вклад и даже 50 рублей будут кстати. Таким образом вы насобираете больше.

16. Низкая стартовая цена аукциона

Опыт ebay и их статистика говорят о том, что низкая стартовая цена позволяет продать товар дороже. Люди втягиваются в торги и тут же привязываются в товару. Если ваш товар можно выставить на торги — хорошо. Эта стратегия работает для тех товаров, на которые будет конкурентный спрос. Если большого спроса не предвидится, — поставьте сразу нормальную цену.

17. Пусть вас представят

Когда вы расхваливаете себя сами, это выглядит нескромно и некрасиво. Вместо этого попросите хорошего человека вас представить. Пусть он, а не вы, расскажет о вашем опыте и качествах. Подтверждено исследованиями: хорошо подготовленная третья сторона, выступающая от вашего имени, может быть очень продуктивной.
Объём продаж в вашем офисе вырастет, если вы будете представлять клиентам ваших сотрудников: «Вам нужно купить кирпич? Андрей знает всё о кирпиче и даже побывал на всех кирпичных заводах области. Сейчас я его приглашу».

18. Знайте, что вы ничего не знаете

Если вы считаете себя самым умным, вы редко будете прислушиваться к советам. Это приведёт к замкнутости и ограниченности. Если же вы слушаете всех вокруг и настроены на то, что каждый может дать вам что-то полезное, — скорее всего, рано или поздно, вы сделаете что-то хорошее. Это не значит, что вы принимаете коллективные решения. Но это значит, что вы слушаете разные мнения и самостоятельно делаете вывод.
Важный момент: если вы самый умный, вам могут не рассказать о вашей ошибке и это приведёт к катастрофе. Например, если вы первый пилот и второй пилот думает, что «так надо», вы можете угробить самолёт и пассажиров. Ваша обязанность — избавиться от ореола непогрешимости вокруг вашей персоны, чтобы любой мог поставить под сомнение ваше решение.

19. Избавляйтесь от группового мышления


Множество катастроф произошло потому что люди больше заботились о сохранении отношений, чем о вскрытии проблем. Поощряйте критику и скептицизм. Особенно к тем точкам зрения, которые поддерживают лидеры группы. В противном случае сигнал тревоги может не дойти до адресата. Включите в группу нонконформиста.

20. Учите на ошибках

Исследования показывают, что когда группа учится на ошибках, качество обучения становится выше, чем когда группа учится на успехах. Если вы строите обучение сотрудников только на том, как принимать правильные решения, это не принесёт должного эффекта. Попробуйте объяснить детям что не курить это хорошо. При этом вы сами курите, ваша мама не курит и вы рассказываете на её положительном примере. А теперь достаньте из ящика вашу мед.карту с раковым диагнозом и расскажите об этом ребёнку. Второй вариант сработает лучше.

21. Расскажите о недостатках и перейдите к выгоде

Расскажите о недостатках вашего продукта. Когда «Фольксваген» запускали на рынок США свой «жук», они писали в заголовках газет так: «Уродливый только снаружи». Адвокат может заранее упомянуть о слабых местах своей позиции ещё до того, как всё то же самое повторит прокурор.
При продаже автомобиля можно упомянуть о незначительных недостатках: иногда не контачит правый стоп-сигнал. Это создаст доверие и покупатель с большим доверием отнесётся к остальным вашим словам. Недочёты должны быть достаточно мелкие. Например, если вы покупателю выложите, что в машине клинит двигатель и раз в неделю отказывает тормоз, — скорее всего вы такой автомобиль не продадите (но лучше и не пробовать, а сразу отремонтировать).
«У нас мало места, но это создаёт уютную атмосферу», «Этот курс подойдёт не для всех: только усидчивые и дотошные смогут дойти до конца», «У конкурентов аналогичная машина стоит на 100 тыс. дешевле, однако с нашей машиной вы сэкономите на запчастях и топливе».

22. Признайтесь, что вы были не правы

Если облажались, — извинитесь и скажите об этом. Ор¬га¬низа¬ции, при¬писы¬ва¬ющие не¬уда¬чи внут-ренним при¬чинам, не толь¬ко вы¬иг¬ра¬ют во мне¬нии об¬щес¬тва, но и по¬лучат при¬быль. Если вы намокли под дождём, — вините себя, а не Зевса. Когда вы постоянно вините обстоятельства, это создаёт впечатление, что вы не контролируете ситуацию. Если же вы примете на себя ответственность за произошедшее, есть вероятность, что люди подумают так: «Этот парень, конечно, козёл, но он понял свои ошибки и не совершит их в будущем. И, похоже, он честный человек».

23. Сходство добавляет влияния

Когда я был совсем глупеньким и, живя в СПб зашёл в одну мошенническую контору, девушка-менеджер, спросив меня, откуда я родом, воскликнула: «О! Это здорово! У меня бабушка живёт в Череповце». Чаша весов в этот момент перевесила в её сторону, и я подумал, что передо мной живой человек, у которого тоже есть бабушка.
Совпадение имён, городов, похожесть фамилии, день рождения, рост, вес, школа: всё это поможет установить связь. Если вы знаете о таком совпадении, — воспользуйтесь им.

24. Зеркальте и повторяйте


Напротив вас сидит человек, закинув ногу на ногу. Сделайте точно так же. Клиент вертит в руке карандаш? Повертите ручкой. Это не должно быть похоже на издевательство и карикатуру: незаметно и ненавязчиво.
Когда официант повторяет речь клиента, прибыль заведения увеличивается на 70%. Клиент сказал: «Вот эту жареную хрень». Повторите в точности за ним, но в форме вопроса. Пример из IT: «Значит, вы хотите, чтобы сайт был лёгким: пусть по небу летит слонёнок и извергает из хобота бетон. Верно?». Тогда у клиента возникнет цепочка: вы_повторяете → вы_понимаете → вы_сделаете.

25. Редкие вещи имеют большую ценность

Мы хотим больше, если знаем об эксклюзивности товара. В монетном дворе ограниченной партией отчеканили монету, на которой вместо двуглавого орла случайно оказалась голова Ксении Собчак? — Отлично! Эта монета станет нумизматической редкостью.
Предоставьте потребителям информацию о том, что действительно является редким в ваших товарах и услугах. «У нас вы можете заказать особый чай. Это Иван-чай, который мы собирали и обрабатывали вручную. Попробуйте». Этим пользуются владельцы интернет-магазинов, которые пишут, что товара осталось «мало». Срабатывает чувство потери: а вдруг мне не хватит?

26. Вызывайте чувство потери

Когда кока-кола изменила формулу, по США прошла волна акций протеста. Люди требовали вернуть назад старую колу. Когда Вконтакте изменил поведение стены, множество пользователей начали вопить о том, что нужно вернуть старую стену. Это происходит из-за чувства потери. В обычной ситуации мы не обращаем внимания ни на вкус колы, ни на стену Вконтакта. Однако, как только есть угроза потери, мы начинаем ценить теряемое.
Неопытные инвесторы рано продают акции, потому что боятся потерять уже «заработанные» деньги. На GeekBrains говорят, что только во время GeekConf можно приобрести курс с 30% скидкой (я повёлся =).
Если вы хотите убедить сотрудников в том, что нужно участвовать в вашем супер-стартапе, сообщите что они потеряют в случае отказа. Рассчитайте экономическую выгоду от опциона в предприятии через два года и сообщите ребятам.
Сообщение «В случае отказа вы будете терять по 50 центов ежедневно» работает в три раза лучше, чем «в случае согласия вы будете экономить по 50 центов ежедневно».

27. Говорите «Потому что»


Стоит очередь к копиру. Подходит мужик и говорит: «Простите, можно мне пройти без очереди? У меня всего пять страниц». 60% людей согласились его пропустить. Наверное, подумали, что наглость — это второе счастье. Но когда мужик переформулировал просьбу, его пропустили 94% людей. Он начал говорить так: «Можно мне пройти без очереди, потому что я очень спешу». Далее этот же мужик переформулировал вопрос так, что получилась совершеннейшая глупость: «Могу ли я пройти без очереди, потому что мне нужно сделать копии?». Понятное дело, что он не завтракать к копиру пришёл, однако, его пропустили 93%.
Работает сила двух слов: «потому что» и для маленьких просьб почти не важно, что вы скажете после этих слов. Однако, если просьба будет существеннее (20 копий), на псевдопричину мало кто поведётся.
У этого принципа есть дополнительный эффект. Когда вы просите назвать причину, ваш собеседник начинает больше верить в эту причину и хорошенько её запомнит. Его мнение о вас улучшится: «Назовите две причины, по которым вам нравится с нами работать». Однако, не переборщите. Если вы попросите назвать десять причин, это создаст обратный эффект.

28. Используйте простые слова

Люди привязываются к простым произношениям. Если ваше предприятие называется ПромГражданРемСтрой-3 — это капец. Исследования на NYSE показывают, что предприятия с простыми названиями больше зарабатывают.
Использование слишком сложного языка приводит к обратному эффекту. Оцените: «Мы усиливаем свои активы и создаем стратегические альянсы для формирования центра надежных знаний с управляемой клиентами бизнес-структурой и использованием лидирующих технологий, чтобы максимизировать функционирование человеческого фактора». Это публикация из NY Post, однако, такой мусор часто встречается на страницах «О компании» плохих сайтов.
В качестве простых слов можно использовать стихи. Стихи в рекламе способствуют запоминанию. Практика показывает, что рифмованные слоганы некоторых рекламных роликов зрители помнят по 30 лет. Чего нельзя сказать об обычных рекламных сообщениях. Говорят даже, что рифмованное сообщение выглядит более правдивым. Я с этим утверждением внутренне не согласен, однако в книжке написано именно так.

29. Используйте выгодное сравнение

Если сначала поднять гирю в 24 килограмма, а потом поднять гирю в 16 кг, вы ощутите, какая она лёгкая. С другой стороны, если вы сначала поднимите 8 кг, а затем 16 кг, то та же самая гиря вам покажется тяжелее. Дело тут не в гире, а в восприятии.
Расскажите сначала совсем немного о каком-то другом продукте или предмете, а затем перейдите к описанию целевого продукта. Бывают случаи, когда мы не можем изменить наш продукт или нашу идею, но если дадим выгодное для нас сравнение, это поможет нам быть более убедительными.

30. Давайте фору

В автомойках клиентам часто выдают карточки. На них при каждом посещении ставят штамп. После 10 посещений одиннадцатое бесплатно. Если сразу проставить два штампа, количество дошедших до конца вырастет вдвое. Это потому у посетителей сложилось впечатление, что они уже что-то сделали и путь к окончанию квеста не так уж сложен.
Это применимо и в повседневной жизни. Когда вы просите человека о помощи, сообщите ему, какие шаги он уже сделал. Например, что он уже обладает нужным опытом, что у него есть готовые исследования и мысли на нужную тему. Если проект уже начат вами, — сообщите, что проект уже сделан на 30 процентов.

31. Предложите оригинальное название

Цветные карандаши со странными названиями цветов лучше продаются. Например, вместо зелёный пишут лягушачье-зелёный. Или вместо простого оранжевого — миллениум оранжевый. Это кажется глупостью, но эффективно работает. Неожиданные названия выступают своего рода головоломкой: покупатель должен подумать и решение этой маленькой загадки заставит продукт запомниться.
Тот же метод сработает и с детьми: приготовьте на обед «кабачки по-негритянски» или пусть у вас на столе окажется «упма», «кичри», «сабджи» и «карамельное бурфи». Это лучше, чем каша, рис, печёные овощи и конфеты.

32. Повесьте зеркало


Зеркало стимулирует честность. Детям предложили взять одну конфету из корзины и вышли. Ребёнок оставался один-на-один с корзинкой конфет и боролся с искушением взять больше, чем одну. В результате, 33% детей взяло больше одной конфеты. Когда рядом с корзинкой повесили зеркало, количество нечестных детей сократилось до 8%.
Когда человек видит своё отражение, он старается вести себя в соответствии с принятыми им социальными нормами. Правильно поставленные зеркала способствуют тому, чтобы дети лучше вели себя по отношению друг к другу.
Сотрудники вашего магазина воруют? Поставьте на складе больше зеркал.

33. Контролируйте эмоции

Печальные покупатели готовы купить товар на 30% дороже. Печальные продавцы готовы продать товар на 33%, чем эмоционально нейтральные. После просмотра печального фильма люди становятся более расточительнее, чем после просмотра нейтрального фильма.
Прежде, чем пойти на важные переговоры, убедитесь, что вы находитесь в психологически нейтральном состоянии. Не планируйте встречи одну за другой, чтобы эмоции успевали утихнуть.
Как продавец вы можете попробовать вызвать печаль и предложить выгодную для себя сделку. Однако, решение, которое примет ваш покупатель будет потом вызывать сожаление. Если вы рассчитываете на долгосрочные отношения, —не используйте эту уловку.

34. Отдыхайте и не отвлекайтесь

Уставший человек принимает решения необдуманно. Обычно, когда мы слышим какое-то утверждение, мы сначала пытаемся интерпретировать его как истину, но через мгновение включаем критика и проверяем, так ли это. Когда человек устал и критик может не включиться. Не слушайте на ночь враньё с «Эха Москвы» и не читайте Солженицына. Лучше читать священные писания: это укрепит вашу веру =)
Примерно тот же эффект происходит, когда мы отвлекаемся. Если в момент переговоров вы отвлечётесь на что-нибудь постороннее или ваш собеседник намеренно вас отвлечёт, — есть вероятность заключения плохой сделки. Отвлечь может телефон, нестандартные единицы измерения в договоре, птица за окном и декольте собеседницы. Если убрать отвлекающий фактор невозможно, — перенесите принятие решения.

35. Кофеин помогает убеждать

Напоите человека стаканом кофе и начинайте убеждать. Всё дело в том, что кофеин снижает способность противостоять убеждениям. Однако, это работает только когда утверждение хорошо обосновано. При плохих аргументах вам не поможет даже литр кофе.
— Бога нет, потому что я его не вижу (плохой аргумент).
— У вас нет мозгов, потому что я их тоже не вижу (кофеин не помог).
Приглашайте убеждаемого на чашку кофе, хорошенько подготовившись.

36. Встречайтесь лично или звоните

Исследования показывают, что поговорить с человеком лично гораздо эффективнее, чем по электронной почте. Особенно, если мы имеем дело с женщиной. Надеюсь, у уважаемых читателей уже есть это понимание из личного опыта.
Дело в том, что в письме нет эмоций, а эмоциональный фон сообщения — это тот самый эликсир убеждения. Без эмоций сообщение будет сухим и, что ещё хуже, оно может быть неправильно понято. Напишите письмо с текстом: «Ну ты специалист» и вы никак не сможете предугадать, как оно будет воспринято. Всё потому что в нём не было интонации.
Я часто пишу письма и очень внимательно отношусь к тому, как оно может быть воспринято. Может ли оно быть неправильно понято? Есть ли неточности?

Этика

Использование техник убеждения лежит на вашей совести. Если вы заключаете на основе вышеперечисленных техник невыгодную для человека сделку, — он будет разочарован и ваша репутация пострадает. Конечно, если вы какой-нибудь «РЖД» или «Почта РФ», вам не так важна репутация: вы монополист и вам наплевать на мнение о вашем сервисе. Но если вы хотите сохранить хорошие отношения с клиентами, родными, друзьями и партнёрами, — пользуйтесь исключительно во благо ближнего.
«Итак во всем, как хотите, чтобы с вами поступали люди, так поступайте и вы с ними, ибо в этом закон и пророки.» (Нагорная проповедь, Мф, 7.12)

За иллюстрации спасибо Александру Корнилову.
ссылка на оригинал статьи https://habrahabr.ru/post/316784/

Топливные элементы как один из источников энергии для дата-центра

За работой Bloom Energy мы, компания KingServers, следим уже долгое время. Дело в том, что она предлагает интересный вариант снабжения дата-центра энергией. А именно — топливные элементы на биозгазе. Клиены этой компании используют в своих топливных элементах проприетарную технологию, позволяющую получать энергию из атмосферного воздуха и биогаза. Отходы — вода и совсем небольшое количество углекислого газа.

Сейчас многие телекоммуникационные компании идут навстречу своим клиентам, которые высказывают пожелания об отказе от традиционного энергоснабжения в пользу «зеленой» энергии. Почему так происходит — вопрос другой, но тенденция становится все более заметной. Это далеко не всегда возможно, но ряд разработчиков оборудования пошел навстречу таким пожеланиям.

Конечно, ради собственной репутации и оригинальной коммерческая компания может пойти на многое. Но здесь есть и еще одна причина. Дело в том, что биогаз во многих регионах гораздо более дешевый источник энергии, чем все остальные источники. В частности, в Калифорнии многие компании перешли именно на биогаз, отказавшись от традиционных источников.

Сейчас, например, топливные элементы компании Bloom Energy использует в Северной Каролине корпорация Apple, компания Ebay, CenturyLink.


Сейчас компания Bloom Energy приняла решение объединить усилия с решениями от Power Secure. Она предлагает клиентам системы хранения энергии Power Secure. В итоге покупатели получают универсальные решения, которые можно использовать в самых труднодоступных регионах. Использовать решение от Bloom energy можно в самых сложны ситуациях. Дело в том, что у такой системы модульная архитектура, плюс ПО, которое старается оптимизировать работу станции. В результате клиенты дата-центра с такой схемй энергоснабжения добиваются сильной экономии средств, которые в противном случае были бы связаны с использованием электроэнергии.

В числе прочих задач обе компании предусматривают следующие:

  • Разработка и обеспечение электроснабжения всех элементов распределенной инфраструктуры;
  • Возможность работы с нагрузками разного типа;
  • Уровень надежности дата-центров выполняет требования от минимального до соответствующего потребностям важнейших элементов инфраструктуры;
  • Достижение необходимого уровня надежности: от минимального до соответствующего потребностям критически важных элементов инфраструктуры;
  • Работа с местными генерирующими мощностями на базе топливных элементов. По словам некоторых экспертов, новый автомобиль может обеспечить эффективную работу продавцов.

Кроме того, разработчики ставят своей целью обеспечение, в первую очередь, обеспечение качественного электроснабжения элементов распределенной инфраструктуры;
Обслуживание любой степени занятости;
Необходимость достигнуть уровня надежности не ниже Tier III. Есть планы усилить уровень защиты системы благодаря установке решений.

Сейчас обе компании уже принимают предзаказы от клиентов. Причем заказы отнюдь не единичные. Вскоре планируется выпуск топливных элементов Bloom energy с готовой теплой виоды.

Bloom Energy и партнеры уже принимают заказы от потенциальных клиентов. Bloom Energy предлагает это и другие решения для снижения затрат дата-центра, как прямых, так и косвенных.

Ранее представители аналогичного проекта заявили: «Главное отличие нашего проекта от традиционной схемы электропитания — это производство энергии внутри дата-центра, вместо подключения дата-центра к энергетической инфраструктуре какого-либо региона. Довольно большое количество энергии сейчас теряется в энергетической инфраструктуре дата-центров, что влечет за собой финансовые убытки, повышение операционных и капитальных затрат. Мы же показываем как внедрение небольшого источника питания в элемент сетевой инфраструктуры ЦОД-а позволяет снизить сложность проекта распределения энергии между элементами всей системы», — пишут участники проекта в официальном блоге.

В Bloom Energy считают, что их топливные элементы могут заменить собой большинство традиционных источников электроэнергии. И с этой компанией согласны другие.

Недавно корпорация Microsoft предложила использовать биогазовые установки. И сейчас работу система, которая может применяться в любом месте, снабжая экосистему региона необходимой энергией, проветяют в нескольких штатах США и различных европейских странах.
ссылка на оригинал статьи https://habrahabr.ru/post/316782/

Я провел 3 месяца, пытаясь устроиться на работу после лагеря программирования, и вот чему я научился

image

Меньше всего говорят о том, что будет после того как ты окончишь лагерь по программированию — когда ты пытаешься занять позицию разработчика с шестизначным окладом.

image
< 3% заявлений становились предложениями

Я окончил Hack Reactor в июле 2016, и мне потребовалось почти 3 месяца, прежде чем я принял предложение от Radius Intelligence. Я подавал заявления в 291 компанию, прошел 32 собеседования по телефону и 16 обычных, а также выполнил 13 задач по программированию, 11 из которых на сайтах. И получил в итоге 8 предложений. Мне предлагали 60-125 тысяч долларов в компаниях США. В общем 2.8% заявок обернулись для меня выгодными предложениями.

Вот 5 вещей, которые я хотел бы знать, прежде чем устраивался на работу.


Озарение#1: пытайтесь связаться с реальными людьми

Поначалу я подавал заявления в компании самым легким способом через Indeed.com, AngelList, LinkedIn, StackOverflow, Hacker News, сайты компаний и даже Craigslist.

Я хотел подать резюме на любую специальность, где требовался опыт пользования React, Node или JavaScript. В первую неделю, я обращался к 15-20 организациям в день.

Совет от профессионала: Найдите компании, которые используют эту легкую форму подачи заявок

Результат был не утешающим. Менее 5% компаний отвечали мне. Я словно бы бросал заявления об устройстве на работу в черную дыру.

Все изменилось, когда один из моих товарищей, бывший вербовщик, поделился со мной информацией о том, как искать работу. Он сказал отправлять письма непосредственно людям из этих компаний. Это могут быть кто угодно. Главное, чтобы они прочитали ваше заявление.

Тогда каждый раз, когда я хотел подать заявление, я искал компанию на LinkedIn и писал кому-то из их технической поддержки или команды найма.

У большинства небольших компаний или руководителей высшего звена адрес почты в таком формате firstName@dreamCompany.com. У крупных компаний это firstName.lastName@dreamCompany.com.

Для проверки электронной почты, я использовал Rapportive, чтобы привязать почту к аккаунтам в социальных сетях.

Результаты были потрясающими. После 150+ отправленных писем результат улучшился на 22%.
Мне также нравилось связываться с реальными людьми. Удивительно, но мне ответили даже CEO и CTO. Иногда они даже сами проводили собеседования.

Вывод: если вы устраиваетесь на работу самым легким способом, попытайтесь достучаться до реальных людей.

Озарение#2: начните с малого и пробейте себе путь наверх

Вы будете сталкиваться с собеседованиями 1 уровня (нетехническая компания, которая нуждается в любом разработчике), где вам зададут лишь тривиальные вопросы о JavaScript.

Вы столкнетесь с собеседованиями 9 уровня (уровень Google/Facebook), где вам будут задавать сложные вопросы о структуре данных и вопросы касательно алгоритмов.

Я стратегически выстраиваю процесс так, чтобы сначала пройти собеседования низкого уровня, а затем более сложные.

От компаний с собеседованиями низкого уровня я получил опыт, уверенность в себе и своих силах и надежные предложения.

Чем больше опыта я получал, тем эффективней поднимался на новый уровень и мог проходить собеседования в компаниях, где была более высокая планка для работников. Ниже это проиллюстрировано в виде линейной корреляции между количеством недель, которые я потратил на собеседования и окладом, который мне предложили.

image
Прямая зависимость между временем, которое я потратил на собеседования и предложенной зарплаты

Я преодолел сложные вопросы. Затем пробился к высокой зарплате. И в итоге заполучил желаемую должность.

Вывод: планируйте свои собеседования так, чтобы сначала пройти более легкие, а затем сложные.

Озарение#3: учитесь так, будто от этого зависит ваша будущая работа (потому что так и есть)

Ненавижу говорить это, но самое важное, что вы должны делать — это учиться и готовиться.

Почему? Потому что вы не получите предложения, если у вас не будет хороших ответов на вопросы, которые вам будут задавать.

Люди не будут рассматривать вашу кандидатуру, если они будут видеть, что вы не готовы к собеседованию.

Возвращаясь к теме о Hack Reactor, моей слабостью были структуры данных и алгоритмы. Исследование Триплбайта выявило, что оценки ребят из компьютерного лагеря слабее, чем оценки ребят из computer science.

Поэтому я учился и практиковался. Каждый день.

Я посвящал целые дни изучению алгоритмов сортировки. В другие дни я фокусировался на понимании того, как работает интернет.

Если я не полностью понимал концепцию, то проводил весь день за просмотром видео на YouTube или искал информацию на StackOverflow пока, наконец, не понимал.

Я нашел следующие учебные материалы полезными:

  • InterviewCake: Мой любимый источник информации о структуре данных и алгоритмах. Он разбивает решение на пошаговый алгоритм — отличная альтернатива Cracking the Code Interview (CTCI). Жаль только, что они не решают другие проблемы!
  • HiredInTech’s System Design Section: отличное руководство по собеседованиям касательно системы дизайна.
  • Coderust: если вы избегаете CTCI как чумы, Coderust 2.0 возможно идеально вам подойдет. За 49$, вы получите решения практически на любом языке программирования, с использованием интерактивных схем.
  • Reddit’s How to Prepare for Tech Interviews: постоянно использую его в качестве ориентира своей подготовки.
  • Front End Interview Questions: Исчерпывающий перечень интерфейсных вопросов.
  • Leetcode: ресурс с вопросами по алгоритмам и структуре данных. Вы можете фильтровать их по компаниям. Так, например, вы можете получить все вопросы, которые, как правило, задают Uber или Google.

Вывод: слишком много подготовки не бывает.

Озарение#4: показывайте себя с лучшей стороны

Пробиться в индустрию сложно. Вы должны хорошо проявить себя, даже если не очень подготовлены. Чтобы добиться успеха, нужно быть своим собственным адвокатом.

Продавайте себя

В Hack Reactor мы тренировались маскировать наше отсутствие опыта. В нашей личной жизни, мы намеренно умалчиваем о нашем образовании в лагере программистов.

Почему? В противном случае, нас автоматически классифицируют как младших разработчиков или как работников, у которых недостаточно опыта.

В одном из собеседований с стартапом, собеседование сразу сошло на нет, как только услышали, что я был в лагере программистов. Одна компания использовала это против меня и предложила мне 60000$ (столько предлагают младшим разработчикам).

В конечном счете, вы должны убедить компании, что вы можете сделать эту работу.

В то же время, вы должны убедить себя, что вы можете сделать эту работу.

Вы можете. Сосредоточьтесь на любви к программированию. Сосредоточьтесь на том, что вы построили с React и Node. Сосредоточьтесь на том, чтобы продемонстрировать ваши обширные знания в JavaScript и других языках программирования.

Только они могут доказать, что вы заслуживаете эту работу.

Это двусторонний разговор

Собеседование — это взаимное изучение соответствия между работником и работодателем. Хоть вы и должны убедить работодателя нанять вас, он тоже должен завоевать вас.

Не стыдитесь использовать собеседование как возможность оценить возможность трудоустройства.

Я разговаривал с любой компанией, даже если я не имел к ней ни малейшего интереса.

Я проходил собеседования на местах со всеми компаниями, которые меня приглашали. Я задавал вопросы и получал знания от команды инженеров об используемых инструментах и технологиях, проблемах компании и архитектуры системы.

Профессиональный совет: во время собеседований задавайте следующие вопросы:

  • С какими техническими трудностями вы недавно столкнулись?
  • Что вам нравится в работе на компанию X?
  • Как построены команды и как обычно распределяются задачи?

Я относился к каждому взаимодействию как к возможности узнать что-то новое. Каждое взаимодействие помогло мне улучшить свой доклад, собеседование и технические навыки. Каждая неудача помогла мне найти мои слабые места.

Вывод: знайте себе цену! И помните, это взаимная разведка.

Озарение#5: это марафон, а не спринт

Путешествие отнюдь не легкое. В течение 3 месяцев, я оттачивал свое мастерство 6 дней в неделю. Но я старался заботиться о себе.

image
Так может выглядеть типичный день в JavaScript

Несколько дней я учился с друзьями. В другие дни я шел в кафе и занимался один или зависал в выпускном зале Hack Reactor. И каждую неделю я связывался с консультантом занятости, чтобы поговорить о своем прогрессе.

Легко перегореть в процессе. Хорошо питайтесь, спите и занимайтесь спортом.

Может стать одиноко. Проводите время с друзьями, которые проходят через то же, что и вы.

Вывод: приготовьтесь к долгой игре и убедитесь, что вы хорошо заботитесь о себе

Итог:

  1. Связывайтесь с реальными людьми
  2. Начните с малого и пробивайте себе путь наверх
  3. Учитесь так, будто ваша будущая работа зависит от этого
  4. Показывайте себя с лучшей стороны
  5. Это марафон, а не спринт

Процесс может казаться нескончаемым, но вы справитесь. Продолжайте считать часы. Продолжайте подавать заявления. Продолжайте заботиться о себе. Все это окупится в итоге.

Особая благодарность Дилану Трану, Карен Цао, Рохиту ‘Солнечному’ Рехи, Джейк Пейс, Анамите Гуха, Стефани Лю, и многим другим.
ссылка на оригинал статьи https://habrahabr.ru/post/316776/

Подключение периферийных модулей к MIPSfpga, на примере ультразвуковых датчиков расстояния

Доброго времени суток. В этой статье расскажу как интегрировать модули, на примере двух ультразвуковых датчиков HC-SR04 и Pmod MAXSONAR, в систему на кристалле на основе MIPSfpga. Также расскажу как написать программу для управления подключенных модулей.
Основываясь на моем примере вы сможете подключить ваши собственные модули, управлять ими при помощи программы. Создавать систему со своим набором периферии, на основе MIPSfpga.



Подключать будем вот такой датчик:

Документацию на него можно найти здесь. Данные будем выводить на семисегментные индикаторы на плате. Также будем генерировать звуковые сигналы различной длительности при помощи пьезодинамика.

Для начала, необходимы исходники MIPSfpga. Инструкция по скачиванию:
www.silicon-russia.com/2015/12/11/mipsfpga-download-instructions
Далее, нужно скачать надстройку MIPSfpga-plus, которая позволяет записывать программы по UARTу:
github.com/MIPSfpga/mipsfpga-plus.
Описание и инструкции по установке присутствуют, если коротко, то для того чтобы была возможность просто запустить скрипт и проект собрался, необходимо:
Поместить исходники MIPSfpga в папку:

C:\MIPSfpga

А MIPSfpga-plus в:

C:\github\mipsfpga-plus

Далее в папке C:\github\mipsfpga-plus\boards выбрать свою плату, у меня это de0_cv, и выполнить скрипт make_project. Проект, который нужно запускать будет находиться в C:\github\mipsfpga-plus\boards\de0_cv\project.
Если вашей платы нет, то можно выбрать наиболее подходящую по количеству логических ячеек и изменить назначения.

Также понадобятся компилятор, линковщик Codescape.
И USB UART преобразователь. Например, pl2303hx или ch340.

Датчик имеет аналоговый выход, выход широтно-импульсной модуляции, последовательный интерфейс UART, который и будем использовать для подключения датчика к MIPSfpga.
Подключение осуществляется путем подключения регистров, в которые отображаются данные с датчика, к шине, по которой процессор общается с памятью.

Опишем модуль, который будет принимать и обрабатывать данные с датчика.

UART приемник будем использовать уже описанный, который используется для зашивки программ, изменив только параметр baud_rate на 9600, такую скорость передачи использует датчик.

Модуль uart receiver
module uart_receiver (     input  clock,     input  reset_n,     input  rx,     output reg [7:0] byte_data,     output           byte_ready );       parameter  clock_frequency        = 50000000;      parameter  baud_rate              = 9600;     localparam clock_cycles_in_symbol = clock_frequency / baud_rate;      // Synchronize rx input to clock      reg rx_sync1, rx_sync;      always @(posedge clock or negedge reset_n)     begin         if (! reset_n)         begin             rx_sync1 <= 1;             rx_sync  <= 1;         end         else         begin             rx_sync1 <= rx;             rx_sync  <= rx_sync1;         end     end      // Finding edge for start bit      reg prev_rx_sync;      always @(posedge clock or negedge reset_n)     begin         if (! reset_n)             prev_rx_sync <= 1;         else             prev_rx_sync <= rx_sync;     end      wire start_bit_edge = prev_rx_sync & ! rx_sync;      // Counter to measure distance between symbols      reg [31:0] counter;     reg        load_counter;     reg [31:0] load_counter_value;      always @(posedge clock or negedge reset_n)     begin         if (! reset_n)             counter <= 0;         else if (load_counter)             counter <= load_counter_value;         else if (counter != 0)             counter <= counter - 1;     end      wire counter_done = counter == 1;      // Shift register to accumulate data      reg       shift;     reg [7:0] shifted_1;     assign    byte_ready = shifted_1 [0];      always @ (posedge clock or negedge reset_n)     begin         if (! reset_n)         begin             shifted_1 <= 0;         end         else if (shift)         begin             if (shifted_1 == 0)                 shifted_1 <= 8'b10000000;             else                 shifted_1 <= shifted_1 >> 1;              byte_data <= { rx, byte_data [7:1] };         end         else if (byte_ready)         begin             shifted_1 <= 0;         end     end      reg idle, idle_r;      always @*     begin         idle  = idle_r;         shift = 0;          load_counter        = 0;         load_counter_value  = 0;          if (idle)         begin             if (start_bit_edge)             begin                 load_counter       = 1;                 load_counter_value = clock_cycles_in_symbol * 3 / 2;                             idle = 0;             end         end         else if (counter_done)         begin             shift = 1;              load_counter       = 1;             load_counter_value = clock_cycles_in_symbol;         end         else if (byte_ready)         begin             idle = 1;         end     end      always @ (posedge clock or negedge reset_n)     begin         if (! reset_n)             idle_r <= 1;         else             idle_r <= idle;     end  endmodule

Согласно даташиту[1], каждые 49мс, сонар отправляет четыре байта в ASCII формате, символ “R” и три символа измеренного расстояния, старшими разрядами вперед.

Модуль sonar
module sonn (     input  clock,     input  reset_n,     input  rx, 	 output reg [15:0] hword );  reg [1:0] count2; wire [7:0] byte_data; reg [31:0] wordd;  always @(posedge clock)     if (! reset_n) 	     wordd <= 32'b0; 	  else if (byte_ready) 	     	case(count2) 			2'd0:begin  				wordd[31:24]<=byte_data; 				    if(byte_data==8'h52) 					count2<=2'd1; 				end 			2'd1:begin wordd[23:16]<=byte_data; count2<=2'd2;end 			2'd2:begin wordd[15:8]<=byte_data; count2<=2'd3;end 			2'd3:begin wordd[7:0]<=byte_data; count2<=2'd0; 			           hword={4'b0000,wordd[19:16],wordd[11:8],wordd[3:0]};end 			default begin  				wordd[31:24]<=byte_data; 				    if(byte_data==8'h52) 					count2<=count2+1'b1; 				end 			endcase 	 uart_receiver uart(clock,reset_n,rx,byte_data,byte_ready); endmodule

По каждому такту и флагу byte_ready(взводится, когда был принят байт) ожидаем символ “R” – 52 в шестнадцатеричном, далее переходим к приему следующих трех символов. По приему трех байт записываем в выходной регистр младшие полубайты, таким образом переводим из ASCII в двоично-десятичный формат.

Модуль для управления пьезодинамиком состоит из двух, в первом собственно генерируются импульсы с возможностью выбора частоты:

Модуль tone
module note(clk,reset_n,notein,noteout); input clk,reset_n; input [6:0]notein; output reg noteout;  reg [19:0]div; reg [19:0]cnt; reg eocnt;   always @* begin   case (notein)     0: div = 191114; // C     1: div = 180385; // C#     2: div = 170262; // D     3: div = 160705; // D#     4: div = 151686; // E     5: div = 143173; // F     6: div = 135136; // F#     7: div = 127552; // G     8: div = 120389; // G#     9: div = 113636; // A     10:div = 107259; // A#     11:div = 101239; // H     12:div = 95558; // C      13:div = 90194; // C#     14:div = 85132; // D     15:div = 80354; // D#     16:div = 75845; // E     17:div = 71558; // F     18:div = 67567; // F#     19:div = 63775; // G     20:div = 60197; // G#     21:div = 28403; // A        22:div = 53629; // A#     23:div = 50619; // H     24:div = 47777; // C     25:div = 45097; // C#     26:div = 42566; // D     27:div = 40176; // D#     28:div = 37921; // E             default: div = 1; //   endcase end        always @(posedge clk) begin  if(~reset_n) begin   noteout<=0;   cnt <= 0; end     if(cnt == div) 	 begin         cnt <= 0; 		  noteout <= ~noteout; 	 end     else         cnt <= cnt + 1'b1; end  endmodule 

Считаем до div и инвертируем выходной сигнал. Div выбирается входным notein.
Div = Fclk/Fnote/2
Где Fclk – частота тактового сигнала, Fnote – требуемая частота выходного сигнала.

И модуль где регулируется длительность звуковых импульсов:

Модуль buzz
module buzz(clk,reset_n,en,tim,tone); input clk,reset_n,en; input [1:0]tim; output reg tone;  wire [6:0]notein; wire noteout; assign notein=21;  reg [27:0]counter,div,div1; reg ene;  note note1(clk,reset_n,notein,noteout);  always@(posedge clk) if(~reset_n) begin  counter<=28'b0;  ene<=1'b0; end else begin   case(tim) 	0:begin div<=28'd 5_000_000; div1<=28'd 12_000_000; end 	1:begin div<=28'd 10_000_000; div1<=28'd 20_000_000; end 	2:begin div<=28'd 25_000_000; div1<=28'd 35_000_000; end 	3:begin div<=28'd 50_000_000; div1<=28'd 60_000_000; end    default begin div<=28'd 10_000_000; div1<=28'd 20_000_000; end   endcase      counter<=counter+1;   if(counter==div) 	 ene<=1'b1;   if(counter==div1 | counter>60_000_000)    begin 	 counter<=28'b0; 	 ene<=1'b0;    end end  always@(posedge clk) tone<=en¬eout&ene; endmodule

Каждый такт счетчик инкрементируется, при достижении значения div разрешается звуковой сигнал, при достижении значения div1 запрещается. Таким образом задается длительность, и частота звуковых сигналов. Также счётчик ограничен 60000000 для предотвращения длительного импульса, который может возникнуть при изменении div1 в момент, когда значение счётчика между div и div1.

Подключаем к проекту файлы с описанными выше модулями.

  • В файле верхнего уровня у меня это de0_cv.v добавим следующие строчки:
    wire [15:0]hword; wire [31:0]control;  sonn sonna (  .clock		( CLOCK_50  ),  .reset_n 		( RESET_N   ),  .rx			( GPIO_0[7] ),	  .hword 		( hword     ) );  buzz buzz (  .clk			( CLOCK_50		),  .reset_n		( RESET_N		),  .en			(control [0]		),  .tim			(control [2:1]	),  .tone			( GPIO_0[35]	) );

    Для входа RX UART приемника выделяем пин GPIO_0[7] и для выхода tone GPIO_0[35]. Регистры hword и control будем подключать к шине.

     assign GPIO_0 [1] = 1'b1; //VCC for Sensor  assign GPIO_0 [3] = 1'b0; //GND for Sensor  assign GPIO_0 [34] = 1'b0; //GND for buzz

    Выделим ножки GPIO_0 [1], GPIO_0 [3], GPIO_0 [34] для питания сенсора, общего провода для сенсора и пьезодинамика соответственно.

    В описании модуля mfp_system добавим:

    .IO_Sonar	( hword    ),  .IO_control     ( control  ),

  • В файле mfp_system.v добавляем входы выходы:
     input [15:0]  IO_Sonar,  output [31:0] IO_control, 

    В описании модуля mfp_ahb_lite_matrix_with_loader:

    .IO_Sonar         (   IO_Sonar   ),  .IO_control       (   IO_control ),

  • В файле mfp_ahb_lite_matrix_with_loader.v:
     input  [15:0] IO_Sonar,  output  [31:0] IO_control,

    В описании модуля mfp_ahb_lite_matrix:

     .IO_Sonar	( IO_Sonar        ),   .IO_control       ( IO_control      ),

  • В файле mfp_ahb_lite_matrix.v:
     input  [15:0] IO_Sonar,  output [31:0] IO_control,

    В описании модуля mfp_ahb_gpio_slave

     .IO_Sonar	 ( IO_Sonar ),  .IO_control       ( IO_control)

  • В файле mfp_ahb_gpio_slave.v:
     input [15:0]IO_Sonar,  output reg[31:0]IO_control,

    в предпоследнем always по! HRESETn

     IO_control      <=32'b0;

    И в case (write_ionum)

     `MFP_CONTROL_IONUM       : IO_control      <=HWDATA;

    В последнем always в case (read_ionum)

    `MFP_SONAR_SENSOR_IONUM  : HRDATA = { 16'b0, IO_Sonar };

В файле mfp_ahb_lite_matrix_config.vh который находится в папке C:\github\mipsfpga-plus
Добавляем следующие строчки:

`define MFP_SONAR_SENSOR_IONUM      4'h6 `define MFP_CONTROL_IONUM           4'h9  `define MFP_SONAR_SENSOR_ADDR     32'h1f800018 `define MFP_CONTROL_ADDR          32'h1f800024

Собственно это и есть адреса по которым будут доступны регистры.

Исходники модулей, и измененные файлы доступны здесь:
github.com/Denis-Kingit/UltraSonicToMIPSfpga

Далее компилируем проект и прошиваем плату. Подключаем датчик, преобразователь, пьезодинамик:
Пин GND преобразователя к GPIO_1[26], пин TX к GPIO_1[31].
Пьезодинамик к GPIO_0[34], GPIO_0[35].
Пин GND датчика к GPIO_0[3], VCC – GPIO_0[1], TX – GPIO_0[7].
Получается что-то вроде:

Программная часть

Копируем содержимое папки C:\github\mipsfpga-plus\programs\01_light_sensor или попросту работаем в ней.
Добавим в файл mfp_memory_mapped_registers.h адреса регистров:

#define MFP_SONAR_SENSOR_ADDR   0xBF800018 #define MFP_CONTROL_ADDR        0xBF800024  #define MFP_SONAR_SENSOR        (* (volatile unsigned *) MFP_SONAR_SENSOR_ADDR  ) #define MFP_CONTROL	        (* (volatile unsigned *) MFP_CONTROL_ADDR  ) 

Теперь напишем программу, в которой будем считывать значения с регистра и выводить на семисегментные индикаторы. И в зависимости от считаного значения управляем звуковым сигналом. Изменим main.c:

Программа
#include "mfp_memory_mapped_registers.h"  int main () {     MFP_CONTROL = 1;     for (;;)     {         MFP_7_SEGMENT_HEX = MFP_SONAR_SENSOR; 	  if(MFP_SONAR_SENSOR<0x10) 		MFP_CONTROL = 1; 	  else if (MFP_SONAR_SENSOR<0x12) 		MFP_CONTROL = 3; 	  else if (MFP_SONAR_SENSOR<0x14) 		MFP_CONTROL = 5; 	  else if (MFP_SONAR_SENSOR<0x16) 		MFP_CONTROL = 7; 	  else 		MFP_CONTROL = 0;     }      return 0; }

Компилируем запустив скрипт

 02_compile_and_link

Генерируем motorola_s_record файл

 08_generate_motorola_s_record_file

Проверяем к какому СОМ порту подключен USB UART преобразователь

 11_check_which_com_port_is_used

Изменяем файл 12_upload_to_the_board_using_uart

set a=7  mode com%a% baud=115200 parity=n data=8 stop=1 to=off xon=off odsr=off octs=off dtr=off rts=off idsr=off type program.rec >\.\COM%a%

где а – номер СОМ порта, к которому подключен USB UART преобразователь.
И наконец загружаем программу

 12_upload_to_the_board_using_uart

Теперь подключим Ultrasonic HC-SR04

Идея подключения такая же, отображаем данные с датчика в регистры, подключенные к шине.

Для измерения расстояния необходимо подать импульс длительностью 10мкс на сигнальный пин Trig, после чего ультразвуковой модуль будет излучать восемь пачек ультразвукового сигнала с частотой 40кГц и обнаруживать эхо.

Измеренное расстояние до объекта пропорционально ширине эха, которое кодируется длительностью электрического сигнала на выходе датчика (Echo). Рекомендованный период между измерениями не менее 50мс. Для того что бы рассчитать расстояние необходимо длительность импульса (эха) в микросекундах разделить на 58 для расстояния в сантиметрах или на 148 для расстояния в дюймах. Если никаких препятствий не обнаружено, то на выходе будет сигнал с длительностью 38мс [2].

Модуль Sonic
module sonic(clk,trig,reset_n,en,echo,out); input clk,echo,reset_n,en; output reg trig; output reg[23:0]out;  reg [23:0]count; reg [23:0]countp;  always@(posedge clk) if(~reset_n) begin  countp<=24'b0;  count<=24'b0; end else   if(en) begin 	if(countp==0) 	 trig<=1'b1; 	if(echo) 		count<=count+1'b1;	 	if(countp==500) 		trig<=1'b0; 	if(countp==2500000) 		begin 			if (count>1800000)			 				out<=24'hfff; 			else 				out<=count/2900; 			countp<=24'b0; 			count<=24'b0; 		end 	countp<=countp+1'b1; end endmodule	

С периодом 2500000 тактов (50мс) создаем импульс на выходе trig длительностью 500 тактов (10мкс), считаем длительность эха, делим на 2900 (на 50 для перевода в микросекунды и на 58 для перевода в сантиметры) и записываем результат в регистр (для то что бы не создавать дополнительный делитель можно переводить программно), если длительность импульса больше 36мс записываем 0хFFF, что будет означать что препятствий не обнаружено.

Подключим модуль в файле верхнего уровня проекта(de0_cv.v).

wire [23:0] usonic; sonic sonica ( .clk		( CLOCK_50	), .trig		( GPIO_0[33]	), .reset_n	( RESET_N	), .en		( control[3]	), .echo		( GPIO_0[32]	), .out		( usonic	) );

Аналогичным образом изменяем файлы: mfp_ahb_gpio_slave.v, mfp_ahb_lite_matrix.v, mfp_ahb_lite_matrix_with_loader.v, mfp_ahb_lite_matrix_config.vh, mfp_system.v в папке C:\github\mipsfpga-plus.

Для подключения датчика понадобится источник питания на 5В, пин trig подключаем к GPIO_0[33], так как датчик работает от 5В, пин echo необходимо подключить через делитель напряжения к GPIO_0[32], соединяем общий провод источника, датчика и платы.

Пишем программу:

Программа
#include "mfp_memory_mapped_registers.h"  int main () {     int k = 0;     for (;;)     {         //MFP_RED_LEDS      = MFP_SONICR_SENSOR >> 4; 	  k=MFP_SONIC_SENSOR/58/50;         MFP_7_SEGMENT_HEX = k; 	  if(k<0x10) 		MFP_CONTROL = 1; 	  else if (k<0x12) 		MFP_CONTROL = 3; 	  else if (k<0x14) 		MFP_CONTROL = 5; 	  else if (k<0x16) 		MFP_CONTROL = 7; 	  else 		MFP_CONTROL = 0;     }      return 0; }

Считываем значения с регистра, в зависимости от полученного значения управляем длительностью звука, выводим значение расстояния на семисегментные индикаторы.

Так же необходимо добавить новый адрес в файл mfp_memory_mapped_registers.h

#define MFP_SONIC_SENSOR_ADDR   0xBF800020  #define MFP_SONIC_SENSOR        (* (volatile unsigned *) MFP_SONIC_SENSOR_ADDR  )

Описанным выше способом вы можете подключить ваши собственные модули, и управлять ими программно.

[1] LV-MaxSonar – maxbotix.com/documents/LV-MaxSonar-EZ_Datasheet.pdf
[2] Ultrasonic HC SR04 – robocraft.ru/blog/electronics/772.html
Исходники MIPSfpga-plus github.com/MIPSfpga/mipsfpga-plus
Codescape – Codescape
Инструкция по скачиванию mipsfpga – Инструкция
Исходники модулей, программ и измененных файлов:
github.com/Denis-Kingit/UltraSonicToMIPSfpga
Просто полезная книжка – Дэвид Харрис и Сара Харрис «Цифровая схемотехника и архитектура компьютера»
ссылка на оригинал статьи https://habrahabr.ru/post/316770/

Переходим на Swift 3 с помощью миграционного «робота» в Xcode 8.1 и 8.2

Уже известно, что Xcode 8.2 будет последним релизом, который поддерживает переходную версию Swift 2.3. Поэтому нужно срочно подумать о миграции на Swift 3.
Я хочу поделиться некоторым опытом такой миграции на примере приложений, связанных со стэнфордским курсом «Developing iOS 9 Apps with Swift», как демонстрационных (их 12), так и полученных в результате выполнения Заданий этого обучающего курса (их 6 с вариантами). Они все разной сложности, но там есть и рисование, и многопоточность, и показ изображений с помощью ScrollView, и работа с сервером Twitter, и база данных Core Data, и работа с облачным сервисом Cloud Kit, и карты Map Kit. И все это было написано на Swift 2.2 (stanford.edu), а мне было необходимо перевести все приложения на Swift 3. Конспект лекций стэнфордского курса на русском языке можно найти на сайте «О стэнфордских лекциях», а код — для Swift 2.3 на Github и для Swift 3 на Github.

Если вы решили мигрировать на Swift 3, то в Xcode 8 вам нужно запустить инструмент миграции (своебразного «робота») c помощью меню Edit->Convert->to Current Swift Syntax:

Далее вам предлагают карту различий между исходным кодом Swift 2 и кодом Swift 3, который сгенерировал этот «робот»:

Надо сказать, что миграционный «робот» в Xcode 8.1 и Xcode 8.2 работает превосходно по сравнению с начальной версией в Xcode 8.0, с которой мне пришлось начинать. Новый миграционный «робот» — изобретательный и очень разумный. На примере этой карты различий можно прекрасно изучать, какие изменения претерпели те или иные синтаксические конструкции в Swift 3. Миграционный «робот» делает очень большую работу по замене имен, сигнатуры методов и свойств, превращая, если это необходимо, ранее обычные свойства в Generic (например, NSFetchRequest, который не является Generic в Swift 2, но является таковым в Swift 3). Он может заменять новым кодом целые «паттерны», например, синглтон, если он был выполнен старыми средствами с помощью dispatch_once(&onceToken).
Ниже я покажу примеры этого. Миграционный «робот» действует по принципу «не навреди» и где только можно старается поддержать работоспособность имеющегося кода, даже вставляя дополнительный код. Вам следует очень внимательно посмотреть эти изменения и включить в список те места, код которых вам непонятен или кажется неэффективным и менее читаемым. Назовем это списком заданий для уточнения кода.

Если вы согласны с предложенными «роботом» преобразованиями, то вы их сохраняете и работаете дальше. Но, как и ожидалось, миграционный «робот» делает только часть работы для получения компилируемого кода в Swift 3. В приложениях остается 2-3 ошибки и 3-4 предупреждения. Поэтому вашим следующим шагом будет открытие навигатора «ошибок и предупреждений» (если они есть) и исследование их все одного за другим:

Для большинства ошибок и предупреждений предлагаются способы решения, и, в основном, это правильные решения:

Нам нужно сделать «кастинг типа» для переменной json, которая в Swift 3 представлена «роботом» как Any, хотя мы работаем с ней как с ссылочной (reference) переменной. В результате получаем:

Но иногда приходится исправлять ошибки.
Сразу после работы миграционного «робота» мы имеем ошибку при инициализации «параллельной» очереди (более подробно этот случай рассматривается ниже):

Вместо двух строк с ошибкой добавляем одну строку с правильным кодом:

Иногда вам предлагается несколько вариантов решения проблемы, и вы можете выбрать любой:

Нам сообщается, что неявно произойдет принудительное преобразование String? в Any. Это можно исправить тремя способами и тем самым убрать это предупреждение:

  1. предоставить значение по умолчанию,
  2. принудительно «развернуть» Optional значение,
  3. осуществить явный «кастинг» в Any с помощью кода as Any.

Мы предпочтем первый вариант и будем использовать пустую строку " ", если выражение равно nil:

Вообще миграция — это прекрасный повод для того, чтобы более широко взглянуть на свой код и, возможно, улучшить его.

В результате работы со списком ошибок и предупреждений вам удалось откомпилировать приложение и запустить тестовый пример. Это очень важный этап миграции.
Теперь вы можете сфокусироваться на списке заданий на уточнение кода, который вы составили при просмотре карты различий между двумя версиями: Swift 2 и Swift 3. Весь этот код технически корректен, но он может быть либо избыточным, либо неэффективным, либо приводить к ошибкам выполнения. Некоторые из этих ситуаций имеют общий характер, а некоторые — сильно зависят от специфики вашего приложения.
Я поделюсь некоторыми из них, с которыми мне пришлось столкнутся при миграции приложений курса «Developing iOS 9 Apps with Swift».

1. Нужно вернуть уровень доступа fileprivate обратно в private.

В процессе миграции на Swift 3 все уровни доступа private заменяются на новый уровень доступа fileprivate, потому что private в Swift 2 имел смысл именно fileprvate.

Миграционный «робот» действует по принципу «не навреди», поэтому он заменил все старые private на новые fileprivate, то есть расширил область доступа private переменных и методов.

В большинстве случаев это излишняя предосторожность, и нам вовсе не нужен уровень доступа fileprivate, но вы должны решить это самостоятельно в своей команде разработчиков и исправить в ручном режиме.

Если вы разрабатываете framework, то миграционный «робот» в Swift 3 заменит все уровни доступа public, которые были в Swift 2, на новый уровень доступа open. Это касается только классов.

В Swift 3:

  • open класс доступен и может иметь subclasses за пределами модуля, в котором он определен. Свойства и методы open класса доступны и могут быть переопределены (overridable) за пределами модуля, в котором определен класс.
  • public класс доступен, но не может иметь subclasses за пределами модуля, в котором он определен. Свойства и методы public класса доступны, но не могут быть предопределены (overridable) за пределами модуля, в котором определен класс.

Таким образом, уровень доступа open — это то, что было public в предыдущих версиях Swift, а уровень доступа public более ограничен. Крис Латтнер сказал в SE-0177: Allow distinguishing between public access and public overridability, что в Swift 3 уровень доступа open просто более public, чем public. Еще можно посмотреть SE-0025 Scoped Access Level.

При миграции frameworks в Swift 3 мы не будем возвращать уровень доступа open назад в public. Здесь нас все устраивает.

Вообще иерархия уровней доступа в Swift 3 так располагается в порядке убывания:

open -> public -> internal -> fileprivate -> private

2. Вы не можете сравнивать Optional значения в Swift 3.

При автоматической миграции с Swift 2 на Swift 3 иногда перед некоторыми классами появляется код:

Дело в том, что в Swift 2 можно было сравнивать Optional значения, например, таким образом:

или так:

В Swift 3 такую возможность убрали (SE-0121 – Remove Optional Comparison Operators) и для сохранения работоспособности такого кода в Swift 3 миграционный «робот» добавляет вышеприведенный код, что, конечно, удобно на начальном этапе перехода на Swift 3, но некрасиво, так как если у вас встречается сравнение Optional значений в нескольких расположенных в отдельных файлах классах, то вышеприведенный код добавиться многократно. Этот код нужно удалить, сразу обозначится проблема, и решать проблему нужно на месте. Вначале избавляемся от Optional с помощью синтаксической конструкции if let, а затем проводим необходимое сравнение. Например, так:

или так:

3. Swift 3 не обеспечивает автоматической совместимости (bridging) чисел с NSNumber.

В Swift 2 многие типы при необходимости автоматически совмещались («bridging«) с экземплярами некоторых subclasses NSObject, например, String в NSString, или Int, Float, … в NSNumber. В Swift 3 вам придется делать это преобразование явно (SE -0072 Fully eliminate implicit bridging conversions from Swift). Например, в Swift 2 мы имели код для преобразования числа в строку:

В Swift 3 после миграционного «робота» мы получим ошибку:

От нас требуют явного преобразования Double в NSNumber, и мы можем использовать два способа преобразования — с помощью оператора as:

или с помощью инициализатора NSNumber:

4. «Робот» не умеет преобразовывать параллельные очереди, но прекрасно работает с dispatch_once

Например, обычный «паттерн» асинхронного выполнения кода на параллельной очереди QOS_CLASS_USER_INITIATED с последующим переходом на main queue для отображения данных на UI на Swift 2 выглядит следующим образом:

Миграционный робот" преобразует этот код в код с ошибкой и предлагает функцию global(priority: qos), которая будет упразднена в iOS 10:

Для того, чтобы убрать эту ошибку, нам нужно использовать другую функцию — global (qos: .userInitiated):

Зато миграционный «робот» прекрасно справляется с dispatch_once, которая упразднена в Swift 3, и ее следует заменить либо глобальной, либо статической переменной или константой.
Вот как выглядит код для однократной инициализации фоновой очереди при выборке данных с сервера Flickr.com в Swift 2:

А это код в Swift 3 после работы миграционного «робота»:

Вы видите, что «робот» вынул внутренность синглтона и оформил ее в виде lazy переменной __once, которая представлена как выполняемое замыкание, при это нас предупреждают, что переменная onceToken не используется. Она действительно больше не нужна, и мы убираем эту строку:

5. Будьте очень внимательны с заменой методов типа …inPlace, при переходе на Swift 3.

Swift 3 возвращается к соглашению о наименовании методов и функций, которое было в Swift 1, то есть функции и методы именуются в зависимости от того, создают ли они «побочный эффект». И это замечательно. Давайте приведем пару примеров.

Вначале рассмотрим методы не имеющие «побочного эффекта», они, как правило, именуются Существительными. Например,

x.distance (to: y)
x = y.union(z)

Если функции и методы имеют «побочный эффект», то они, как правило, именуются императивным Глаголом в повелительном наклонении. Если я хочу, чтобы массив X был отсортирован, то я скажу: «X отсортируй (sort) сам себя или X добавь (append) к себе Y»:

x.sort ()
x.append(y)
y.formUnion(z)

Таким образом Swift 3 группирует методы по двум категориям: методы, которые производят действие по месту — думайте о них как о Глаголах — и методы, которые возвращают результат выполнения определенного действия, не затрагивая исходный объект — думайте о них как о Существительных.
Если НЕТ окончания «ed», то все происходит «по месту»: sort (), reverse (), enumerate (). Это Глаголы. Каждый раз, когда Swift 3 модифицирует метод добавлением окончания «ed» или «ing»: sorted (), reversed (), enumerated (), то мы имеем возвращаемое значение. Это Существительные.
Эти довольно невинные правила вызывают путаницу, если речь заходит об изменении методов сортировки при переходе от Swift 2 к Swift 3. Дело в том, что в Swift 2 все функции и методы, которые работают «по месту», содержат в своем названии слово «InPlace», поэтому для сортировки по месту используется функция sortInPlace (), а функция sort () в Swift 2 возвращает отсортированный массив. В Swift 3, как видно из вышеприведенных примеров, sort () переименован в sorted (), а sortInPlace () в sort ().
В результате метод sort () имеет разную семантику в Swift 2 и в Swift 3. Но это нестрашно, потому что если и в Swift 2, и в Swift 3 имеется пара функций ( как с побочным эффектом, так и без него), то миграционный «робот» блестяще осуществит замену одного имени другим:

А что, если в Swift 2 были две функции, а в Swift 3 осталась одна? Например, в Swift 2 были функции insetInPlace и insetBy, а в Swift 3 осталась, по какой-то причине, одна — insetBy? Миграционный «робот» нам в этом случае не поможет — он оставит старое название функции — insetInPlace — которое, конечно, даст ошибку, и нам придется исправлять ее вручную.

Все методы в Swift 2 с присутствием «inPlace» в имени требуют особого внимания при переходе на Swift 3.

Я сама попалась на этом вроде бы невинном изменении. Рассмотрим простейший метод one(), который увеличивает размер прямоугольника bbox до тех пор, пока не «поглотит» некий другой прямоугольник rect. Этот сильно упрощенный пример имеет реальный прототип, а именно класс AxesDrawer, который был предоставлен в стэнфордском курсе для рисования осей графика в Задании 3. Именно там встречается случай, представленный ниже и с ним пришлось иметь дело при переводе класса AxesDrawer из Swift 2.3 в Swift 3.

В Swift 2 я могу использовать метод insetInPlace для прямоугольников CGRect, который будет увеличивать размер прямоугольника на dx по оси X и на dy по оси Y:

Здесь не требуется использовать возвращаемое значение метода insetInPlace, потому что прямоугольник изменяется «по месту».

Если мы используем миграционный «робот» для перехода на Swift 3, то он оставит метод insetInPlace неизменным, так как аналога ему в Swift 3 нет, и мы получим ошибку:

В Swift 3 есть только метод insetBy, применяем его, ошибка исчезает, и нам предлагают изменить переменную var bbox на константу let bbox:

что мы и делаем:

Вы видите, что нет никаких предупреждений, никаких ошибок, а мы ведь создали «вечный» цикл, потому что новый метод insetBy не изменяет прямоугольник «по месту», а возвращает измененное значение, которое мы не используем в цикле while, но об этом тоже почему-то нет сообщения, так что создалась ОЧЕНЬ ОПАСНАЯ ситуация, когда мы «зациклили» навсегда наш код.

Мы должны снова присвоить bbox, возвращаемое методом insetBy значение:

Естественно, нам предлагают обратно вернуться от константы let bbox к переменной var bbox, и мы это делаем:

Теперь код работает правильно.
Так что будьте очень внимательны с заменой методов …inPlace при переходе на Swift 3.

6. В Swift 3 запрос NSFetchRequest <NSFetchRequestResult> к базе данных Core Data стал Generic

Но работоспособность класса CoreDataTableViewController, предоставленного стэнфордским университетом для работы с данными Core Data в таблице, обеспечивается автоматически при использовании миграционного инструмента.
Давайте рассмотрим, как это получается.

Если вы работаете с фреймворком Core Data, то следует обратить внимание на то, что запрос к базе данных, который в Swift 2 был NSFetchRequest, в Swift 3 стал Generic NSFetchRequest <NSFetchRequestResult>, а следовательно, стал Generic и класс NSFetchResultsController<NSFetchRequestResult>. В Swift 3 они стали зависеть от выбираемого результата, который должен реализовать протокол NSFetchRequestResult:

К счастью, объекты NSManagedObject базы данных Core Data автоматически выполняют протокол NSFetchRequestResult и мы «законно» можем рассматривать их в качестве результата запроса.

В Swift 2 запрос и его выполнение выглядят так:

В Swift 3 мы можем указать в запросе тип получаемого результата (в нашем случае Photo), и тем самым избежать дополнительного «кастинга типа»:

Действительно, если мы посмотрим на тип результата выборки results в Swift 3, то это будет [Photo], что нам позволит извлечь атрибут unique объекта базы данных Photo:

Однако, если бы мы использовали миграционный «робот» для перехода на Swift 3, то мы получили бы код, в котором результат выборки results определяется только тем, что он должен выполнять протокол NSFetchRequestResult:

Поэтому «роботу» пришлось применить «кастинг типа» as ? [Photo] для извлечения атрибута unique объекта базы данных Photo. Мы видим, что миграционный «робот» опять пытается нам «подсунуть» более обобщенное решение, вполне работоспособное, но менее эффективное и менее «читабельное», чем приведенный выше «ручной» вариант. Поэтому после работы миграционного «робота» нам придется править код вручную.

Но есть одно место в приложениях, связанных с Core Data, где миграционный «робот», работая так, как показано выше, предлагает гениальный код в Swift 3. Это класс NSFetchResultsController, который в Swift 3 также, как и запрос NSFetchRequest стал Generic, то есть NSFetchResultsController<NSFetchRequestResult>. В результате возникли некоторые трудности при использовании в Swift 3 фантастически удобного класса CoreDataTableViewController, который разработан в Стэнфорде.

Вначале очень кратко напомню о том, откуда появился класс CoreDataTableViewController. Когда у вас огромное количество информации в базе данных, то прекрасным средством показа этой информации является Table View. В 99% случаев либо Table View, либо Collection View используются для показа содержимого больших баз данных. И это настолько распространено, что Apple обеспечила нас в iOS прекрасным классом NSFetchedResultsController, который “подвязывает” запрос NSFetchRequest к таблице UITableView.
И не только “подвязывает” лишь однажды, а эта “подвязка” действует постоянно и, если в базе данных каким-то образом происходят изменения, NSFetchRequest возвращает новые результаты и таблица обновляется. Так что база данных может меняться “за сценой”, но таблица UITableView всегда остается в синхронизированном с ней состоянии.
NSFetchResultsController обеспечивает нас методами протоколов UITableViewDataSource и UITableViewDelegate, такими, как numberOfSectionsInTableView, numberOfRowsInSections и т.д. Единственный метод, который он не реализует, — это cellForRowAt. Вам самим придется реализовать его, потому что для реализации метода cellForRowAt нужно знать пользовательский UI для ячейки таблицы, а вы — единственный, кто знает, какие данные и как они размещаются на экране. Но что касается других методов протокола UITableViewDataSource, даже таких, как sectionHeaders и всего остального, NSFetchedResultsController берет все на себя.

Как работать с NSFetchResultsController?

От вас потребуется только создать запрос request, настроить его предикат и сортировку, а выводом данных в таблицу займется NSFetchResultsController.
NSFetchResultsController также наблюдает за всеми изменениями, происходящими в базе данных, и синхронизирует их с Table View.
Способ, каким она это делает, связан с делегатом NSFetchResultsControllerDelegate, методы которого вам предлагается без изменения скопировать из документации в ваш класс.

«Ну вот, я думал, что настроить NSFetchResultsController — это просто, а тут выясняется, что я должен реализовать методы делегата NSFetchResultsControllerDelegate?» — подумаете вы.
Но вам повезло, всю эту работу проделали за вас и предоставили в ваше распоряжение замечательный класс с именем CoreDataTableViewController.
При этом был не только скопировал весь необходимый код из документации по NSFetchResultsController, но и переписан с Objective-C на Swift.
Теперь, для того, чтобы ваш UITableViewController унаследовал всю функциональность NSFetchResultsController, вам достаточно сделать CoreDataTableViewController вашим superclass и определить public var с именем fetchedResultsController. Вы устанавливаете эту переменную, и CoreDataTableViewController будет использовать ее для ответа на все вопросы UITableViewDataSource, а также делегата NSFetchedResultsController, который будут отслеживать изменение базы данных.
В итоге вам всего лишь нужно:

  1. установить переменную var fetchedResultsController и
  2. реализовать метод cellForRowAt.

В классе, наследующим от CoreDataTableViewController, cоздаем NSFetchResultsController с помощью инициализатора, включающего в качестве аргумента запрос request, а затем присваиваем его переменной var с именем fetchedResultsController. Как только вы это сделаете, таблица cо списком фотографий начнет автоматически обновляться (Swift 2):

Конечно, реализуем метод cellForRowAtIndexPath (Swift 2):

Получаем список фотографий с сервера Flickr.com:

Все очень здорово и просто в Swift 2, но в Swift 3 запрос NSFetchRequest<NSFetchRequestResult> стал Generic, а следовательно, стал Generic и класс NSFetchResultsController<NSFetchRequestResult>.
Переменная public var с именем fetchedResultsController, с которой мы работаем в CoreDataTableViewController, тоже стала Generic в Swift 3 после применения миграционного «робота»:

По идее и класс CoreDataTableViewController нужно сделать Generic, но мы этого делать не будем, потому что его subclasses, например, такие, как приведенный выше PhotosCDTVC, испольуются на storyboard, а на storyboard не работают Generic классы.
Как же нам быть? Класс CoreDataTableViewController чрезвычайно удобный и позволяет избежать дублирования кода во всех Table View, работающих c Core Data?

Тут нам на помощь приходит миграционный «робот». Посмотрите, как он преобразовал класс PhotosCDTVC в части определения переменной с именем fetchedResultsController, в которой результат выборки в запросе определяется только тем, что он должен выполнять протокол NSFetchRequestResult (Swift 3):

А это как раз то, что требует переменная с именем fetchedResultsController в нашем суперклассе CoreDataTableViewController, то есть фактически «робот» выполнил «кастинг типа» ВВЕРХ (upcast) нашего результата выборки объекта базы данных Photo до NSFetchRequestResult. Понятно, что мы получим результат выборки типа NSFetchRequestResult, поэтому когда приходит время работать с реальным объектом Photo в методе cellForRowAt миграционный «робот» выполняет обратную операцию — «кастинг типа» ВНИЗ (downcast) — с помощью оператора as? (Swift 3):

Так что в случае с классом CoreDataTableViewController миграционный «робот» сработал идеально. Вам ничего не нужно изменять или дополнять.

7. Swift 3 расширил использование синтаксиса #selector, аргументами могут быть getter: и setter: для Objective-C свойств.

Когда вы определяете в Swift 3 селектор #selector, относящийся к Objective-C свойствам, то необходимо указать, имеете ли вы ввиду setter или getter.

Так получилось, что в одном из своих приложений на Swift, работающих с Core Data, я использовала в качестве public API переменную var coreDataStack:

Эту переменную я устанавливаю в AppDelegate не совсем обычным образом — через Objective-C setter setCoreDataStack для Swift свойства с именем coreDataStack. Этот способ я подсмотрела на одном из видео на сайте raywenderlich.com:

Мне было любопытно, как можно установить селектор на метод setCoreDataStack, которого явно нет в приложении. Этот код так и остался, пока я не решила перейти на Swift 3. Какого же было мое удивление, когда я обнаружила, как деликатно обошелся с этим кодом миграционный «робот» — он использовал синтаксическую конструкцию #selector с незнакомым для меня аргументом setter:

Мне захотелось больше узнать о #selector и я нашла замечательную статью «Hannibal #selector».

8. В Swift 3 вы получите предупреждение, если не будете использовать возвращаемое функцией не Void значение.

В Swift 2 при вызове функции необязательно было использовать возвращаемое функцией значение, даже если это значение не Void. Никакого предупреждения от компилятора в этом случае не поступало. Если вы хотите, чтобы пользователь получал такое предупреждение от компилятора, то вам нужно было специально разместить предложение @warn_unused_result перед декларированием этой функции. Это касалось, в основном, методов, которые меняют структуру данных. Например, sortInPlace.

В Swift 3 ситуация поменялась на противоположную. Теперь всегда, когда вы не используете любую функцию с возвращаемым значением, вы будете получать предупреждение. Для того, чтобы отменить в Swift 3 появление такого предупреждения достаточно разместить предложение @discardableResult перед декларацией функции.

Например, в Swift 2 мы могли использовать метод без получения возвращаемого значения:

Но после применения миграционного «робота» вы получите в этом коде предупреждение:

которое сообщает вам, что возвращаемое значение [UIViewController]? не используется. Если вы хотите убрать это предупреждение, то нужно дать понять компилятору ЯВНО, что вы не интересуетесь возвращаемым значение, с помощью символа _ (подчеркивания):

ВЫВОДЫ.

Перевод кода из Swift 2 на Swift 3 — очень увлекательное занятие. Можно в качестве исходных файлов использовать те, которые указаны в начале поста, а можно и более ранние, написанные. например, на Swift 2.0. Так что используйте миграционный «робот» в Xcode 8.1 и 8.2 для расширения своих знаний о Swift 3. Если вы хотите использовать в вашем приложении, написанном на Swift 3, какие-то куски кода, написанного на Swift 2, то также удобно использовать миграционный «робот». Надеюсь, он вас не подведет.

Ссылки: Yammer iOS App ported to Swift 3
ссылка на оригинал статьи https://habrahabr.ru/post/316320/