Разработка DIY диммера 220V на esp8266 (nodeMCU+RobotDyn Thyristor AC)

25 июня 2019, 23:00

Как разрабатываются устройства IoT? Это сложно? Китайская компания Espressif Systems в свое время сделала переворот в индустрии IoT, представив свой новый чип ESP8266 по необычайно низкой цене, ставший культовым для производства DIY устройств умного дома. Под новый чип от  Espressif Systems программисты начали активно писать библиотеки и адаптировать существующие библиотеки платформы Arduino. Это сделало разработку IoT устройств необычайно простой и увлекательной. Сегодня существует множество коммерческих устройств на базе чипа ESP8266. Я решил поделиться с вами своим опытом создания устройства IoT на базе чипа ESP8266. 

Сколько вольт "в розетке"?

Большинство ответит: около 220 вольт и будут правы, но не совсем. Напряжение в сети питания представляет собой синусоиду с амплитудой около 311 вольт (tnx to AlexAW), на четверти цикла которой напряжение равно 110 вольт, а иногда и вовсе равно нулю!

Тоесть, если включать нагрузку каждый раз, когда синусоида приближается к нуля, можно напрямую без адаптеров из розетки заряжать мобильный телефон! 

Для определения точки, когда в сети напряжение равно нулю я воспользовался вот таким устройством от китайских товарищей из RobotDyn стоимостью 230 руб. Он уже содержит в себе сразу детектор нуля (zero-cross detector) и симмистор, который открывается при подаче импульса управления, оставаясь открытым до тех пор пока питающее напряжение не упадет практически до нуля. Для получения нужного  напряжения на выходе мы должны синхронизировать сигнал управления с переходом синусоиды питающего напряжения через ноль. Управление силовым симмистором заведено  через маломощный оптосиммистор, поэтому цепи управления гальванически развязаны с сетевым напряжением. Каждый раз, когда сетевое напряжение приближается к нулю, модуль  подает сигнал на один из своих выходов. Смещая фазу включения симмистора путем подачи управляющего сигнал на другой пин модуля можно получить на выходе любое напряжение в пределах от 220 вольт до нуля. 

Управлять этими сигналами мы будем с помощью модуля nodemcu, на борту у которого установлена ESP8266. Подключаем пины Z-C и pwm к цифровым пинам ESP8266, подаем питание на модуль и... Ничего не происходит! Верно, нам необходимо еще написать свою прошивку для модуля. Устанавливаем Atom и PlatformIO и приступаем к написанию микропрограммы. Китайские товарищи из RobotDyn уже написали библиотеку для управления таймерами, что упрощает  написание микропрограммы для модуля. Хотя так было не всегда, библиотека появилась около полугода назад, в первоначальной версии прошивки я использовал собственный код для диммирования. 

Что должно уметь наше устройство?

Во-первых, конечно, оно должно управляться из внешних систем по радиоканалу (Wi-Fi в нашем случае): должно принимать команды и отправлять ответ о результате их выполнения. Во-вторых, должна быть возможность найти устройство в сети. И конечно же, возможность обновления "по воздуху" (OTA Update).  Приступим к реализации. Полный листинг кода прошивки я думаю будет интересен небольшому кругу читателей, поэтому всю программную реализацию я оставлю "за кадром", сосредоточимся на принципиальном проектировании устройства. 

Наше устройство должно быть безопасным. Т.к. во время циклов включения-выключения наш транзистор нагревается, установим на плату вот такой простой термодатчик DALLS DS18B20 за 35 рублей. Датчик обменивается с микроконтроллером данными по однопроводной линии связи интерфейса 1-Wire, диапазон измерения температуры составляет от -55 до +125 градусов цельсия, этого должно нам вполне хватить. После превышения температуры 40 градусов, устройство автоматически отключит само себя и перестанет принимать команды до того, пока температура не снизится.  Callback функция отключения выглядит следующим образом:

void emergencyCallback() {
  sensors.requestTemperatures();
  float temperature = sensors.getTempC(insideThermometer);

  if (temperature > 40) {
    dimmer.setState(OFF);
    digitalWrite(LED_PIN, LOW);
    Serial.printf("Temperature is %.2f degrees celsius. Swith OFF on emergency reason.\n\r", temperature);
  } else Serial.printf("Temperature is %.2f degrees celsius\n\r", temperature);

}

