Используем Onion Omega2 для создания устройств с Linux и Wi-Fi
В последнее время передо мной часто встают задачи сделать то или иное DIY устройство с Wi-Fi. Я рассматривал разные варианты одноплатных компьютеров и микроконтроллеров, на основе которых это лучше делать, и в итоге моим фаворитом стала Onion Omega2.
Сейчас я расскажу, почему она мне так нравится, и покажу на примере, как ей пользоваться. Как обычно, это будет и в виде традиционной текстовой статьи, и посредством видео.
Видео
Статья
Почему Omega2
Для начала рассмотрим, какие вообще на рынке есть средства, чтобы легко добавить Wi-Fi в наше DIY устройство. Особенно если это устройство — часть умного дома.
Очень многие скорее всего сразу скажут — Raspberry Pi. И да, это полноценный одноплатный компьютер, весьма мощный и c видеовыходом. И он идеально подходит для каких-то сложных задач, которые требуют большие вычислительные мощности и возможность подключения телевизора/монитора. Например, на её основе можно сделать видеоплеер или игровую консоль, но для простых задач вроде управления устройствами умного дома она слишком громоздкая и дорогая. Это как стрелять из пушки по воробьям. Конечно, есть ещё модель Raspberry Pi Zero, которую позиционируют как маленькую и ультрадешёвую, но пока что они все ещё весьма дорогие, чтобы устанавливать их в каждый выключатель и чайник.
Другая крайность — ESP8266. Это очень популярный микроконтроллер с Wi-Fi, который стоит дешевле двух долларов. И это действительно очень достойное решение, которого будет достаточно для многих задач. Только вот зачастую наоборот слишком примитивное, ведь под него необходимо писать именно прошивки, Линукса там уже нет, а для работы с периферией и сетевым стеком используются отдельные библиотеки.
Полюбившаяся же мне Onion Omega2 является золотой серидиной. Это одноплатный компьютер на базе MIPS-процессора с Linux, Wi-Fi, Ethernet, UART, ШИМ, I2C, SPI, USB, и конечно же GPIO. Изначально производитель заявлял цену в $5, но со всеми дополнительными расходами и доставкой для конечного пользователя такая штука пока что стоит где-то 9–10 долларов, наверняка в будущем подешевеет. Есть версия чуть дороже, со слотом для SD-карты, но поверьте, встроенной памяти на 16 мегабайт хватит для большинства повседневных задач. Анонсирована ещё версия для поверхностного монтажа, которая скорее всего будет ещё дешевле, ещё меньше и иметь ещё больше выводов. Но я уже купил себе целую коробку обычных омег, ведь при такой цене можно уже смело втыкать Linux и Wi-Fi в каждый выключатель.
Как обычно, многие спросят меня — зачем? Почему меня вдруг не устраивает ультрадешёвая ESP8266, и как же так получилось, что я вдруг опустился до чего-то столь высокоуровневого?
Да дело банально в удобстве использования и обслуживания. Если говорить про умный дом, то это не просто управление утюгом через Интернет, это комплекс устройств, которые работают вместе в одной сети и реагируют на события друг друга. При этом программирование является неотъемлемой частью использования умного дома, ведь устройствам надо периодически объяснять, что в каком случае требуется делать. И Linux в этом плане сильно облегчает задачу, он берёт на себя всю головную боль с многозадачностью и выполнением заданий по расписанию, при этом Linux — огромная база уже привычного софта. Тут вам и полноценный веб-сервер, и Perl, и PHP, и Ruby, и различные сетевые утилиты, благодаря которым не нужно изобретать велосипед, и с помощью которых можно достаточно легко менять поведение устройства в реальном времени, без перекомпиляции. Да многие повседневные задачи можно вообще на bash-скриптах реализовать.
Недостатки Omega2
Не буду лукавить, недостатков у Omega2 по сравнению с классическими проводными решениями и микроконтроллерами тоже хватает.
Во-первых, это конечно же питание. Эта штука может потреблять до 500 миллиампер и при этом не хило так греться. И если весь мой старый умный дом питался от одного блока питания, то тут уже нужен отдельный блок на каждое устройство.
Во-вторых, Linux очень плохо справляется с задачами реального времени. Если вам требуется работать с сигналами длительностью в микросекунды, придётся писать модуль ядра, а то и вовсе подключать дополнительный микроконтроллер.
В-третьих, у Омеги нет АЦП, то есть никаких аналоговых входов, а это бывает весьма нужно при работе с аналоговыми датчиками. Эта проблема решается подключением внешнего АЦП или, опять же, подключением копеечного микроконтроллера, тем более под Linux существует софт для их прошивки, что полностью избавляет от необходимости использовать программатор.
Четвёртый недостаток свойственен скорее всем Wi-Fi-устройствам, а не только Омеге. Это отсутствие децентрализованности. Использование Wi-Fi подразумевает, что у всей системы есть одна слабая точка — Wi-Fi роутер, без него устройства теряют связь друг с другом. Но на самом деле абсолютно в любой конфигурации есть такое слабое звено. У меня вот раньше, как я уже говорил, всё питалось от одного блока питания. И весь умный дом умер, когда у меня сломался блок бесперебойного питания. И надо отметить, что Омега2 постоянно работает ещё и в качестве Wi-Fi точки доступа. Поэтому даже при полном отсутствии роутера всегда можно подключиться к устройству, например с телефона. К тому же в любом случае важно делать устройства с расчётом и на работу без сети.
Не знаю, до чего ещё докопаться, но наверное можно сказать про время загрузки. Omega2 достаточно долго загружается и выходит на связь. Это абсолютно неважно для устройств, которые работают круглосуточно, но может стать проблемой для приборов, которые включаются в розетку лишь иногда.
Мне заказали сделать устройство, которое должно просто автоматически открывать дверь подъезда при звонке в домофон, имея при этом возможность настраиваться удалённо, через Интернет. Дело в том, что заказчик периодически сдаёт свою свою квартиру через один сайт, находясь при этом в другом городе. И ему нужно, чтобы в день заселения человек мог попасть в подъезд, и там уже взять ключ из специального бокса. Попробуем сделать это на основе Omega2.
Задача для меня не совсем новая. Я уже делал домофон с автоответчиком, который умеет не только снимать трубку, но и отвечать записанными на SD карту сообщениями, плюс записывать на эту же SD карту сообщения от тех, кто приходил. По сути нужно просто упростить эту схему (не нужен автоответчик) и использовать Omega2 вместо ATMEGA64.
Принцип работы домофонных трубок очень прост. Когда трубка висит, её динамик включен в домофонную сеть напрямую, соответственно трубка имеет сопротивление около 50 Ом. Когда трубку снимают, её сопротивление возрастает где-то до килоома и немного меняется, когда мы говорим в микрофон, передавая таким образом звук. И наконец, когда мы нажимаем кнопку открытия двери, сопротивление трубки вырастает ещё сильнее.
Соответственно с аппаратной точки зрения нам нужно:
* Первое — определить момент, когда кто-то звонит в домофон. Это делается легко, только в этот момент в линии появляется напряжение. Чтобы определить наличие напряжения, можно использовать транзистор. Как только через его базу будет течь хотя бы мизерный ток, он откроется и замкнёт одну из ног омеги на землю;
* Второе — через некоторое время снять трубку, увеличив сопротивление устройства. Для этого можно использовать банально реле. Это громоздко, они щелкают, но очень надёжно. Сопротивление же лучше сделать подстраиваемым, ведь у разных производителей домофонов это значение может быть немного разным;
* Третье — спустя ещё какое-то время ещё сильнее увеличить сопротивление устройства, опять же можно сделать через реле.
Всё достаточно просто. Стоит не забыть добавить такие мелочи, как кнопка, пара светодиодов, чтобы отображать текущий режим, и пьезодинамик, чтобы издавать звуки.
Стоит обратить внимание, что не все выводы Omega2 можно использовать в режиме GPIO.
Её flash-память подключена через SPI, соответственно эти выводы можно использовать только для подключения SPI устройств. Если повесить туда что-либо ещё, оно скорее всего помешает Omega2 загрузиться. Помимо этого, выводы 1, 12 и 45 не должны быть подтянуты ни к земле, ни к питанию во время запуска устройства.
В итоге у меня получилась вот такая вот плата:
И вот такое устройство:
Подключаем питание, чтобы вдохнуть в него жизнь, и Омега сразу же начинает загружаться.
Вскоре можно будет увидеть новую Wi-Fi точку, которая называется Onion + последние четыре цифры MAC-адреса. Подключаемся к ней, пароль по умолчанию:»12345678».
Внутри этого интерфейса у Омеги по умолчанию IP адрес 192.168.3.1, подключаемся к нему по SSH, логинимся под root«ом, используя пароль «onioneer», и первым делом настраиваем подключение к Wi-Fi точке. Для этого там предустановлен скрипт «wifisetup».
Если всё сделали правильно, через ifconfig можно будет увидеть IP адрес, который выдал Омеге роутер. Теперь можно отключиться от точки доступа самой омеги и подключиться к ней уже по этому IP адресу, используя обычную сеть, ведь теперь она является частью моей домашней сети.
Снова логинимся по SSH и проверяем, что у Омеги теперь есть подключение к Интернету.
Первым делом следует обновить прошивку с помощью команды «oupgrade». Это особенно актуально в свете найденных недавно уязвимостей в протоколе Wi-Fi.
Весь софт устанавливается из репозитория с помощью «opkg». Веб-сервер там уже есть, мне понадобится ещё PHP:
opkg update
opkg install php7 php7-cgi php7-cli
Нужно не забыть настроить при этом веб-сервер, в Омеге используется uhttpd:
vi /etc/config/uhttpd
Дописываем в основную секцию:
list interpreter ".php=/usr/bin/php-cgi"
option index_page 'index.php'
Да, прошивка Omega2 сделана на основе прошивки OpenWRT, поэтому многие инструменты унаследованы оттуда же. Конфигурация редактируется и хранится с помощью UCI — Unified Configuration Interface. Это что-то вроде простенькой базы данных, которая оптимизирована сократить количество перезаписей flash-памяти. Для своих целей я буду использовать её же.
Что же касается управления периферией и GPIO, то это достаточно легко делать прямо из командной строки. На омеге уже предустановлено несколько утилит для этого.
Прежде всего, стоит обратить внимание на то, что многие выводы имеют несколько функций, для переключения между ними используется утилита «omega2-ctrl».
Менять же направление вывода и значение вывода можно утилитами «gpioctl» или более быстрой «fast-gpio». Также можно управлять ими через псевдофайлы в Linux, что является более универсальным и портируемым методом.
Код я решил писать прямо на bash-скриптах, это Linux всё-таки. Задача достаточно простая: если ряд условий выполняется, то ожидаем звонка в домофон и открываем дверь спустя заданный промежуток времени, реагируем на нажатия кнопки заданным в настройках образом, мигаем светодиодами, издаём звуки при необходимости…
Вот тут-то у меня внезапно и возникла проблема. Для генерации звука я решил использовать ШИМ. Однако, программный ШИМ, который предоставляют утилиты Омеги весьма нестабилен. Он хоть и работает на уровне ядра, но его тайминги сильно плавают, что отчётливо заметно на слух. Слишком заметно, так оставлять нельзя.
Однако, у Omega2 вроде как заявлен аппаратный ШИМ. Его можно увидеть в утилите для переключения режима работы пинов, он есть в документации на процессор, который используется в Омеге, но при этом нет никаких средств для работы с ним. Видимо, разработчики их ещё не сделали. Что ж, будем делать сами! В той же документации на процессор описаны регистры для работы с ШИМ.
Их много, местный ШИМ очень гибкий в настройке. Тут можно даже задать произвольные последовательности генерации волны.
В итоге я написал нативную программу на Си, которая работает напрямую с этими регистрами и генерирует волну заданной частоты и скважности, используя именно аппаратный ШИМ. Исходники этой утилиты я выложил на GitHub: github.com/ClusterM/omega2-pwm
Так что пользуйтесь, если кому-то нужно. Звук в итоге стал издаваться без дефектов.
Осталось только сделать веб-интерфейс, чтобы заказчик мог легко всё настраивать и управлять устройствам из любого браузера. Веб-технологии — это моя слабая сторона, тут я отстал от жизни лет на 20, так что тут будет тот ещё говнокод. Как я уже говорил, я не заморачиваюсь и использую PHP в сочетании с JavaScript. Дизайн я делать не умею, да и не нужно этот тут, поэтому я в наглую скопировал его с интерфейса Luci от OpenWRT.
Вот такая вот простенькая админка получилась. Во-первых, тут можно смотреть и добавлять интервалы, когда наш домофон будет автоматически открываться. На этой же странице можно импортировать расписание из «ical» файла. Да, забыл сразу сказать, что это было одно из требований заказчика. Дело в том, что на сайте, где этот человек сдаёт квартиру, можно экспортировать расписание или получить его по ссылке. В итоге заказчику не нужно будет даже вписывать его руками в настройках устройства, оно будет заполняться само с сайта, где он сдаёт квартиру. Конечно же нужно не забыть настроить периодическое выполнение этого скрипта через cron.
Ещё в админке можно менять различные настройки — издавать ли звуки, как быстро нужно открывать дверь, как реагировать на нажатие кнопки, ну и само собой менять пароль на админку.
На отдельной вкладке можно смотреть логи, где будут записываться все действия. Само собой есть вкладка и с настройками Wi-Fi. Тут можно посмотреть, какие поблизости есть точки доступа и подключиться к выбранной.
Подразумевается, что при первом включении устройства заказчик подключится к устройству, например, со смартфона, зайдёт в админку и настроит уже его подключение к роутеру.
Ещё я сделал в админке вкладку, где можно написать произвольный скрипт, который будет выполняться, когда кто-то звонит в домофон. Заказчик этого не просил, да и для рядового пользователя не особо нужно, но таким образом можно при звонке в домофон выполнить вообще любые действия. Например, особенно с помощью утилиты curl. Так, например, можно отправлять push-уведомления на телефон. Можно написать для этого свою программу для смартфона, но я предпочитаю использовать сервис pushover.net (не реклама). Для заказчика я уже написал скрипт-шаблон, ему осталось только подставить свои ключи, которые получаешь на сайте сервиса. Так он сможет почти мгновенно узнавать, если кто-то позвонил в домофон.
На этом этапе всё уже готово. Остаётся только напечатать корпус на 3D принтере.
Выглядит несколько кустарно, но свой функционал выполняет идеально.
Но на этом разработка не закончилась. Случилось то, чего я боялся больше всего. На моём-то домофоне я всё проверил, а вот на домофоне заказчика оно уже не заработало. Он там другой фирмы и видимо чуть-чуть иначе работает. Проблема была в том, что устройство думало, что кто-то звонит в домофон, когда этого на самом деле не происходило. При этом заказчик живёт далеко, приехать и посмотреть я не мог. Однако, я же говорил, что Linux сильно облегчает обслуживание устройства. Заказчик пробросил мне порт SSH на роутере, я подключился удалённо и разобрался, в чём дело. Просто в домофонной линии у него возникали кратковременные помехи, которые можно легко отфильтровать, доработав скрипт. Нужно реагировать только если сигнал в линии есть в течении некоторого времени. Здорово, что это можно вот так просто поправить. Только пришлось заставить заказчика побегать к подъезду для тестирования.
Заключение
Надеюсь, на этом простом примере я показал, чем удобна Omega2, и как Linux облегчает задачу при создании подобных устройств. Если статья вам понравится, я буду продолжать рассказывать о том, как применяю Omega2, и постараюсь делать это более подробно. У меня ещё много проектов с ней, как более простых, так и более сложных.