Управление 8–16 реле с сенсорного дисплея в Easy HMI и Arduino, ESP32.

Ранее я уже создавал проекты по управлению реле с использованием сенсорных дисплеев DWIN и Nextion. Реализация этих проектов не представляет большой сложности. Для этого требуется отрисовывать графику, правильно её нарезать и предварительно изучить недружелюбную документацию, в случае DWIN. С помощью программы Easy HMI это можно сделать гораздо быстрее. Создать проект можно минут за 20–30. Также для данного проекта я написал максимально простой код с минимумом массивов и циклов, что позволит новичку изменять и расширять проект. Также я написал второй, более сложный вариант кода с управлением двумя группами реле. Все настройки вынес в начало кода. Но обо всем по порядку.


Создаем интерфейс управления реле для дисплея в среде разработки Easy HMI.


Важно! Easy HMI предназначена в первую очередь для дисплеев AT HMI, но также поддерживает и некоторые дисплеи сторонних производителей.

Как вы уже, знаете, Easy HMI поддерживает не только наши фирменные дисплеи ATHMI, но и некоторые сторонние дисплеи и кастомные решения на базе TFT + ESP32, подробнее тут. Загружаем или обновляем прошивку для дисплея при необходимости.

В программе EasyHMI 0.1.1 TFT

Сделать это можно прямо из программы Easy HMI. И приступаем к созданию интерфейса, проверяя результат на дисплее в режиме реального времени. Что нельзя делать ни на одном известном мне HMI-дисплее! Приступаем к созданию самого интерфейса, он у меня уже сделан.

Приступаем к созданию самого интерфейса, он у меня уже сделан.

Вы можете создать свой интерфейс, сделать это достаточно просто, тем более есть наборы готовых виджетов. Я потратил 20 минут времени на создание одностраничного интерфейса, при том что создавал несколько дополнительных виджетов. Получился вот такой результат.

Тут 8 круглых кнопок с фиксацией, которые отвечают за включение и выключение реле.

Тут 8 круглых кнопок с фиксацией, которые отвечают за включение и выключение реле. И 2 кнопки без фиксации: Включить все реле и Выключить все реле. И добавил плашку с заголовком. Тут можно написать свой текст, например: Свет в доме, Управление подсветкой, Управление светом в цехе и пр.

Схема подключения ATHMI к ESP32 + 8 реле.

Схема подключения ATHMI к ESP32.

Схема подключения ESP32-2432S028 к ESP32 + 8 реле.

Схема подключения ESP32-2432S028 к ESP32.

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

Схема подключения ATHMI к Arduino NANO + 8 реле.

Схема подключения ATHMI к Arduino NANO.

Схема подключения ESP32-2432S028 к Arduino NANO + 8 реле.

Схема подключения ESP32-2432S028 к Arduino NANO.

Данный проект можно реализовать на других микроконтроллерах и отладочных платах: Arduino MEGA, Arduino UNO, ESP8266 и пр. Схема подключения изменится не сильно.

Схема подключения ATHMI к ESP32 + 8 реле.

Код для проекта "Управление реле с сенсорного дисплея".

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

Простой неоптимизированный код для ESP32.

Для разделения кода по логике и наглядности я разделяю код на вкладки. Когда открываете код, скачанный с сайта, обязательно папку нужно разархивировать. Открываем файл 8_relays_lite.ino в Arduino IDE, откроется 2 вкладки: 8_relays_lite и display.

 в Arduino IDE, откроется 2 вкладки: 8_relays_lite и display.

На вкладке 8_relays_lite расположены переменные и основные блоки setup() и loop(). А на вкладке display — код для работы с дисплеем. В начале кода можно поменять несколько параметров или оставить без изменений:

  • DEBUG - Отвечает за вывод в монитор порта отладочной информации. 1 - вкл., 0 - выкл.
  • Level – отвечает за тип подключённого реле. 1 - реле высокого уровня, 0 - реле низкого уровня.
  • relays_num – Количество подключённых реле. Максимум 16.
  • relays[relays_num] – массив пинов, к которым подключены реле.

Если вам нужно увеличить количество подключённых реле, для этого необходимо поменять переменную relays_num и дописать пины дополнительно подключённых реле в массиве relays[relays_num]. Также для дисплея нужно будет добавить кнопки управления и добавить логику обработки нажатия кнопок на вкладке display.

Если вам нужно увеличить количество подключённых реле, для этого необходимо поменять переменную relays_num

Это нужно делать, так как код не оптимизирован и является простым вариантом кода.

Это нужно делать, так как код не оптимизирован и является простым вариантом кода.

Скачать код можно внизу статьи в разделе «Файлы для скачивания».

На вкладке display прописана обработка нажатия кнопки с фиксацией для каждого состояния. При получении команды с Кнопки " Включить все" используется функция SendBtSwich(0xA04, 1);

