Вы уже, наверное, в курсе, что Easy HMI получил поддержку беспроводной связи по UDP. Если нет, то ознакомьтесь с новыми возможностями тут. А так как есть беспроводной интерфейс, неплохо было бы сделать удаленное управление реле. Что, в свою очередь, позволит управлять светом, вытяжкой, вентилятором, чайником, кофемашиной, обогревателем и другими устройствами и приборами. Для реализации данной идеи можно использовать готовые модули на базе ESP32 и/или ESP8266. Я уже рассказывал про модуль ESP12F Relay X4 (LC-Relay-ESP12-4R-MV – по даташиту). Сегодня напишем код для управления данным модулем и также посмотрим, как можно управлять по UDP 2, 3, 5, 10 и даже 12 группами реле с одного сенсорного дисплея. Думаете, это невозможно реализовать? Давайте разберемся!
Как писал ранее, Easy HMI получил поддержку беспроводной связи по UDP. Об этом рассказывал вот в этой статье. На момент написания данного поста UDP поддерживают только наши дисплеи AT HMI, но в ближайшее время выложу прошивку с поддержкой UDP для дисплеев ESP32-2432S024, ESP32-2432S028, ESP32-2432S032, ESP32-3248S035. Подписывайтесь на группу в ВК, чтобы не пропустить последние новости.
Процесс создания интерфейса для управления реле по UDP не сильно отличается от создания интерфейса для управления по UART. Но есть одна особенность. Чтобы отследить, получило ли устройство команду от дисплея, сделаем обратную связь. И для этого кнопки управления реле сделаем без фиксации. Зачем это нужно, рассмотрим, когда будем писать код для устройства управления реле, например, для ESP12F Relay X4.
И главный момент: нужно в программе Easy HMI активировать работу по UDP. Это нужно сделать в разделе Настройки. Все, интерфейс сделан и внесены настройки для беспроводной работы.
Перед написанием кода нужно разобраться с модулем ESP12F Relay X4 и определить, к каким пинам подключены реле. На плате есть колодка подключения перемычек для реле и аналоговый вход. Если не припаять перемычки, то реле не будут управляться от ESP8266.
Pin | Описание |
---|---|
ADC | Аналоговый вход. Диапазон входного напряжения 0 ~ 1В, диапазон значений: 0 ~ 1024 |
EN | Включить пин, подтянут по умолчанию |
GPIO16 | Используется перемычка RY1 для включения реле 1 |
GPIO14 | Используется перемычка RY2 для включения реле 2 |
GPIO12 | Используется перемычка RY3 для включения реле 3 |
GPIO13 | Используется перемычка RY4 для включения реле 4 |
На плате есть колодка подключения программатора.
Pin | Описание |
---|---|
5V | Питание 5V |
TX | Подключить к RX программатора |
RX | Подключить к TX программатора |
GPIO0 | Подтягивается к GND для программирования |
GND | Пин для подтяжки GPIO0 к GND |
GND | Пин подключения к GND программатора |
Подключаем любой USB-TTL конвертер, не забываем, что нужно при загрузке подтянуть GPIO0 к GND (установить перемычку). Я буду использовать конвертер на PL2303HX. Подключаем по схеме:
После загрузки нужно убрать перемычку GPIO0 <------> GND и перезагрузить модуль. Подробнее про модуль ESP12F Relay X4 читайте в этой статье.
Написал максимально простой код с минимумом массивов и циклов. В текущей версии Easy HMI нельзя менять логин и пароль точки доступа. Я над этим работаю. И, возможно, на момент, когда вы читаете данную статью, эти настройки уже доступны.
/* Управление реле по UDP: Беспроводное решение с ESP8266, ESP32 и Easy HMI. https://arduino-tex.ru/news/218/upravlenie-rele-po-udp-besprovodnoe-reshenie-s-esp8266-esp32-i.html */ #if defined(ESP8266) #include <ESP8266WiFi.h> // Библиотека WiFi для ESP8266 #endif #if defined(ESP32) #include "WiFi.h" // Библиотека WiFi для ESP32 #endif #include <WiFiUdp.h> // Библиотека UDP для передачи датаграмм через WiFi WiFiUDP udp; // Объект UDP для отправки и приёма сообщений // --- Настройка UDP --- const char* ssid = "ATHMI_AP"; // Имя WiFi сети const char* password = "C3ej7769Kjh"; // Пароль WiFi сети IPAddress receiverIp(192, 168, 4, 1); // IP-адрес устройства, которому отправляются команды const uint16_t receiverPort = 49356; // Порт, на который слушает получатель // Можно менять настройки в зависимости от проекта #define DEBUG 1 // Включение/выключение отладочных сообщений (1 - включить) const bool level = 1; // Уровень сигнала для реле: 1 - HIGH активность, 0 - LOW активность const byte relays_num = 4; // Количество реле в проекте byte relays[relays_num] = { 16, 14, 12, 13 }; // Пины к которым подключены реле bool flag_ON[relays_num] = { false }; // Статус реле: включено или выключено, по умолчанию — выкл. void setup() { if (DEBUG) { Serial.begin(115200); // Инициализация serial для отладки Serial.println("Start program"); } // Инициализация пинов реле как выходов for (byte i = 0; i < relays_num; i++) { pinMode(relays[i], OUTPUT); if (!level) digitalWrite(relays[i], HIGH); // Если уровень LOW активный, то по умолчанию ставим пин в HIGH } // Подключение к WiFi сети WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(600); Serial.println("Connecting to WiFi..."); } Serial.print("Connected to WiFi with IP: "); Serial.println(WiFi.localIP()); // Запуск UDP-сервера на указанный порт udp.begin(receiverPort); } void loop() { // Проверка, есть ли входящий UDP пакет if (udp.parsePacket()) { char incomingPacket[16]; // Буфер для получения команды int len = udp.read(incomingPacket, 16); // Чтение данных if (len > 0) { incomingPacket[len] = '\0'; // Добавляем нулевой символ для строки if (DEBUG) Serial.println(incomingPacket); // Вывод команды для отладки // Обработка команд для кнопок А1A (управление реле 1) if (strstr(incomingPacket, "BtA1A=1") != NULL) { // Нажата кнопка А1A (вкл. реле 1) flag_ON[0] = !flag_ON[0]; // Инвертировать состояние реле SetRelays(1, flag_ON[0]); // Установить реле delay(160); // Обновление цвета кнопки (например, для индикатора) if (flag_ON[0]) SendBtColor(0xA1A, 0xFA8072, 0xFF4500); // Цвет "включено" else SendBtColor(0xA1A, 0x32CD32, 0x2E8B57); // Цвет "выключено" } if (strstr(incomingPacket, "BtA1D=1") != NULL) { // Отпущена кнопка А1D (выкл. реле 2) flag_ON[1] = !flag_ON[1]; // Инвертировать состояние второго реле SetRelays(2, flag_ON[1]); delay(160); if (flag_ON[1]) SendBtColor(0xA1D, 0xFA8072, 0xFF4500); else SendBtColor(0xA1D, 0x32CD32, 0x2E8B57); } // Аналогично для реле 3 (A20) if (strstr(incomingPacket, "BtA20=1") != NULL) { flag_ON[2] = !flag_ON[2]; SetRelays(3, flag_ON[2]); delay(160); if (flag_ON[2]) SendBtColor(0xA20, 0xFA8072, 0xFF4500); else SendBtColor(0xA20, 0x32CD32, 0x2E8B57); } // Аналогично для реле 4 (A23) if (strstr(incomingPacket, "BtA23=1") != NULL) { flag_ON[3] = !flag_ON[3]; SetRelays(4, flag_ON[3]); delay(160); if (flag_ON[3]) SendBtColor(0xA23, 0xFA8072, 0xFF4500); else SendBtColor(0xA23, 0x32CD32, 0x2E8B57); } // Команда "Включить все" (A14) if (strstr(incomingPacket, "BtA14=1") != NULL) { // Меняем цвет всех кнопок на "включено" SendBtColor(0xA1A, 0xFA8072, 0xFF4500); SendBtColor(0xA1D, 0xFA8072, 0xFF4500); SendBtColor(0xA20, 0xFA8072, 0xFF4500); SendBtColor(0xA23, 0xFA8072, 0xFF4500); // Включаем все реле for (byte i = 1; i <= relays_num; i++) { SetRelays(i, 1); flag_ON[i - 1] = true; } } // Команда "Выключить все" (A17) if (strstr(incomingPacket, "BtA17=1") != NULL) { // Меняем цвет всех кнопок на "выключено" SendBtColor(0xA1A, 0x32CD32, 0x2E8B57); SendBtColor(0xA1D, 0x32CD32, 0x2E8B57); SendBtColor(0xA20, 0x32CD32, 0x2E8B57); SendBtColor(0xA23, 0x32CD32, 0x2E8B57); // Выключаем все реле for (byte i = 1; i <= relays_num; i++) { SetRelays(i, 0); flag_ON[i - 1] = false; } } } } } // Функция для управления состоянием реле по номеру (1-4) и состоянию (true/false) void SetRelays(uint8_t num_relay, bool flag_relay) { // В зависимости от уровня (HIGH или LOW активность) выставляем состояние пина digitalWrite(relays[num_relay - 1], level == 0 ? !flag_relay : flag_relay); } // --== Функции для отправки цвета на дисплей или кнопку ==---// // Эта функция отправляет UDP-пакет с командами для подсветки кнопки // num_element - ID элемента (например, кнопки), data_color и data_color2 - цвета в формате 0xRRGGBB void SendBtColor(uint16_t num_element, uint32_t data_color, uint32_t data_color2) { // Проверяем подключение WiFi if (WiFi.status() != WL_CONNECTED) { return; // Выходим, если нет соединения } char buffer_local[46]; // Буфер для формирования команды // Формат строки: bt.{ID}.col={цвет1};{цвет2} snprintf(buffer_local, sizeof(buffer_local), "bt.%X.col=%08lX;%08lX", num_element, data_color, data_color2); // Отправляем UDP-пакет udp.beginPacket(receiverIp, receiverPort); udp.print(buffer_local); udp.endPacket(); // Завершаем отправку }
Пояснения кода:
#include
: ESP8266WiFi.h или WiFi.h нужны для работы с Wi-Fi, а WiFiUdp.h — для общения по сети UDP.const char* ssid = "ATHMI_AP";
: ssid — это имя точки доступа Wi-Fi сети.const char* password = "C3ej7769Kjh";
: password — пароль от точки доступа Wi-Fi сети.IPAddress receiverIp(192, 168, 4, 1);
: Это IP-адрес устройства, которому ESP будет отправлять ответы (например, цвет кнопки изменился).const uint16_t receiverPort = 49356;
: Порт — это как номер квартиры в доме (IP-адрес). ESP будет "слушать" команды, приходящие на этот порт, и отправлять ответы на этот же порт удаленного устройства.#define DEBUG 1;
: Если стоит 1, то в "Монитор порта" в Arduino IDE будут выводиться сообщения о том, что делает программа. Это помогает найти ошибки. Если поставить 0, сообщения выводиться не будут.const bool level = 1;
: Реле бывают разные. Одни включаются, когда на них подают высокий сигнал (HIGH), другие — когда низкий (LOW). Эта настройка говорит, какой тип реле у вас. 1 — для реле высокого уровня.byte relays[] = { 16, 14, 12, 13 };
: Это номера "ножек" (пинов) на ESP, к которым вы подключили реле. Например, 16 — это пин D0 на NodeMCU (ESP8266).bool flag_ON[] = { false };
: Это "флажки", которые запоминают, включено реле (true) или выключено (false).void setup() { ... };
: Этот код выполняется один раз, когда ESP включается. Здесь он настраивает пины реле, подключается к Wi-Fi и начинает слушать UDP-команды.void loop() { ... };
: Этот код работает в бесконечном цикле после setup(). Он постоянно проверяет, не пришла ли новая команда по UDP. Если пришла, он ее обрабатывает.if (strstr(incomingPacket, "BtA1A=1") != NULL);
: Программа ищет в полученной команде (incomingPacket) определенный текст, например, "BtA1A=1". Если находит, значит, нужно выполнить действие для кнопки с ID A1A (например, включить/выключить первое реле).SetRelays(1, flag_ON[0]);
: Эта строчка вызывает специальную функцию SetRelays, чтобы изменить состояние реле. 1 — это номер реле, flag_ON[0] — его новое состояние (включить или выключить).SendBtColor(0xA1A, 0xFA8072, 0xFF4500);
: Эта функция отправляет команду на ваше управляющее устройство (HMI), чтобы оно изменило цвет кнопки с ID кнопки 0xA1A. (0xFA8072 — цвет 1 и 0xFF4500 — цвет 2) — это коды цветов.digitalWrite(relays[num_relay - 1], ...);
: Это команда, которая физически подает или снимает напряжение с пина реле, заставляя его щелкнуть (включиться или выключиться).Отличие от работы по UART заключается в отправке ведомым устройством кода на смену цвета кнопки при нажатии кнопки SendBtColor(0xA1A, 0xFA8072, 0xFF4500). (Вот почему мы сделали кнопки интерфейса без фиксации: меняем цвет командой от подчиненного устройства). В коде есть массив флагов flag_ON[], который хранит, в каком состоянии сейчас конкретное реле. Контроль за реле и цветом кнопки происходит на подчиненном устройстве, а не на дисплее. Что гарантирует, что устройство и состояние кнопки 100% соответствуют. И если вдруг подчиненное устройство недоступно, то на дисплее не будет происходить изменение состояния кнопки при нажатии. Это гарантированная защита для безопасной работы по беспроводной сети. Также можно добавить функцию автоподключения к Wi-Fi, если вдруг соединение оборвалось. Но это опционально и необходимо только в некоторых случаях.
Управлять можно не только одним устройством и одной группой подключенных реле к одному устройству. На данный момент дисплей поддерживает работу максимум с 6 подчиненными устройствами. И к каждому устройству можно подключить несколько групп реле. Написал оптимальный код и вынес все настройки в начало кода. Код ниже настроен для работы с модулем ESP12F Relay X4.
#define DEBUG 1 // Отладка: 1 - вкл. 0 - выкл. const bool level = 1; // 1 - реле высокого уровня 0 - реле низкого уровня const byte relays_num = 4; // Количество реле byte relays[relays_num] = { 16, 14, 12, 13 }; // Пины подключения реле uint16_t button_id[relays_num] = { 0xA1A, 0xA1D, 0xA20, 0xA23 }; // Адрес кнопок для реле uint16_t button_on_off[2] = { 0xA14, 0xA17 }; // Адрес кнопок: вкл. все, выкл. все реле bool flag_ON[relays_num] = { false }; //сотоянеие реле по умолчанию выкл.
И если вы используете мой пример интерфейса для дисплея, тут менять ничего не нужно. Достаточно загрузить его в плату. В коде можно изменить необходимые параметры или оставить без изменений:
Данный код бесплатно можно скачать в группе для владельцев ATHMI дисплеев или по подписке на Boosty.
Давайте в интерфейс дисплея добавим вторую страницу с 8 кнопками. Учитывая особенность работы по беспроводной сети, нужно, чтобы кнопки были без фиксации. Получим вот такие 2 страницы интерфейса для дисплея.
Изменим шапку кода под управление 8 реле и изменим ID кнопок. Получим такой результат.
const bool level = 0; // 1 - реле высокого уровня 0 - реле низкого уровня const byte relays_num = 8; // Количество реле byte relays[relays_num] = { 15, 2, 4, 5, 18, 19, 21, 22 }; // Пины подключения реле uint16_t button_id[relays_num] = { 0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112 }; // Адрес кнопок для реле uint16_t button_on_off[2] = { 0x114, 0x117 }; // Адрес кнопок: вкл. все, выкл. все реле bool flag_ON[relays_num] = { false }; //сотоянеие реле по умолчанию выкл.
Данный код бесплатно можно скачать в группе для владельцев ATHMI дисплеев или по подписке на Boosty.
Загружаем код в ESP32 и проверяем, как все работает. Также можно добавить еще одну группу реле, как в примере управления реле по UART. А на дисплее сделать 3 страницу и управлять 3 группой реле.
Таким образом можно организовать управление 6 ведомыми устройствами. А так как у нас к одному устройству можно подключить не одну группу, то получается, что можно организовать до 6-12 независимых групп реле. Интерфейс дисплея также позволяет создать до 6 страниц. А если взять дисплей большего размера, то можно вывести большее количество кнопок для управления и организовать работу с 2-3 группами реле на одной странице. Выводы о количестве групп, которыми можно управлять, используя ПО Easy HMI по UDP, делайте сами.
Плюсы и минусы:
UDP позволяет управлять группами реле, расположенных в разных местах, не прокладывая дополнительные провода. А обратная связь позволяет точно определить, какое реле сработало и подключено ли устройство к дисплею. Что гарантирует стабильную и качественную работу.
Но тут есть и ложка дегтя, которая связана как раз с беспроводным способом передачи по UDP. UDP действует по принципу "отправил и забыл" и не заботится о том, доставлен ли пакет или нет. Как раз тут могут возникать ситуации, когда данные не получит подчиненное устройство или ответ от подчиненного устройства не дойдет на дисплей. Но это крайне маловероятно, если соблюдать несколько условий:
Запланированное расширение функционала.
Заключение.
Несмотря на то, что данное решение неприменимо там, где требуется 100% стабильность работы, но для использования в домашней автоматизации и других проектах, управление устройствами по UDP имеет большие перспективы на дальнейшее развитие и внедрение в проекты для личного использования и мелкосерийного производства.
По все вопросам вы можете написать мне в соц. сетях:
Понравился проект Управление реле по UDP: Беспроводное решение с ESP8266, ESP32 и Easy HMI? Не забудь поделиться с друзьями в соц. сетях.
А также подписаться на наш канал на YouTube, вступить в группу Вконтакте, в Telegram.
Спасибо за внимание!
Технологии начинаются с простого!
Фотографии к статье
Файлы для скачивания
![]() |
Код для модуля ESP12F Relay X4 (подойдет также для ESP8266, ESP32).ino | 8 Kb | 18 | Скачать |
![]() |
Интерфейс управления реле в Easy HMI.zip | 25 Kb | 5 | Скачать |
Виджеты для Easy HMI
Читайте также
Мы в соц сетях
Комментарии