Подключаем все по следующей схеме:

Для корректной работы датчика между пинами DATA и VDD необходимо припаять резистор на 4,7 кОм. Конфигурация пинов следующая:

#define LED_PIN D6
#define AC_LOAD D8
#define ZC_PIN D1
#define ONE_WIRE_BUS D5

Собираем все на макетной плате:

Чтобы устройством можно было управлять, поднимем на нашей ESP8266 TCP сервер на порту 2000. Для отправки на устройство команд я выбрал текстовый формат сериализации и десериализации данных json т.к. он легко читается как людьми, так и машиной, не придется писать свой парсер, можно отправлять и принимать произвольное количество параметров, да и просто с ним удобно работать в целом (особенно в python). Какие команды нам могут понадобится?

{"id":1, "method":"set_power", "power":"50", "state":"ON"}
{"id":1, "method":"set_power", "power":"50", "state":"OFF"}
{"id":1, "method":"set_state", "state":"OFF"}
{"id":1, "method":"set_state", "state":"ON"}
{"id":1, "method":"set_config", "SSID":"Wi-Fi SSID", "PASSWD": "PASSWORD"}
{"id":1, "method":"set_mode", "mode":"TOGGLE_MODE"}
{"id":1, "method":"get_temperature"}
{"id":1, "method":"get_state"}
{"id":1, "method":"update", "IP":"192.168.1.43", "url":"/update/firmware.bin"}

Параметр method определяет команду для выполнения, set_power устанавливает яркость освещения (диммирование), state - определяет включена или выключена при этом нагрузка. Это может быть удобно, когда в системах управления умным домом вызывается метод "включить" без установки уровня диммирования, в этом случае при включении будет установлен заданный ранее (например, в сцене по времени) уровень освещенности. set_state включает или выключает нагрузку, set_config - посылает на устройство конфигурацию Wi-Fi сети. При первом включении (либо в случае невозможности подключиться к существующей сети) наше устройство переходит в режим точки доступа (с адресом 192.168.4.1), подключившись к которой можно отправить конфигурацию нашей Wi-Fi сети. get_temperature возвращает текущую температуру с сенсора, get_state - текущий статус (выключено или включено), метод update инициирует обновление прошивки, он принимает в качестве параметров IP адрес сервера, на котором находится обновление и сам путь к этом обновлению (url). Само обновление можно, например, разместить в локальной сети на малинке. Отправить команды можно прямо из терминала с помощью утилиты netcat. На запрос

echo '{"id":1, "method":"get_state"}' | nc -w1 192.168.1.43 2000

получим ответ:

{"id":1,"power":30,"state":"ON"}

Для чего нужен id? Дело в том, что ESP8266 отправляет ответ всем подключенным клиентам и чтобы различать ответы, которые предназначены именно нам как раз и нужен id запроса. 

echo '{"id":1, "method":"get_temperature"}' | nc -w1 192.168.1.43 2000

вернет нам текущую температуру с датчика DS18B20

{"id":1,"temperature":21.9}

Уже сейчас наше устройство можно интегрировать с системами управления умным домом путем выполнения shell команд, например можно легко добавить в homebridge, который прокинет устройство в HomeKit. 

Demo

Статические IP. Не люблю я статические IP, поэтому для своего устройства я предусмотрел возможность сетевого поиска. 

void discoverResponder() {

    if (Udp.parsePacket()) {
      char packetBuffer[255] = "";
      if (Udp.read(packetBuffer, 255) == 0) return;
      Serial.printf("Received broadcast message: %s from %s\n", packetBuffer, Udp.remoteIP().toString().c_str());

      if (String(packetBuffer) == "discover") {
        Udp.beginPacket(Udp.remoteIP(),Udp.remotePort());
        StaticJsonDocument<100> jsonResult;

        jsonResult["deviceID"] = String(ESP.getChipId(), HEX);
        WiFi.localIP() ? jsonResult["IP"] = WiFi.localIP().toString() : jsonResult["IP"] = WiFi.softAPIP().toString();
        jsonResult["model"] = MODEL;

        String jsonReply;
        serializeJson(jsonResult, jsonReply);

        Udp.print(jsonReply);
        Udp.endPacket();
      }
    }
}

