Привет, Хабр!
В этой статье я хочу описать свой опыт разработки такого простого, но в тоже время самого используемого элемента «Умного дома». Речь пойдет о модуле управления освещением. Забегая вперед, хочу сказать, что данный проект был реализован еще в 2021 году, но в настоящее время потребовалась реализация еще одного модуля. Я решил совместить приятное с полезным, дополнительно обновить прошивку устройства и «перепроектировать» данный модуль с помощью современного ПО и само собой — поделиться с вами. Если стало интересно, то добро пожаловать под кат.
❯ Небольшая предыстория
Домашней автоматизацией я занимаюсь давно и застал те времена, когда еще не было доступных микроконтроллеров с беспроводной коммуникацией на борту (типа ESP8266), в основном использовались проводные решения на базе 1-Wire. И мой «Умный дом» не стал исключением.
Каждый начинающий «строитель» «Умного дома» понимает, что первым делом нужно научиться включать и выключать свет, чтобы эффектно удивлять друзей, управляя освещением со смартфона. В те времена это казалось магией :) Вот и я, закупившись на Алиэкспрессе поддельными двухканальными 1- Wire свичами DS2413P, решил реализовать управление светом. В итоге была собрана плата управления на базе купленных свичей и симисторным управлением нагрузкой. Данное устройство надежно проработало аж до 2021 года. Но летом того же года была жуткая гроза и по витой паре интернет провайдера прилетел мощный разряд, который унес в электронный рай сетевую карту сервера, USB 1-Wire адаптер, ну и плату управления освещением с эффектным взрывом симистора. Тогда я подумал, что пора завязывать с проводными решениями ибо гирлянда сгоревших устройств ни на секунду меня не радовала и я принялся за разработку беспроводного модуля управления освещением.
❯ Проектируем аппаратную часть
Условно мы можем разделить модуль на три сегмента:
- Система питания;
- Контроллер управления;
- Система силового управления.
При проектировании принципиальной схемы устройства будем придерживаться «золотого» принципа: чем проще — тем лучше, а значит — надежнее. Поэтому в качестве системы питания будет реализована схема на базе экономичного импульсного преобразователя напряжения LNK306GN, который доказал свою надежность временем и работой в аномальных условиях.
Серия микросхем LinkSwitch-TN специально разработана для замены всех неизолированных источников питания с линейным питанием и питанием от конденсаторов в диапазоне выходного тока менее 360 мА при равной стоимости системы, обеспечивая гораздо более высокую производительность и энергоэффективность.
Устройства LinkSwitch-TN объединяют в монолитной IC силовой полевой МОП-транзистор с напряжением до 700 В, генератор, простую схему управления включением/выключением, высоковольтный импульсный источник тока, генератор частот, схему ограничения тока и схему отключения при перегреве.
В качестве «мозга» нашего устройства, будем использовать микроконтроллер от компании Espressif Systems ESP8266. А для силового управления нагрузкой, то есть нашими лампочками, будем использовать связку оптопары MOC3052M и симистора BT136-600. Почему не реле? — спросите вы, ну не люблю я реле, они щелкают и габаритные. Ниже можно видеть результат разработки принципиальной схемы устройства. Для разработки схем и печатных плат я использую открытое ПО KiCAD.
Принципиальная схема модуля:
Как я уже говорил ранее, источник питания реализован на высоковольтном импульсном преобразователе LNK306GN, который позволяет максимально упростить схему источника питания. На входе источника формируется напряжение в 3,3 В, данное напряжение устанавливается обратной связью, которая организована с помощью резистивного делителя напряжения R4 и R5. Данная схема питания не имеет гальванической развязки с сетью, поэтому нужно обеспечить эффективную изоляцию платы для исключения поражения электрическим током. Первоначальный запуск устройства должен выполняться с последовательно подключенной нагрузкой (лампа накаливания 60 Вт) в цепи питания, чтобы исключить повреждения в случае ошибки при монтаже компонентов.
Трассировка платы:
Визуализация печатной платы:
Хочется добавить, что данная плата разрабатывалась с учетом современных реалий, здесь изменен форм-фактор микросхемы LNK306GN на SOP-7 в старой версии модуля используется тип корпуса DIP-7.
❯ Изготовление печатной платы
На тот момент, плата изготавливалась по канонам DIY, с помощью фоторезиста и фотошаблона. Но в настоящее время я пользуюсь для изготовления прототипов плат лазерным методом.
Активация фоторезиста с помощью фотошаблона:
Плата прототипа модуля после монтажа электронных компонентов:
❯ Разработка корпуса
Разработка корпуса устройства выполнялось в открытом ПО FreeCAD. Корпус довольно тривиальный и не содержит сложных элементов.
Визуализация корпуса с моделью платы:
Далее модель корпуса распечатывается на 3D принтере, в качестве материала печати используется HIPS пластик.
Устройство в собранном виде:
AirTag для сравнения габаритов устройства:
❯ Разработка прошивки и описание интерфейса
Разработка микро ПО устройства велась в среде Arduino IDE, обновленная версия реализована на моей, ставшей уже базовой, прошивке для умный устройств. Для улучшения пользовательского опыта, в прошивке применены следующие технологии:
- Captive portal;
- Multicast DNS;
- MQTT Auto Discovery;
- SSDP.
Captive portal — это сервис, на который принудительно перенаправляется пользователь, который выполнил подключение к устройству. Данный сервис работает только в режиме «точки доступа» при первоначальной конфигурации устройства. При отсутствии сетевого соединения или при первоначальной настройке, устройство создает беспарольную точку доступа с именем CYBEREX-Light. При подключении к данной точке доступа, пользователь автоматически будет перенаправлен на страницу авторизации для выполнения первоначальной конфигурации устройства. Для конфигурации устройства необходимо ввести пароль по умолчанию "admin".
Ниже приведены несколько скриншотов веб интерфейса устройства.
Страница входа:
Главная страница с элементами управления:
Конфигурация обмена по MQTT протоколу:
Multicast DNS — данный сервис используется для поиска устройств по доменному имени в локальной сети без использования предварительно настроенного DNS сервера. Другими словами, пользователь может получать доступ к устройству без необходимости ввода IP адреса. Ниже пример использования данного сервиса, где доступ к устройству выполняется с помощью его локального имени 11395386.local.
Страница конфигурации управления устройством через API:
Как вы можете видеть на скриншоте, в устройстве реализован доступ управления каналами модуля по API. Данная функция необходима для прямого взаимодействия с устройством без посредников в виде MQTT сервера или системы «Умного дома». Эту функцию можно использовать для подключения беспроводных выключателей, пример реализации в одном из моих проектов:
Демонстрируемый беспроводной выключатель также реализован на ESP8266, в качестве элементов питания использует две батарейки формата АА. Данный выключатель проработал уже три года на одних элементах питания, благодаря режиму DeepSleep.
Также функция данного API применяется в моей «умной колонке» (статья первая, статья вторая) для управления освещением. Ниже пример кода для реализации прямого управления с помощью «умной колонки»:
elif cmd == 'lightON':
try:
contents = urllib.request.urlopen("http://11395386.local/?page=status&apikey=UkFA7").read()
response0 = json.loads(contents)
if response0['c1'] == 'Off1' and response0['c2'] == 'Off2':
text = "Включила свет"
if response0['c1'] == 'On1' and response0['c2'] == 'Off2':
text = "Первый светильник уже включен, включила второй!"
if response0['c1'] == 'Off1' and response0['c2'] == 'On2':
text = "Второй светильник уже включен, включила первый!"
if response0['c1'] == 'On1' and response0['c2'] == 'On2':
text = "Свет уже включен! Но я могу выключить, если попросите!"
if response0['c1'] == 'Off1':
response2 = requests.get('http://11395386.local/?page=control&apikey=UkFA7&switch=1')
if response0['c2'] == 'Off2':
response2 = requests.get('http://11395386.local/?page=control&apikey=UkFA7&switch=2')
tts.va_speak(text)
except:
tts.va_speak("Сожалею, но возникла ошибка, попробуйте позже!")
elif cmd == 'lightOFF':
try:
contents = urllib.request.urlopen("http://11395386.local/?page=status&apikey=UkFA7").read()
response0 = json.loads(contents)
if response0['c1'] == 'Off1' and response0['c2'] == 'Off2':
text = "Свет уже выключен! Но я могу включить, если попросите!"
if response0['c1'] == 'On1' and response0['c2'] == 'Off2':
text = "Второй светильник уже выключен, выключила первый!"
if response0['c1'] == 'Off1' and response0['c2'] == 'On2':
text = "Первый светильник уже выключен, выключила второй!"
if response0['c1'] == 'On1' and response0['c2'] == 'On2':
text = "Выключила свет!"
if response0['c1'] == 'On1':
response2 = requests.get('http://11395386.local/?page=control&apikey=UkFA7&switch=1')
if response0['c2'] == 'On2':
response2 = requests.get('http://11395386.local/?page=control&apikey=UkFA7&switch=2')
tts.va_speak(text)
except:
tts.va_speak("Сожалею, но возникла ошибка, попробуйте позже!")
❯ Интеграция в «Умный дом»
Интеграция устройства в систему «Умного дома» реализована с помощью MQTT Auto Discovery.
MQTT Auto Discovery — сервис, позволяющий максимально упростить интеграцию нашего устройства в систему «Умного дома». В моем случае, в качестве системы «умного дома», я использую Home Assistant, поэтому сервис MQTT Auto Discovery адаптирован именно под неё. Ниже код реализации MQTT Auto Discovery в микро ПО устройства:
void send_mqtt(String tops, String data, String subscr){
// Анонсируем объекты для Home Assistant [auto-discovery ]
// Анонсируем объекты один раз при успешном подуключении и при запуске устройства
// if(!annonce_mqtt_discovery){
mqqt_d_annonce("CL1", "c1", "On1", "Off1");
mqqt_d_annonce("CL2", "c2", "On2", "Off2");
mqqt_d_annonce("CL3", "c3", "On3", "Off3");
annonce_mqtt_discovery = true;
// }
// Отправляем данные
client.publish(tops.c_str(), data.c_str());
client.subscribe(subscr.c_str());
}
void mqqt_d_annonce(String namec, String cn, String on_d, String off_d){
String top = String(settings.mqtt_topic) +"/jsondata";
String control = String(settings.mqtt_topic) +"/control";
char jsonBuffer[1024] = {0};
DynamicJsonDocument chan1(1024);
chan1["name"] = namec;
chan1["state_topic"] = top;
chan1["command_topic"] = control;
chan1["payload_on"] = on_d;
chan1["payload_off"] = off_d;
chan1["state_value_template"] = "{{ value_json."+cn+" }}";
serializeJson(chan1, jsonBuffer, sizeof(jsonBuffer));
String top_to = "homeassistant/light/"+cn+"/config";
client.publish(top_to.c_str(), jsonBuffer, true);
}
После успешного подключения устройства к сети и настройки MQTT соединения, в «объектах» Home Assistant появятся объекты нашего устройства, пользователю останется только настроить карточку объектов на панели управления, чтобы иметь возможность управлять данным модулем. Ниже приведен пример кода карточки объектов:
type: horizontal-stack
cards:
- show_name: true
show_icon: true
type: button
tap_action:
action: toggle
entity: light.cl1
name: Свет 1
show_state: true
hold_action:
action: more-info
- show_name: true
show_icon: true
type: button
tap_action:
action: toggle
entity: light.cl2
name: Свет 2
show_state: true
hold_action:
action: more-info
- show_name: true
show_icon: true
type: button
tap_action:
action: toggle
entity: light.cl3
name: LED
show_state: true
hold_action:
action: more-info
В результате карточка объектов будет выглядеть следующим образом:
Осталось упомянуть о последнем сервисе SSDP.
Чтобы как-то «повелевать» всем зоопарком моих умных устройств, был реализован данный сервис.
SSDP (Simple Service Discovery Protocol) — сетевой протокол, основанный на наборе протоколов Интернета, служащий для объявления и обнаружения сетевых сервисов. SSDP позволяет обнаруживать сервисы, не требуя специальных механизмов статической конфигурации или действий со стороны серверов, таких как DHCP или DNS.
Для моего удобства, я написал мобильное приложение, которое позволяет в три нажатия обнаружить и сконфигурировать устройство без лишних хлопот и похода в роутер. Ниже представлены скриншоты приложения, ссылка на приложение будет размещена в конце статьи.
Приложение для поиска устройств в сети:
❯ Использование аппаратного выключателя
Дабы не исключать классическую схему управления освещением с помощью обычного выключателя, который обычно встраивается в стену, в устройстве также реализован вход (J5) для подключения аппаратного выключателя. Данное решение позволяет без дополнительных переделок интегрировать модуль в существующую систему освещения.
❯ Использование аппаратного выключателя
Ну что ж, давайте подведем итоги. В итоге у нас получилось простое, но эффективное и относительно компактное устройство для управления освещением, с возможностью работы как в автономном режиме, так и в составе «Умного дома». Данное устройство разрабатывалось, прежде всего, для управления светодиодным освещением, но примененные силовые симисторы позволяют коммутировать осветительную нагрузку до 300Вт на канал, без ощутимого нагрева силовых элементов.
На этом можно и завершить статью. Надеюсь, мой опыт будет вам полезен. Если у вас есть замечания, предложения или вы хотите поделиться подобным опытом, то добро пожаловать в комментарии! Если статья вам понравилась, то поддержите её стрелочной вверх. Всем добра, здоровья и спасибо за внимание!
Ссылки к статье:
- Проект печатной платы;
- Исходный код прошивки устройства;
- Модель корпуса устройства;
- Мобильное приложение для поиска устройств.
Автор: CyberexTech