Я создавал подобные проекты для дисплея Nextion и сделал серию уроков для него. Затем создал аналогичный проект для дисплея DWIN. Пришло время сделать такой же проект для своего дисплея AT HMI. Создавать интерфейс буду в разработанном мной программном обеспечении Easy HMI. Подробнее о данной программе я рассказывал ранее, а также о том, как можно управлять дисплеем по UART и какие команды для этого уже есть. А сегодня на практике используем полученные знания и создадим наш замечательный проект.
Важно! Easy HMI работает исключительно с дисплеями AT HMI.
Последняя версия Easy HMI и Datasheet на дисплеи AT HMI.
Создаем интерфейс в Easy HMI.
Создание интерфейса для дисплея AT HMI сейчас достаточно простой процесс. Нужно просто добавить в проект виджеты, расставить их как нужно и, при необходимости, изменить цвет элементов, надписи, размер текста и размер линий. И всё – интерфейс для проекта готов. При этом один и тот же виджет можно использовать для разных проектов и дисплеев с разным разрешением. Для данного проекта я сделаю интерфейсы для дисплеев 2,8 дюйма с разрешением 320х240 пикселей и для 3,5-дюймового дисплея с разрешением 480х320 пикселей. Скачать исходные материалы можно внизу статьи в разделе «Файлы для скачивания». Несмотря на значительную разницу в разрешении этих дисплеев, переделать пришлось только модульные виджеты (они содержат большое количество компонентов и сделаны в виде самостоятельного модуля). Как создавать виджеты, я расскажу в уроках.
Используемые модули для интерфейса дисплея 3,5 дюйма:
- #8 – Кнопка включения
- #10 – Кнопка выбор цвета
- #52 – Плашка с закруглением – синего цвета
- #152 – Модуль яркость, громкость
- #153 – Модуль смены режима -2
Список используемых модулей для дисплея 2,8 дюйма вы можете посмотреть самостоятельно, открыв проект, который находится в прикреплённом файле внизу статьи. Эти и другие модули можно скачать вместе с программой Easy HMI и попробовать создать свой интерфейс. Посмотреть, что получится, можно в эмуляторе – не обязательно покупать дисплей для тестирования и проверки работы этого ПО.
Пример добавления виджета в проект.
Давайте рассмотрим, как происходит добавление виджетов в проект на примере добавления кнопок изменения цвета подсветки. Для этого нужно нажать на кнопку «Загрузить виджет».
В открывшемся окне выбираем виджет «10 – Кнопка выбор цвета».
Виджет добавлен в проект, но он расположится в левом верхнем углу эмулятора со стандартными параметрами цвета и текста.
Как переместить его на нужную позицию нашего интерфейса? Для этого кликнем по родительскому элементу, который следует сразу за названием виджета «10 – Кнопка выбор цвета», в данном случае это кнопка.
И меняем позицию кнопки – тем самым изменяем и позицию самого виджета со всеми вложенными элементами. Также здесь же можно изменить размер кнопки и другие параметры. Строка ниже (3) позволяет редактировать текст кнопки.
Цвет кнопки здесь изменить нельзя. Чтобы создавать кнопки разного цвета, нужно изменять цвет при редактировании виджета. Это можно делать параллельно с созданием проекта. Для этого переходим во вкладку «Виджеты» и видим, что у нас уже открыт виджет, который мы только что добавили в проект. Да, последний добавленный виджет в проект автоматически открывается для редактирования.
Здесь нам нужно изменить цвета и, если требуется, другие параметры. Например, для дисплея другого размера нужно изменить размер кнопки и размер текста. Всё, теперь можно добавить кнопку в проект.
Да, немного неудобно изменять цвет и другие параметры, к которым нет доступа в настройках элементов проекта. Но эти параметры легко подправить в виджете, и при этом в проекте не нужно выводить много параметров, которые могут запутать новичка.
Программа находится в стадии постоянной доработки, так что в ходе создания новых проектов будут добавлены новые возможности, которые упростят процесс создания интерфейса.
В проекте есть модульные виджеты. Они содержат в себе несколько кнопок, линий, фигур и текст. Такие виджеты менее универсальны, но позволяют создавать более интересные проекты и тратить на создание гораздо меньше времени. Хотя, для того чтобы упростить процесс, эти модули можно разбить на несколько самостоятельных виджетов.
Схема подключения дисплея AT HMI к Arduino UNO + WS2812.
Схема подключения будет аналогичной для Arduino NANO, Arduino Pro Mini и т.д.
Схема подключения дисплея AT HMI к ESP8266 + WS2812.
Схема подключения нарисована для Wemos D1 mini, но она будет аналогичной для других плат на базе модуля ESP-12E, ESP-12F, ESP-12S, таких как: NodeMCU, WeMos и т.д.
Код для Arduino, WeMos (ESP8266).
Код для Arduino, ESP8266 и других микроконтроллеров будет состоять из функций для работы с дисплеем по UART и код для работы с адресными светодиодами. О командах UART для работы с дисплеем я рассказывал в предыдущей статье. Сейчас сделаем удобные функции, чтобы можно было пользоваться ими при создании проектов не только для Arduino, WeMos, но и для других отладочных плат на других микроконтроллерах. Например, переделать данный пример под ESP32 не составит большого труда. Я стараюсь, чтобы код был максимально простым и универсальным.
Код разделил на 3 вкладки, чтобы было удобнее с ним работать и было понятно, какой код для какой цели написан.
На основной вкладке led_ATHMI_3_5-ESP8266_1_1.ino
располагаются основные настройки и функции setup()
и loop()
.
На вкладке display.ino
находятся функции для работы с дисплеем. Основные функции, которые помогают отправлять данные на дисплей для изменения свойств элементов на дисплее, находятся внизу вкладки. Все функции подписаны, и написан пример, какую команду функция отправляет на дисплей.
Вверху над страницей находится массив строк с названиями световых эффектов, которые нужны для работы со светодиодами. Их нужно прописать здесь, так как в коде работы с дисплеем мы отправляем на дисплей название световых эффектов.
На вкладке led.ino
, наверное, понятно из названия, находятся функции для работы с адресными светодиодами. Код с данной вкладки я не буду объяснять в этой статье, так как о работе со светодиодами я рассказывал уже много раз в своих предыдущих проектах. Вы можете ознакомиться с ними здесь.
Несмотря на то, что код старался не усложнять, написал один массив с адресами кнопок на дисплее. Если вы откроете эмулятор и выставите вывод ID кнопок, то увидите, что это за кнопки.Кстати, скопировать ID элемента очень просто – достаточно кликнуть по нему левой кнопкой мыши.
uint16_t array_btn[] = {0xA1F, 0xA22, 0xA25, 0xA28, 0xA2B, 0xA2E, 0xA31, 0xA34}; // Адреса кнопок
Также эти ID используются для обработчика команд нажатия на кнопки изменения цвета подсветки. Но я прописал их полностью в коде, не используя массив, чтобы было более понятно. При необходимости можно упростить код и использовать массив для обработки данных с кнопок. Сделаю пример, как это реализовать, в уроках.
Разбор кода, полученные данные от дисплея.
Функция ReadSerial()
читает данные из порта и, при получении конца строки, данные передаёт в функцию AnalyseString()
, где происходит обработка полученных команд. А именно, мы получаем информацию о нажатии кнопок и нажатии кнопок с фиксацией.
Кнопка включения имеет 2 состояния, так как она с фиксацией. Нажали – пришла команда 1
в конце. Нажали повторно – пришла команда с 0
в конце. Как я объяснял в статье о командах UART, команда состоит из стартовых символов, ID кнопки и после знака равенства – состояние кнопки.
Аналогично работают кнопки переключения цвета подсветки. Для кнопки без фиксации обрабатываем только нажатое состояние, т.е. команду в конце с 1
. Вот так просто обработать данные, полученные с дисплея при нажатии кнопок.
Отправляем данные на дисплей.
Для отправки данных, как я уже упоминал ранее, написал функции, которые позволяют с лёгкостью сформировать команду для отправки на дисплей. Вам не нужно писать их самостоятельно – достаточно только добавить эти функции в свой проект, например, в конец кода, и использовать их для управления элементами на дисплее.
Кнопка включения и выключения подсветки.
Начнём с кнопки включения подсветки. Здесь у меня 2 функции для работы с линиями: первая функция изменяет толщину линии, вторая изменяет цвет линии.
SendLnWidth(0xA03, 8);
SendLnColor(0xA02, 0xCCCCCC);
Вернее, двух линий, так как иконка нарисована из двух линий. В функцию передаём ID элемента в HEX формате (число в шестнадцатеричной системе счисления 0xA03). Второй параметр – это ширина линии (8) , у второй функции – это цвет линии также в HEX формате RGB888 (0xCCCCCC). Этот формат достаточно распространён, и можно получить цвет с помощью любого графического редактора или сайта для подбора цвета и палитры.
Остальные функции в данном блоке кода для работы с адресными светодиодами.
flag_off_led = true; // блакируем изменения яркости с кнопко ярче и темнее
last_brightnessLED = brightnessLED;
brightnessLED = 0; // первоначальная яркость
FastLED.setBrightness(25.5 * brightnessLED); // Яркость 0%
Кнопки переключения эффектов.
Передают название эффектов из массива.
SendTxTxt(0xA1B, phrases[last_effect]); // устанавливаем текст на плашке с id 0xA18
Для этого в функцию передаётся ID элемента текста на дисплее в HEX формате и текст из массива также по его индексу строки phrases[last_effect]. Здесь можно просто написать текст в кавычках для отправки текста на дисплей по аналогии с тем, что сделано в блоке setup()
. SendTxTxt(0xA18, "Статический цвет");
– это позволяет убедиться, что при старте программы будет точно установлен режим «статический цвет».
Остальные функции работают по аналогии. В некоторых функциях кроме посля ID передаётся больше, чем один параметр. Например, для смены цвета кнопки и плашки нужно передать 2 цвета для создания градиента. Если не нужно создавать градиент, передавать всё равно нужно 2 цвета, но одного значения, например, белый RGB888 = #FFFFFF
.
//== изменяем цвет плашки num_element = id, data_color = 0xFFFFFF, data_color2 = 0xCCCCCC
void SendPlTColor(uint16_t num_element, uint32_t data_color, uint32_t data_color2) {
String data_txt_local = "pl." + String(num_element, HEX) + ".col=" + String(data_color, HEX) + ";" + String(data_color2, HEX) + "\n"; // pl.A03.col=000000;CCCCCC\n
mySoftwareSerial.print(data_txt_local); // Отправляем
num_element = 0; // Очищаем переменную
data_color = 0;
data_color2 = 0; // Очищаем переменную
}
//== изменяем Размер плашки num_element = id, data_width = 200, data_height = 100
void SendPlSize(uint16_t num_element, uint16_t data_width, uint16_t data_height) {
String data_txt_local = "pl." + String(num_element, HEX) + ".siz=" + String(data_width) + ";" + String(data_height) + "\n"; // pl.A03.siz=200;100\n
mySoftwareSerial.print(data_txt_local); // Отправляем
num_element = 0; // Очищаем переменную
data_width = 0;
data_height = 0; // Очищаем переменную
}
Работаем с массивом адресов кнопок изменения цвета подсветки.
Как я рассказывал ранее, у нас есть массив адресов кнопок, он нужен, чтобы отслеживать, какую кнопку нажали, чтобы её заблокировать и с предыдущей кнопки снять блокировку. Без массива здесь не обойтись.
uint16_t array_btn[] = {0xA1F, 0xA22, 0xA25, 0xA28, 0xA2B, 0xA2E, 0xA31, 0xA34}; // Адреса кнопок
Да, нажатия кнопок прописаны «в лоб», и обработка массива немного нелогична. Но для читабельности кода и чтобы было проще понять, что делает код, сделал так. В уроке напишу, как уменьшить код с использованием массива для отсеивания нажатия на кнопку.
//--- изменяем цвет статического режима --- //
if ((incStr.indexOf("BtA1F=1") >= 0)) {
if (last_effect > 0) // если педыдущий режим был не статический цвет
{
SendTxTxt(0xA1B, phrases[0]);
last_effect = 0; // ставим эффект на статический цвет
}
SendBtSnus(array_btn[last_color] , 0); // снимаем блок с пред. кнопки
SendPlSwich(array_btn[last_color], 0); // возвращаем кнопку в изночальное положения
last_color = 0; // изменяем цвет на 1 в массиве CRGB Colors_p[]
SendBtSnus(array_btn[last_color], 1); // ставим блок на текущ. кнопку
}
if ((incStr.indexOf("BtA22=1") >= 0)) {
if (last_effect != 0) // если педыдущий режим был не статический цвет
{
SendTxTxt(0xA1B, phrases[0]);
last_effect = 0; // ставим эффект на статический цвет
}
SendBtSnus(array_btn[last_color], 0); // снимаем блок с пред. кнопки
SendPlSwich(array_btn[last_color], 0); // возвращаем кнопку в изночальное положения
last_color = 1; // изменяем цвет на 1 в массиве CRGB Colors_p[]
SendBtSnus(array_btn[last_color], 1); // ставим блок на текущ. кнопку
}
При нажатии на кнопку «смены цвета» нам нужно первым делом проверить, какой режим был включен. Если не «статический», то меняем надпись – это у нас первый элемент массива с текстом режимов. Функция будет выглядеть так: SendTxTxt(0xA1B, phrases[0]);
.
Затем снимаем блокировку с предыдущей кнопки, так как кнопка с фиксацией, её нужно вернуть в не нажатое состояние. Для этого служит вторая функция SendPlSwich(array_btn[last_color], 0);
Затем нам нужно заблокировать текущую кнопку. Для этого в переменную last_color = 1;
сохраняем номер текущей кнопки в массиве ID. Как видим, здесь мы можем сравнить с массивом, какая кнопка нажата – это играет роль отладки кода. А при нажатии другой кнопки смены цвета мы знаем, какая была нажата ранее, и повторяем процедуру, которая описана выше.
SendBtSnus(array_btn[last_color], 0); // снимаем блок с пред. кнопки
SendPlSwich(array_btn[last_color], 0); // возвращаем кнопку в изночальное положения
last_color = 1; // изменяем цвет на 1 в массиве CRGB Colors_p[]
SendBtSnus(array_btn[last_color], 1); // ставим блок на текущ. кнопку
В проекте мы использовали не все функции, которые прописаны для работы с элементами на дисплее. Вы можете использовать их в своих проектах. Также дописать по аналогии недостающие функции для управления элементами, опираясь на команды из статьи: «Описание UART протокола для Easy HMI 0.1.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
mySoftwareSerial.print(data_txt_local); // Отправляем
num_element = 0; // Очищаем переменную
data_txt = ""; // Очищаем переменную
}
//== изменяем состояние кнопки с фиксацией (не применимо для кнопки без фиксации) num_element = id, data_swi = 0/1
void SendPlSwich(uint16_t num_element, bool data_swi) {
String data_txt_local = "bt." + String(num_element, HEX) + ".swi=" + String(data_swi) + "\n"; //bt.A1F.swi=1\n
mySoftwareSerial.print(data_txt_local); // Отправляем
num_element = 0; // Очищаем переменную
data_swi = 0; // Очищаем переменную
}
//== блакируем кнопки с фиксацией и без фиксации num_element = id, data_stt = 0/1
void SendBtSnus(uint16_t num_element, bool data_stt) {
String data_txt_local = "bt." + String(num_element, HEX) + ".stt=" + String(data_stt) + "\n"; // bt.A06.stt=1\n
mySoftwareSerial.print(data_txt_local); // Отправляем
num_element = 0; // Очищаем переменную
data_stt = 0; // Очищаем переменную
}
//== изменяем цвет плашки num_element = id, data_color = 0xFFFFFF, data_color2 = 0xCCCCCC
void SendPlTColor(uint16_t num_element, uint32_t data_color, uint32_t data_color2) {
String data_txt_local = "pl." + String(num_element, HEX) + ".col=" + String(data_color, HEX) + ";" + String(data_color2, HEX) + "\n"; // pl.A03.col=000000;CCCCCC\n
mySoftwareSerial.print(data_txt_local); // Отправляем
num_element = 0; // Очищаем переменную
data_color = 0;
data_color2 = 0; // Очищаем переменную
}
//== изменяем Размер плашки num_element = id, data_width = 200, data_height = 100
void SendPlSize(uint16_t num_element, uint16_t data_width, uint16_t data_height) {
String data_txt_local = "pl." + String(num_element, HEX) + ".siz=" + String(data_width) + ";" + String(data_height) + "\n"; // pl.A03.siz=200;100\n
mySoftwareSerial.print(data_txt_local); // Отправляем
num_element = 0; // Очищаем переменную
data_width = 0;
data_height = 0; // Очищаем переменную
}
//== Изменяем ширину линии num_element = id, data_wdt = 6
void SendLnWidth(uint16_t num_element, uint8_t data_wdt) {
String data_txt_local = "ln." + String(num_element, HEX) + ".wdt=" + String(data_wdt) + "\n"; // ln.A08.wdt=6\n
mySoftwareSerial.print(data_txt_local); // Отправляем
num_element = 0; // Очищаем переменную
data_wdt = 0; // Очищаем переменную
}
//== изменяем цвет линии num_element = id, data_color = 0xFFFFFF
void SendLnColor(uint16_t num_element, uint32_t data_color) {
String data_txt_local = "ln." + String(num_element, HEX) + ".col=" + String(data_color, HEX) + "\n"; // ln.A03.col=000000\n
mySoftwareSerial.print(data_txt_local); // Отправляем
num_element = 0; // Очищаем переменную
data_color = 0;
}
// перходим на другой экран data_screen = 2
void SendScreen(uint16_t data_screen) {
String data_txt_local = "sc.1.num=" + String(data_screen) + "\n"; // sc.1.num=2\n
mySoftwareSerial.print(data_txt_local); // Отправляем
data_screen = 0; // Очищаем переменную
}
На этом всё. Более подробно будем разбираться с работой дисплеев AT HMI и программным обеспечением EasyHMI в уроках. В уроках поэтапно расскажу, как создать этот проект и подробно опишу функции для работы с дисплеем.
По все вопросам вы можете написать мне в соц. сетях:
Понравился проект Руководство по созданию панели управления WS2812 на базе AT HMI и Arduino? Не забудь поделиться с друзьями в соц. сетях.
А также подписаться на наш канал на YouTube, вступить в группу Вконтакте, в Telegram.
Спасибо за внимание!
Технологии начинаются с простого!
Фотографии к статье
Файлы для скачивания
|
Библиотеки для проекта.zip | 364 Kb | 23 |
Скачать
Вы можете скачать файл.
|
|
Код для Arduino и дисплея 3,5.zip | 6 Kb | 21 |
Скачать
Вы можете скачать файл.
|
|
Код для ESP8266 и дисплея 3,5.zip | 6 Kb | 23 |
Скачать
Вы можете скачать файл.
|
|
Код для ESP8266 и дисплея 2.8.zip | 6 Kb | 23 |
Скачать
Вы можете скачать файл.
|
|
Программа Easy HMI 0.1.1 с виджетами и проектами.zip | 1800 Kb | 23 |
Скачать
Вы можете скачать файл.
|
Комментарии