Для поиска в сети ESP8266 DIY Smart Home устройств достаточно отправить на порт 1000 широковещательный UDP пакет с содержанием "discover". Скрипт (поиска) на Python выглядит так:

import json
import socket

print('Starting discover ESP8266 DIY Smart Home devices...')
helobytes = 'discover'.encode()

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.settimeout(5)
s.sendto(helobytes, ('<broadcast>', 1000))

data, addr = s.recvfrom(1024)

reply = json.loads(data.decode())
deviceID = reply["deviceID"]
IP = reply["IP"]
hardware = reply["hardware"]

print('Discovered. Device ID: {0}, IP: {1}, Model: {2}'.format(deviceID, IP, hardware))

 В результате придет ответ:

{"deviceID":"d7531с","IP":"192.168.1.43","hardware":"ZCACD1"}

Здесь deviceID - уникальный идентификатор нашего устройства, нужен для того, чтобы различать несколько устройств в одной сети, IP - IP адрес, необходимый для отправки на устройство команд. 

Прошивка ESP8266

Заливать пошивку мы будем с помощью инструментов esptool и nodemcu-pyflasher. Устанавливаем. 

git clone https://github.com/espressif/esptool.git
cd esptool
sudo python setup.py install

После установки esptool запускаем nodemcu-pyflasher. Здесь нужно указать порт загрузки - он появляется после после подключения USB to TTL конвертера (либо после подключения USB кабеля если конвертер уже распаян на плате), путь к нашей прошивке, скорость можно оставить 115200. В случае ошибок загрузки, скорость нужно уменьшить, например до 9600. Указываем нужно ли нам стирать все данные на флеш памяти ESP, нажимаем кнопку Flash NodeMCU, ждем несколько секунд - все готово! Иногда перед подключением ESP к компьютеру нужно зажать на плате кнопку "flash", а уже потом подключать питание. Если кнопки flash нет на плате, просто замыкаем контакты GPIO0 и GND, затем подаем питание, это переведет наш модуль в режим прошивки, позволяя загрузить нашу микропрограмму на устройство. 

Интеграция в Domoticz

В конечном итоге я делал устройство для интеграции в системы управления умным домом. Можно конечно подключить его через shell скрипты, но ничто не сравнится с нативной поддержкой, "родные" устройства в Domoticz имеют  наивысший приоритет и работают очень шустро, к тому же будет обратная связь от устройства со статусом выполненной команды (включилось/выключилось), более того, появляется возможность реализовать коммуникацию напрямую через сокеты, что добавит скорости и стабильности нашему устройству. Настройка довольно проста и похожа на настройку других моих плагинов для Domoticz:

Для настройки необходимо ввести только deviceID, встроенная система поиска "discover" сама найдет устройство в сети. Для получения deviceID при первой настройке нужно просто оставить поле равным 0, это запустит режим сетевого поиска и в логе Domoticz будет отображен deviceID, который нам нужен. 

После запуска плагин создает выключатель типа диммер, и набор сцен. Bright - яркая сцена, TV - приглушенный до 30%  свет, Daily - включенный на половину диммер, Midnight - минимальное освещение. Можно так же реализовать аппаратные сцены, такие как "восход" или "закат" - все в наших руках! Дополнительно создается температурный сенсор с датчика DS18B20, который можно найти во вкладке "Температура". 

Для установки плагина клонируем репозитарий:

cd domoticz/plugins
git clone https://github.com/Whilser/ESP-DIY-Samrt-Home.git ESPSmartHome
sudo service domoticz restart

Там же, в репозитарии находится прошивка для модуля: файл firmware.bin.

Больше, чем просто диммер