// Пример отправки команды для перевода кнопки в нажатое состояние
SendBtSwich(0xA04, 1);
// где 0xA04 — ID элемента (кнопки)
// 1 — состояние кнопки с фиксацией (1 - кнопка в нажатом состоянии, 0 - в отпущеном состоянии)
    SendBtSwich(0xA04, 1); // изменяем состояние кнопки с фиксацией
    SendBtSwich(0xA06, 1);
    SendBtSwich(0xA08, 1);
    SendBtSwich(0xA0A, 1);
    SendBtSwich(0xA0C, 1);
    SendBtSwich(0xA0E, 1);
    SendBtSwich(0xA10, 1);
    SendBtSwich(0xA12, 1);

Тут мы по очереди отправляем для каждой кнопки смену состояния на "нажатое". Чтобы получить ID кнопки, его можно скопировать в эмуляторе в Easy HMI: достаточно кликнуть по ID нужной кнопки, и он будет скопирован в буфер обмена.

Чтобы получить ID кнопки, его можно скопировать в эмуляторе в Easy HMI: достаточно кликнуть по ID нужной кнопки

Затем просто вставим данный ID в код.

// Цикл для включения всех реле
for (byte i = 1; i <= relays_num; i++) {
  SetRelays(i, 1); // Вызов функции включения i-го реле
}
// Функция SetRelays(i, 1) отправляет команду на включение реле,
// перебирая массив пинов relays[relays_num], к которым подключены реле.
....
void SetRelays(uint8_t num_relay, bool flag_relay) {
  digitalWrite(relays[num_relay-1], level == 0 ? !flag_relay : flag_relay);
}

Затем идет цикл, который включает все реле. Функция SetRelays(i, 1) отправляет команду на включение реле, по очереди перебирая массив пинов relays[relays_num], к которым подключены реле. Отключение всех реле происходит аналогично.

//--- Кнопка Выкл. Все --- //
  if ((incStr.indexOf("BtA17=1") >= 0)) {  //--- кнопка в нажатом сотоянии
    SendBtSwich(0xA04, 0); // изменяем состояние кнопки с фиксацией
    SendBtSwich(0xA06, 0);
    SendBtSwich(0xA08, 0);
    SendBtSwich(0xA0A, 0);
    SendBtSwich(0xA0C, 0);
    SendBtSwich(0xA0E, 0);
    SendBtSwich(0xA10, 0);
    SendBtSwich(0xA12, 0);
    for (byte i = 1; i <= relays_num; i++) {
      SetRelays(i, 0);
    }
  }

Внизу страницы кода написаны функции, которые позволят работать с элементами дисплея.

