Говорят что лень — мать прогресса. В моём случае, так оно и было. Сейчас я живу в солнечной Индонезии, где по ночам люди освещaют свои дома для отпугивания воров (и призраков). Случилось так что моим поручением стало включение и выключение сего освещения. Каждое утро и вечер надо пройти вокруг дома и щёлкнуть всеми наружными выключателями. Особенно трудно не забыть об этом утром, поскольку включённые лампочки не заметны при дневном свете. После недельки таких хождений мне захотелось лучшей жизни. Я решил сделать дистанционный выключатель и автоматизировать управление светом. Таким образом, закладывая первые виртуальные кирпичи своего умного дома. Была только одна маленькая проблемка — я не имел ни малейшего представления как спроектировать электронику и развести плату.
На заглавном фото вы видите результат моих работ. Выключатель представляет из себя две вставки в стену. В одной располагается физический выключатель, а в другой его «мозг». Виртуальный выключатель работает в OpenHab2, запущенный в с свою очередь на RaspberryPi2.
Дизайн/Пожелания
Итак, с чего же все таки начать разработку такого устройства? Я хотел чтобы виртуальный выключатель работал вместе, а не вместо, физического, и чтобы выключение физического выключателя не отключало виртуальный. Здесь такую конструкцию любя называют «отельный выключатель».
А как быть с корпусом? Мой девайс ни в коем случае не должен быть «wall wart»-ом. Наоборот, он должен гладко сливаться с физическим выключателем не выдавая своего существования. Значит плата должна будет помещаться в одну из распостранённых стенных коробочек. Ниже, на фотографии показан экземпляр такой коробочки, она из линейки выключателей и розеток компании Panasonic. На её базе я разработал своё устройство.
Ок, а что про «умные» функции? Я хотел выключатель который знает включён ли он или нет. Не просто знал статус рэле, но действительно знал если ток течёт через систему. Также я хотел чтобы это состояние сохранялось долгосрочно, и например, при сбое в электросети свет не включался/выключлся внезапно, после восстановления питания.
Напоследок, я хотел красивую панель управления для виртуального выключателя. Мне требовалось хорошее решение для контроля умного дома, куда я мог бы подключиться. Я совсем не желал писать еще одно кул-приложение для смартфона, чёрт побери!
Первый Прототип
Итак, я хотел построить электронное устройство, но совсем не знал как это сделать. Я был знаком с микроконтроллерами, умел пользоваться мульти-митером и спаял пару нехилых бордов чужого дизайна. Но проектировать свою схему я никак не умел. Поэтому, сперва я решил собрать свой выключатель из готовых модулей. Вот что я насобирал:
Для понижения 220В в 5В я использовал заряжалку от телефона. Сразу берите хорошую заряжалку, например ту которая прилагалась к телефону при покупке. Не покупайте Китайский афтермаркет на базаре, они обычно кривые. Я взял свою от какого-то старого Самсунга.
Рэле я взял как кит («beefcake» kit из SparkFun-a). Оно было большое, с громким кликом и имело всю необходимую обвязку (транзистор, защитный диод, итд) чтобы орудовать им ногой микроконтроллера.
Для измерения тока я взял один из Allegro-вских ACS712 модулей на маленькой плате. Там была вся обвеска, нужно было только подключить питание и читать аналог выход.
Вышеперечисленное составило мой модуль питания. Для логической части я взял:
Dev-борду на PIC24F от Circuits@Home. Она была сделана для создания USB Host устройств, но мне от неё нужен был только гигантский PIC, который на ней стоял. Также, я взял PickIt3 программатор/дебагер для него. В аду есть зарезервированное место для того человека, который в первый раз осмелился назвать эту хрень дебагером.
Wifi модуль изначально был CC3000 на breakout board-е. Но ненадолго. CC3000 мог быть той самой рабочей лошадкой для интернет утюгов, но только до того как TI не взвинтила на него цены (от $10 до $30) и прекратила выдавать сэмплы. Как раз когда я собирался погрузиться в его изучение, вышел другой чип про который вы возможно слышали — ESP8266. Ультра-дешёвый wifi модуль управляемый странными AT командами.
АТ команды еще долго не давали мне покоя. Кого в здравом уме может потянуть на водворение столь странного синтаксиса? Потом я конечно понял, что эти АТ команды не изобретены Espressif-ом (компания выпускающая ESP8266), а были использованы потому что такие же АТ команды в том же исполнении были использованы ранее в других похожих продуктах, такими как например GSM модемы. А ещё ранее GSM модемов, ими пользовался кто-то еще, и так далее к самому первому dialup модему. Ожидалось что люди раньше писавшие под АТ команды смогут быстро подключить ESP8266. Только это был не я ;)
Софт для микроконтроллера.
Программирование — другое дело, это я могу! Используя мою компашку модулей я написал большинство прошивки для PIC-а. Я решил, несколько произвольно, что мой девайс будет доступен через JSON RPC поверх TCP. RPC (remote procedure call) показался мне наиболее логическим способом организовать связь между центральным сервером и моим устройством. Устройство будет открывать соединение с сервером, а сервер будет пользоваться установленным каналом для вызова методов «вкл», «выкл», «статус» и получать какие-то данные в ответ. А JSON я взял чтобы не придумывать свой синтаксис и парсер к нему.
Я нашел маленькую С либу для JSON парсинга — JSMN. Она легка в использовании, но в ней не было простых способов для проходов по JSON дереву. Без проблем, нужный функционал был легко добавлен. Поверх JSMN, я написал свой JSONRPC сервер. Модуль инициализируется массивом function pointer-ов и строковых имён функций (примерно как регистрируются JNI методы в Андроиде). Таким образом сервер знает какую функцию запустить когда встречает eё имя в JSONRPC запросе. При вызове происходит автоматическая проверка типа аргументов, проверка типа возврата будет добавлена в будущем. Взгляните, если вам интересно.
О, да, есть еще одна вещь которую стоит упомянуть прежде чем мы пойдём дальше. Каждый микроконтроллерный проект стоит начинать с хорошего UART консоля. Ну, вообще-то довольно просто послать пару байт по UART-у а потом покрутиться в цикле, ожидая ответа, ты это имел в виду? Нет, это плохой UART консоль. Хороший будет неблокирующим, использующим прерывания, кольцевые буферы и всё такое. К сожалению опен сорцного варианта я не нашел, и был вынужден портировать один из вендор-привязанных под свои нужды. Собираюсь написать свой, с нуля, и выпустить его, но руки все никак не доходят.
Также, нам нужен интерфейс к ESP8266. Я решил написать модуль который назвал 'at-socket'. Пользовательский интерфейс сокет-подобный: open/close/send/receive/joinap/quitap/etc, но под капотом эти функции выполняют последовательности правильных AT команд и возвращают бинарные статусы. Это было намного труднее чем может показаться. Сталкиваясь с AT командами впервой, я не знал есть ли какие-то устоявшиеся конвенции, и если авторы данной AT имплементации их придерживались. Например, не было сказано ничего про синхронизацию (возможно ли прочитать асинхронную АТ команду посреди синхронного вызова?). Контрольные слова иногда меняются в разных командах (пр. ERROR и FAIL), а иногда вообще используются одиночные, символы без EOL маркеров (пр. '>'), и поэтому нельзя вот так просто взять и читать построчно из буффера. Ещё не забываем парсить размер входящих данных из строки в инт. Вместе взяты, эти мелочи сильно мешаются. В конце концов, методом экспериментов, я получил нечто исправное, но вы наверное можете представить как код, написанный таким образом, выглядит изнутри. Поэтому вашему вниманию я его предлагать не буду. Возможно после того как я его перепишу зная главные подвохи, но не ранее. Мне одно не понятно — где все эти легаси АТ команд либы которые держат этот синтаксис на плаву?
Второй заход на железо/Делаем платы
До этого момента, я успешно компенсировал своё незнание электроники использованием готовых модулей, но теперь оно смотрело мне прямо в лицо. Альфа версия прошивки для микры была готова и рвалась на новое железо. Я понимал что изготовка плат займет время, поэтому хотел начать процесс как можно быстрее, а в это время ковырять центральный сервер умного дома.
Мои попытки заинтересовать друга-электроньщика не увенчались успехом. Я был один. Я решил что по крайней мере нарисую схему, в конце концов, у меня уже были все модули одиночки и к ним обычно прилагалась схема, или-же была в даташыте. Всё что от меня требовалось это объединить всё в одну большую схему, а с ней уже можно было грамотно спрашивать о помощи.
С помощью ютуба и поисковиков я научился использовать электронный CAD (начинал с Eagle-a, и да, он ужасен). По мере добавления каждого модуля в мой мастер чертёж, я просто не смог не задаться вопросами про то как он работает. До этого электронные схемы вводили меня в заблуждение. Они были большими и я даже не знал с какой стороны начинать на них смотреть. А тут, всё было элегантно разбито на маленькие кусочки и можно было задуматься над тем что даёт тот или иной резистор и конденсатор. Я задавал вопросы на stackoverflow и toster, и понемногу начал понимать что к чему — сurrent limiting resistors, pull ups, pull downs, filtering caps, protection diodes, voltage dividers и тд. А ещё я понял что для каждой микросхемы обычно есть примеры разводки в даташыте, и даже если не всё понятно, можно начинать использовать и задавать вопросы. Таким образом я даже осмелился добавить несколько вкусностей в свою большую схему которых не было в модулях. И наконец-то я понял какая она — минимальная обвязка для микропроцессора. На эту тему предлагаю вам отвлекательную историю.
Дайте я вам немного расскажу про Индонезийские электронные магазины. Это обычно полу-тёмная, тесная комната с открытой стеной на улицу и минимальными витринами. Ходовые товары это колонки и усилители для многочисленных мечетей и немного дешёвых Китайских LED-шных поделок которые местные любят крепить куда-нибудь на бампер своего автомобиля или мопеда. Вся электронная мелочь лежит в пыльных коробочках за прилавком с пожелтевшими наклейками. Даже и не думайте про каталог, говорите что вам нужно и мы проверим есть это у нас или нет. В тот вечер я зашёл на Digikey, ткнул в поисковую строку и тихо плакал. Однажды я увидел пару школьников покупающих транзисторы, светодиоды и еще какую-то мелочь. Я спросил у них, что они собирают, поскольку до этого я никогда не видел чтобы кто-то здесь интересовался сбором электроники. Они сказали мне что делают flip-flop. Внезапно у меня была надежда! Здесь все таки существуют те кого интересует электроника. Может быть я их найму когда они закончат школу, или устрою им хакатон, или… но не долго музыка играла. Оказалось что они собирали flip-flop для школьного задания, и примерно на этом вся электроника в школе начиналась и заканчивалась.
Итак, я был в одном из этих магазинов электроники с моим списком. На мой вопрос про керамические конденсаторы в ответ я получил мутный взгляд и хлопающие глаза. После 15 минут объяснений я вышел из магазина получив резистор на 10К, кристалл на 12MHz и пару 8nF конденсаторов к нему. Других керамических конденсаторов у них не было, и они не во что не хотели воспринимать мои описания нетравленой платы. Пока ты не выучишь ключевые слова на местном (нетравленная плата оказалась 'PCB polos') на тебя будут смотреть как на макаку сбежавшую из зоопарка.
Мои приключения с поиском деталей затянулись на пару недель пока мы не съездили в ближайший «мегаполис». В нём магазины были такие же как в деревне, но с немножко бОльшым выбором. Зная ключевые слова я смог быстро проверить наличие нужных товаров. Мне досталось керамических конденсаторов на 0.1uF, но не выше. Я также взял танталовый конденсатор (последний, пыльный) на 25uF, который позже оказался битым и испортил мой дев борд. У них также был PCB polos! Но только односторонний, чтобы жизнь малиной не казалась.
Через несколько дней я спаял свою плату, используя тонкий провод (который, в свою очередь, был извлечён из горелого трансформатора от паяльной станции) для дорожек.
Момент включения был разочарованием. Программатор не хотел распознавать чип. Причиной тому был битый танталовый конденсатор, но я этого еще не знал, и было непонятно если программатор сгорел или я неправильно собрал плату. Чтобы закончить историю, скажу вам что позже я пересобрал дев борду на макетной плате с гигантскими (по физическим размерам) thin film конденсаторами и все заработало. Программатор был жив.
Итак, где мы остановились? Ах, да — я дорисовал мастер схему и обдумывал следующий ход. Я не хотел заниматься разводкой платы сам. Это была бы моя первая плата и косяки были гарантированы. Вдобавок, модуль питания использовал 220В и косяки становились пожароопасны. Я сделал то что должен сделать любой человек в такой ситуации — я заправил заказ на фрилансим. Три исполнителя откликнулись, и так я познакомился с Данилом. Он прекрасно развёл модули питания и логики, и даже переманил меня на сторону Altium-a (Altium против Eagle это примерно как Photoshop против MSPaint).
Пока Данил трудился над платой я помогал рисованием посадочных площадок (footprints) и выбирал главные компоненты. Свои порывы «тоже порисовать» в Altium-e я удовлетворял повторением туториалов с ютуба и официальной документации, которая очень хороша. Мне понравился вот этот чувак. С моими новыми знаниями я мог разглядывать варианты плат от Данила, и давать полноценный фидбэк. Вообщем учите CAD, это не так сложно как кажется. Забегая вперёд вот какие получились платы:
Заполучив в трясущиеся ручки Gerber файлы, надо было найти место где их напечатать и закупить компоненты. Я знаю только два места где можно взять маленькую партию плат по низкой цене — oshpark и cheapdirtypcbs. Я выбрал oshpark, потому что мне очень нравится их веб интерфейс и я уже видел их продукт и он действительно добротный. Единственная проблема — они в Америке а я в Индонезии. А знаете что есть ещё бОльшая проблема? Заказать рассыпуху в Инденозию, [цензура]. Здесь нет местных оутлетов больших дистрибуторов как Digikey/Mouser/Element14/итд. Я подумывал заказать из оутлетов в близлежайших странах — у Mouser есть Малазийский сайт, а у Element14 Сингапурский. Счастливого выяснения цены за доставку. По-моему у Mouser на их Малазийском сайте было написано с тримя восклицательными знаками что — наконец-то они делают доставку в Индонезию!!! За низкую, низкую цену в $70. Ок. Идём дальше. В конце концов, я нашёл решиппера в Америке, и они получили все мои платы и компоненты и выслали мне их одной партией. Пересылка теперь стоила $23. Спустя месяц (или другой) посылка была у меня. Кто хочет открыть большой электронный магазин внутри Индонезии вместе со мной? (Серьёзно)
Прежде пройдя квест «Индиана Джонс и Паяльник с Переменной Температурой» (и даже не смейте меня спрашивать про жала правильной формы), я приступил к пайке. Несколько задом наперёд припаянных диодов спустя, у меня был источник питания. Было несколько багов (моих), расскажу только про один интересный/смешной. Модуль с микроконтроллером дался труднее. Оказалось что я нарисовал посадочную площадку для ESP8266 ровно в зеркальном отражении (facepalm). Повезло еще что он не сгорел после такого подключения. С помощью фена я его снял, и переставил лицом вниз. Сработало.
Следующее приключение было с линейным регулятором. Не знаю как я этого не углядел, но оказалось что мои 5В были крайним, низким значением для входа. Когда я подключал нагрузку (читай: включал ESP8266) 3.3В выход проседал до 2.7В, что вызывало brown out reset на PIC-e. Я тут-же заказал замену (MCP1825, рекомендую) на АлиЕкспрессе. АлиЕкспресс очень даже неплох для одиночных компонентов — цена примерно такая же как в Америке, бесплатная доставка при покупке штук эдаки десяти. Но в то же время я не представляю себя заказывающим весь BOM таким образом.
Последний баг в логическом модуле был неправильным выбором ног под UART. Я уже навострился пользоваться микрочиповскими remappable peripherals, но не заметил что многие из этих пинов годны только для входа. И как следовало ожидать оба пина для UART-a я выбрал именно такие. Ну ничего, починим. Я перерезал дорожки и проложил их «в обход» тоненьким проводом. Капля горячего клея для удержания, и все готово.
Оно запустилось! Я смог прогнать прошивку через все тесты, включая измерение тока. Я посылал JSONRCP команды вручную и получал ответы. Wifi и TCP работали. Вот как выглядит второй прототип:
Центральный сервер умного дома
Центральный сервер представляет из себя самый лакомный кусочек всей экосистемы умного дома. Контроль над ним даёт полный контроль над совместимостью устройств, можно всю метрику пускать через свой облачный сервис (а потом присылать рекламу на памперсы когда видно что одну из комнат перекрасили), интегрироваться с какой-нибудь Корпорацией Зла (для улучшения экспириенса конечно), или еще какую-то подлость. Так что, юные умнодомовцы — задумайтесь кого вы хотите поставить на эту роль. Надеюсь ваш ответ будет «самих себя», но в последнее время я даже не знаю что ожидать.
Я решил быстренько попробовать (установить и запустить) все решения для домашней автоматизации которые смог найти. Вот здесь есть неплохой список (в конце), но в последнее время такие проекты растут как грибы после дождя, поэтому он уже может оказаться не полным. Из тех которые я пробовал, мне не понравился ни один. Мои недовольства обычно попадали в одну из этих групп: полуживой статус проекта; похабная, недописанная документация; грубые нарушения безопасности (проект на базе локального сайта — директории с правами 777, принадлежащие пользователю под которым работает веб сервер, shell вызовы), привязки к облачным сервисам, и во всех случаях — отвратительный интерфейс. Я честно попытался всё установить и запустить, но заработало только где-то в половине случаев. Из работающей половины я остановился на OpenHab — у него наиболее подробная документация, активная разработка, довольно большое сообщество и открытый код. Мне так-же понравилось что он написан на Java. Из недостатков — замудренный код, уродливый интерфейс (сейчас намного лучше в OpenHab2), и нехватка места где можно задать вопросы. Сейчас в альфа стадии находится OpenHab2, и предлагает нам реорганизованный код (на много понятнее чем в первом) и красивый интерфейс PaperUI который хорошо смотрится как на писишках так и на телефонах. Вдобавок, есть все функции для подключения своего интерфейса, если вы рискнёте его написать.
OpenHab организован в core, ui и bindings. Binding это своеобразный драйвер для каждого устройства. В OpenHab-е есть пара обобщaющих байндингов, например http или tcp, и сначала я пытался ими пользоваться, но быстро понял что их полезность крайне ограничена самыми простыми случаями. У меня также есть пара красных слов в сторону «binding notation». Вообщем, если вам нужна своя логика то единственный путь это написание своего байндинга.
Нам повезло, структура байндингов намного улучшилась между первым и вторым OpenHab-ами, и с небольшим упорством я разобрался в байндинг «API» и написал свой. Мой байндинг находит новые устройства, ведёт учёт коннектов, дисконнектов и статусов всех устройств. Я планирую написать отдельный пост посвященный созданию своего байндинга, поэтому сейчас останавливаться на этом не буду и опишу архитектуру в более общих чертах.
Бинарник OpenHab-a запускается на любой машине с Java VM и поднимает веб морду на хосте. Наш байндинг запускает слушающий TCP сокет и ждёт пока к нему не подkлючится новый выключатель. Выключатель изначально программируется некоторыми параметрами от пользователя — wifi имя/пароль и айпишник или hostname где искать центральный сервер. То есть, как только выключатель устанавливает соединение с AP, он заходит на сервер. Когда TCP соединение установлено, пользователь получает уведомление о том что найдено новое устройство и надо бы добавить его в панель управления. И все, никаких конфиг файлов и binding configuration strings. В панели управления устройство выглядит как обычный выключатель, но погодите, это умный выключатель! Его статус (ВКЛ/ВЫКЛ) показывает правдивое состояние системы. Если вы его включите, а там выгорела лампочка, статус быстро вернется назад в ВЫКЛ, потому что если ток не идёт через выключатель, как следствие, лампочка не может работать.
Собираем все вместе
После нескольких итераций «поправь байндинг-подкрути микрокотроллер» вся система была готова к запуску. Отладка происходит вот на таком переносном агрегате.
Production сервер у меня состоит из RaspberryPi2 на котором крутится собранный OpenHab2. Малина подключена к домашней сети через LAN, и можно поднять дополнительный AP, на который посадить все выключатели для разделения и дополнительной безопасности.
А теперь давайте поиграем в электрика. Вооруженный тест-отвёрткой (горит красным светом если касаешься «горячего» провода) и отключив брейкер я взялся за проводку.
Довольно трудно орудовать толстыми медными проводами. Собираем.
Уже три недели я гоняю этот экземпляр с хорошими результатами, и готовлюсь установить еще один на улице.
На прощание
На этом моя история заканчивается. Пока я не решил что делать дальше. Сердце тянет отправить мой выключатель в хардвер инкубатор, авось возьмут — домашняя автоматизация сейчас популярна. А
Автор: kacang