По сути, наше устройство может измерять и посылать окружающую температуру. Да, если его расположить в корпусе, оно будет измерять внутреннюю температуру, но если вывести его за пределы корпуса - получится дополнительный термодатчик. Если заменить Zero-Cross Detector на реле (например, твердотельное), то получим умную розетку и все это легко интегрируется в систему умного дома, более того, имеется нативная поддержка системы управления умным домом Domoticz. Если закачать прошивку в существующее устройство на базе  ESP8266 (например, sonoff), или светодиодную лампочку (с некоторыми переделками, конечно), получим IoT устройство с нужным нам функционалом, это может говорить о том, что наш проект можно превратить в базовую платформу для разработки недорогих IoT устройств с нужным нам функционалом. Именно для этого в функции discover предусмотрена передача модели устройства. 

Что дальше?

Прототип получился немного громоздким, но на то он и прототип. Устройство можно уменьшить в размерах если:

  • Разработать и напечатать собственную плату
  • Нарисовать и напечатать корпус

Следующим устройством семейства DIY Smart Home будет счетчик воды для информирования о ресурсе фильтра питьевой воды и необходимости его замены. Спасибо за вдохновение Виталию. Так же я планирую доработать текущую прошивку, добавив некоторые аппаратные сцены (такие как восход, закат и может быть что-то еще).

Разработка собственных IoT устройств может быть довольно увлекательным занятием, время пролетает незаметно! Можно легко получить устройство с нужным мне функционалом. В дальнейшем я планирую развивать проект, разрабатывая все новые устройства с нужным мне функционалом, дорабатывая поддержку устройств в системе управления умным домом Domoticz (да, я знаю про существование Home Assistant, но так уж исторически сложилось, что начал строить свой умный дом на платформе Domoticz и если все работает и работает хорошо - не вижу особого смысла менять платформу, а все нужные мне устройства, поддержки который нет в Domoticz я могу легко и увлекательно добавить сам... ). 

Ссылка на проект GitHub: DIY Smart Home based on Espressif Systems (ESP32, ESP8266). Там правда пока мало чего документировано, но со временем я добавлю туда материалы. 


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


Все новости мира умных домов - t.me/SprutAI_News