// --== Функции для отправки данных на дисплей ==---//
//== отправка текста num_element = id, data_txt = "текст"
void SendTxTxt(uint16_t num_element, String data_txt) {
  String data_txt_local = "tx." + String(num_element, HEX) + ".txt=" + data_txt + "\n";  // tx.A09.txt=Привет\n
  Serial2.print(data_txt_local);                                                         // Отправляем
}
//== изменяем состояние кнопки с фиксацией (не применимо для кнопки без фиксации)  num_element = id, data_swi = 0/1
void SendBtSwich(uint16_t num_element, bool data_swi) {
  char buffer_local[16];
  snprintf(buffer_local, sizeof(buffer_local), "bt.%X.swi=%d\n", num_element, data_swi ? 1 : 0);  //bt.A1F.swi=1\n
  Serial2.print(buffer_local);                                                                    // Отправляем
}
//== блакируем кнопки с фиксацией и без фиксации  num_element = id, data_stt = 0/1
void SendBtSnus(uint16_t num_element, bool data_stt) {
  char buffer_local[16];
  snprintf(buffer_local, sizeof(buffer_local), "bt.%X.stt=%d\n", num_element, data_stt ? 1 : 0);  // bt.A06.stt=1\n
  Serial2.print(buffer_local);                                                                    // Отправляем
}
//== изменяем Размер кнопки  num_element = id, data_width = 200, data_height = 100
void SendBtSize(uint16_t num_element, uint16_t data_width, uint16_t data_height) {
  char buffer_local[25];
  snprintf(buffer_local, sizeof(buffer_local), "bt.%X.siz=%d;%d\n", num_element, data_width, data_height);  // pl.A03.siz=200;1000\n
  Serial2.print(buffer_local);                                                                              // Отправляем
}
//== изменяем цвет кнопки num_element = id, data_color = 0xFFFFFF, data_color2 = 0xCCCCCC
void SendBtColor(uint16_t num_element, uint32_t data_color, uint32_t data_color2) {
  char buffer_local[40];
  snprintf(buffer_local, sizeof(buffer_local), "bt.%X.col=%08lX;%08lX\n", num_element, data_color, data_color2);  // bt.A03.col=000000;CCCCCC\n
  Serial2.print(buffer_local);                                                                                    // Отправляем
}
//== изменяем цвет плашки  num_element = id, data_color = 0xFFFFFF, data_color2 = 0xCCCCCC
void SendPlColor(uint16_t num_element, uint32_t data_color, uint32_t data_color2) {
  char buffer_local[40];
  snprintf(buffer_local, sizeof(buffer_local), "pl.%X.col=%08lX;%08lX\n", num_element, data_color, data_color2);  // // pl.A03.col=000000;CCCCCC\n
  Serial2.print(buffer_local);                                                                                    // Отправляем
}
//== изменяем Размер плашки  num_element = id, data_width = 200, data_height = 100
void SendPlSize(uint16_t num_element, uint16_t data_width, uint16_t data_height) {
  char buffer_local[25];
  snprintf(buffer_local, sizeof(buffer_local), "pl.%X.siz=%d;%d\n", num_element, data_width, data_height);  // pl.A03.siz=200;1000\n
  Serial2.print(buffer_local);                                                                              // Отправляем
}
//== Изменяем ширину линии  num_element = id, data_wdt = 6
void SendLnWidth(uint16_t num_element, uint8_t data_wdt) {
  char buffer_local[16];
  snprintf(buffer_local, sizeof(buffer_local), "ln.%X.wdt=%d\n", num_element, data_wdt);  // ln.A08.wdt=6\n
  Serial2.print(buffer_local);                                                            // Отправляем
}
//== изменяем цвет линии  num_element = id, data_color = 0xFFFFFF
void SendLnColor(uint16_t num_element, uint32_t data_color) {
  char buffer_local[25];
  snprintf(buffer_local, sizeof(buffer_local), "ln.%X.col=%08lX\n", num_element, data_color);  // ln.A03.col=000000\n
  Serial2.print(buffer_local);                                                                 // Отправляем
}
//== перходим на другой экран  data_screen = 2
void SendScreen(uint16_t data_screen) {
  char buffer_local[12];
  snprintf(buffer_local, sizeof(buffer_local), "sc.1.num=%d\n", data_screen);  // sc.1.num=2\n
  Serial2.print(buffer_local);                                                 // Отправляем
}

Тут их больше, чем используется в проекте, для того чтобы вы могли расширить возможности вашего проекта. Также вы можете самостоятельно написать другие функции на основе команд управления дисплеем по UART. Так легко создать управление реле. Вы можете изменить проект и использовать свой интерфейс управления. Для адаптации проекта достаточно изменить ID элементов на ID из вашего интерфейса. Как я описал выше, достаточно просто кликнуть по ID нужного элемента и заменить его в коде. Я думаю, с этим сложности не должно возникнуть.

Простой неоптимизированный код для Arduino NANO (UNO).

В коде не будет больших изменений, только изменится подключение по UART, для этого будем использовать библиотеку SoftwareSerial.

Пины подключения дисплея:

// Подключаем библиотеку для программной эмуляции Serial порта
#include <SoftwareSerial.h>
// Определяем пины для SoftwareSerial
#define MYPORT_TX 2  // Пин TX дисплея подключается к этому пину Arduino
#define MYPORT_RX 3  // Пин RX дисплея подключается к этому пину Arduino
// Создаём объект SoftwareSerial и передаём номера управляющих пинов RX и TX
SoftwareSerial mySerial(MYPORT_RX, MYPORT_TX); // RX, TX

И массив подключения реле также изменится:

// Пины подключения реле к Arduino NANO/UNO
byte relays[relays_num] = {4, 5, 6, 7, 8, 9, 10, 11};

Остальной код без существенных изменений. Скачать код можно внизу статьи в разделе «Файлы для скачивания».


Код для ESP32: управление двумя независимыми группами реле.

Данный код я сделал максимально оптимальным, и все необходимые настройки для управления двумя группами реле вынес в настройки вверху программы.

//=========== Настройки Группы реле 1 ===========//
const bool level = 0;       // Тип реле: 1 - высокий уровень (HIGH), 0 - низкий уровень (LOW)
const byte relays_num = 8;   // Количество реле в группе 1
uint8_t relays[relays_num] = {15, 2, 4, 5, 18, 19, 21, 22};  // Пины ESP32, к которым подключены реле группы 1
uint16_t button_id[relays_num] = {0xA04, 0xA06, 0xA08, 0xA0A, 0xA0C, 0xA0E, 0xA10, 0xA12}; // ID кнопок в Easy HMI для управления реле группы 1
// ID кнопок "Включить все" и "Выключить все" для группы 1
uint16_t button_on_off[2] = {0xA14, 0xA17}; // {ID вкл. все, ID выкл. все}
//=========== Конец настроек Группы 1 ===========//