Остались вопросы? Мы в Telegram - t.me/soprut

  1. Дмитрий Батюшин (ReD)
    Дмитрий Батюшин (ReD) 26 дней назад

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

  2. Владислав Попов (Vladislav_P)

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

  3. Илья Яшин (yshinig)
    Илья Яшин (yshinig) 26 дней назад

    Главный вопрос как работает диммир со светодиодными лампами???

    • Антон Киселёв (Whilser)
      Антон Киселёв (Whilser) 26 дней назад

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

      • Александр Вайдуров (AlexAW)

        Пробовал пару штук - не понравилось. Вроде Гауссы, но по сравнению с лампами накаливания яркость изменяют нелинейно. Кстати светодиоды (светодиодные ленты)  при линейном изменении ШИМ тоже изменяют яркость нелинейно (это свойство светодиодов) может поэтому и Диммируемые светодиодки себя так ведут. Но ИМХО не понравилось мне.

        Кстати не зря видимо появились диммируемые светодиодки на 3 уровня яркости. По факту больше и не требуется обычно. 

        1000x_image.jpg?1561565767
        • Антон Киселёв (Whilser)
          Вообще, зная характеристики напряжение/яркость лампы можно сделать программную компенсацию, изменять напряжение нелинейно. Тогда яркость будет изменяться более-менее линейно. 

          • Александр Вайдуров (AlexAW)

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

            Кстати если делать диммер (ШИМ регулятор) для Светодиодных лент, там эту нелинейность надо обязательно закладывать.

  4. Андрей Медведев (rjayone)

    Просто топ статья! Спасибо!

  5. Никита Герасимов  (Rapidshe)

    Лайк и подписка)

    Как спаяешь на платке я бы купил парочку)

    и кажется   DIY а не   DYI ))

  6. Александр Вайдуров (AlexAW)

    Хороший диммер. 

    Есть предложение по софтовому улучшению потребительских характеристик. Как то подсмотрел у Шнайдеровских однокнопочных диммерах. Краткое касание кнопки включает выключает свет на ранее установленном уровне яркости. долгое удержание приводит к плавной регулировке яркости. У вас по сути так и реализовано. Но фишка шнайдеровского в том, что при включении выключении (кратковременном нажатии) он устанавливал запомненное значение яркости плавно, и выключал соответственно тоже. Смотрится оч. приятно. Я в своих сделал очень нравится. Вот демка моего прототипа  https://www.youtube.com/watch?v=1U6Oy17Ns0k&t=32s  Еще такой режим бережет лампы накаливания. 

    • Антон Киселёв (Whilser)
      Антон Киселёв (Whilser) 25 дней назад

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

  7. Евгений Селянин (Shico)
    Евгений Селянин (Shico) 25 дней назад

    Огромное спасибо за труды. Действительно годно и информативно. 

  8. (meta11ist87)
    (meta11ist87) 23 дня назад

    Годно, спасибо за труды. Ещё бы эту чудесную штуку прикрутить к ХА каким либо способом...

    • Антон Киселёв (Whilser)

      Вообще, можно доработать прошивку и подвязать через MQTT брокер. Я делал так с Domoticz раньше, но потом отказался т.к. в текущем решении без MQTT брокера не нужно промежуточное звено и взаимодействие с устройством происходит напрямую через сеть. 

  9. (maikl)
    (maikl) 22 дня назад

    Круто!

    Хотя хотелось бы подробнее. Зачем тогда шим контролеры если тут так просто регулируется?

    • Антон Киселёв (Whilser)
      Антон Киселёв (Whilser) 2 часа назад

      ШИМ работают с постоянным током, здесь ток переменный. Плюс частоту ШИМ можно регулировать, здесь - ограничены частотой сетевого напряжения около 50 Гц, что довольно мало для получения достаточно стабильных напряжений для высокоточной техники. 

  10. Алексей Новосельцев (novo)

    Огонь статья и разработка! Сам использую RBDimmer почти год, сначала как просто выключатель, вместо твердотельных реле, затем как регулятор оборотов вентиляторов 220в (в санузлах, а потом и в приточках), последнее его применение подогрев приточного воздуха зимой (PID управление тэном).

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

    Попробую твой код, может не будет моргать лампа и я найду свою ошибку ;)

    • Антон Киселёв (Whilser)
      Антон Киселёв (Whilser) 2 часа назад
      Проблема моргания на низком свечении может быть связана с тем, что ESP не успевает обрабатывать сигнал по причине плохой сборки ("шумов"), плохого сигнала и т.д., часть ресурсов процессора у него тратится на рутинные задачи, либо в качестве сборки самого RobotDyn Thyristor AC. На высоких вольтажах это может быть не сильно заметно т.к. спираль не успевает достаточно остыть. Проблема может решиться заменой компонентов либо в использовании более оптимизированного кода для диммирования (например, с аппаратными таймерами) - надо смотреть чем конкретно вызвана проблема.  

К списку статей

Скидки для сообщества

Ноотехника

+375 17 233-25-45
Промокод:
Sprut
Размер скидки:
10%
Действует у всех официальных представителей. Для применение необходимо указать в поле комментария или при звонке менеджеру.

Интернет-магазин yourhomekit.ru

+7 914 550-51-11
Промокод:
SPRUT-BLG
Размер скидки:
8%
Cамый большой ассортимент в России аксессуаров Apple HomeKit

Похожие статьи

04 сентября 2018, 12:14
Интеграция RGB ленты на ESP8266 с прошивкой tasmota в систему HomeBridge (HomeKit)
02 ноября 2018, 12:14
Кнопка звонка с уведомлениями в HomeKit
15 октября 2018, 09:05
Прошивка для Sonoff c нативным HomeKit
15 ноября 2018, 09:42
Способы автоматизации механических ворот
27 октября 2018, 12:20
Нативный Термостат для котла на ESP8266 с поддержкой Apple HomeKit
01 октября 2018, 07:43
Нативный HomeKit на ESP8266
15 июня 2018, 12:13
Охранная система в гараж на ESP8266 с интеграцией в Apple HomeKit
02 октября 2018, 18:41
Установка SDK для компиляции прошивок под HomeKit
22 октября 2018, 19:00
Сборка DIY Лабораторного блока питания из китайских модулей
25 ноября 2018, 18:23
Умное зеркало добавляем модули Airplay и Google Calendar