В коде можно изменить все необходимые параметры или оставить без изменений:

  • DEBUG - Отвечает за вывод в монитор порта отладочной информации. 1 - вкл., 0 - выкл.
  • level – отвечает за тип подключённого реле для группы 1. 1 - реле высокого уровня, 0 - реле низкого уровня.
  • relays_num – Количество подключённых реле в группе 1. Максимум 16.
  • relays[relays_num] – массив пинов ESP32, к которым подключены реле группы 1.
  • button_id[relays_num] – массив ID кнопок управления реле группы 1. Менять не нужно, если используете мой интерфейс.
  • button_on_off[2] - Массив ID кнопок: button_on_off[0] (0xA14) - вкл. все, button_on_off[1] (0xA17) - выкл. все реле для группы 1.

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

//=========== Настройки Группы реле 2 ===========//
const bool level_2 = 1;     // Тип реле: 1 - высокий уровень (HIGH), 0 - низкий уровень (LOW)
const byte relays_num_2 = 8;// Количество реле в группе 2
// Пины ESP32, к которым подключены реле группы 2
uint8_t relays_2[relays_num_2] = {13, 12, 14, 27, 26, 25, 33, 32};
// ID кнопок в Easy HMI для управления реле группы 2
uint16_t button_id_2[relays_num_2] = {0x104, 0x106, 0x108, 0x10A, 0x10C, 0x10E, 0x110, 0x112};
// ID кнопок "Включить все" и "Выключить все" для группы 2
uint16_t button_on_off_2[2] = {0x114, 0x117}; // {ID вкл. все, ID выкл. все}
//=========== Конец настроек Группы 2 ===========//

Схема подключения ATHMI к ESP32 + 16 реле.

Количество и тип реле можно изменять для каждой группы. Например, для первой сделать 10 реле, а для второй 8.

Количество и тип реле можно изменять для каждой группы. Например, для первой сделать 10 реле, а для второй 8. Первая группавысокоуровневые реле, а втораянизкоуровневые реле. Также я прокомментировал весь код, и можно продублировать код группы и создать 3, 4 и 5 независимую группу. Данный код бесплатно можно скачать в группе для владельцев ATHMI дисплеев или по подписке на Boosty.

Количество и тип реле можно изменять для каждой группы. Например, для первой сделать 10 реле, а для второй 8.

Схема подключения ATHMI к ESP32 + 16 реле.

Управление большим количеством реле (в теории до 32–50 реле).

Без расширителя пинов к ESP32 не подключить большое количество реле. А вот к Arduino MEGA можно подключить в теории до 50 реле, так как данная плата имеет 53 цифровых входа/выхода.

А вот к Arduino MEGA можно подключить в теории до 50 реле, так как данная плата имеет 53 цифровых входа/выхода.

И код переписывать не нужно, так как у Arduino MEGA доступен аппаратный UART2. Но на практике данное количество реле я не подключал, так что 100% гарантии дать не могу, что все заработает без проблем "из коробки".

Интерфейс для управления двумя группами реле.

Для управления второй группой реле на странице 1 в программе Easy HMI я создал интерфейс по аналогии с главной страницей. И добавил кнопки для перехода между страницами. Получился вот такой результат. По аналогии можно создать другие дополнительные страницы управления. При этом на странице можно сделать разнообразную компоновку групп управления; общие кнопки включения/выключения можно добавлять, а можно и не добавлять. Получается неплохая база для создания разнообразных структур управления силовой нагрузкой.

Подведём итог.

Я постарался сделать максимально универсальный код, чтобы его можно было использовать с разными платами: Arduino UNO, Arduino NANO, Arduino MEGA, ESP32, ESP8266. Кроме этого, реализовал поддержку реле разного типа: высокоуровневого и низкоуровневого.

Интерфейс для управления двумя группами реле.

По все вопросам вы можете написать мне в соц. сетях:

Понравился проект Управление 8–16 реле с сенсорного дисплея в Easy HMI и Arduino, ESP32? Не забудь поделиться с друзьями в соц. сетях.

А также подписаться на наш канал на YouTube, вступить в группу Вконтакте, в Telegram.

Спасибо за внимание!

Технологии начинаются с простого!

Фотографии к статье

Файлы для скачивания

Простой код для Arduino NANO (UNO) Простой код для Arduino NANO (UNO).zip3 Kb 37 Скачать
Простой код для ESP32 Простой код для ESP32.zip3 Kb 36 Скачать
Интерфейс управления реле в Easy HMI Интерфейс управления реле в Easy HMI.zip8 Kb 41 Скачать

Комментарии

Ваше Имя*


Разработка проектов