В статье [1] были рассмотрены общие принципы создания графического web-интерфейса (WebUI) систем беспроводного дистанционного управления (ДУ) на основе Wi-Fi-модуля NodeMCU v3 и приведён простой пример конкретной реализации WebUI для управления бытовой техникой. Важными аспектами в реализации и эксплуатации распределённых систем управления (РСУ) в целом являются функциональные возможности:
- местного управления оборудованием с одновременной передачей данных на WebUI для отображения (автоматическая синхронизация в направлении сервер-клиент);
- сохранения настроек оборудования и других данных в локальном ППЗУ.
Внедрение этих возможностей в рассмотренное устройство [1] существенно повысит его эксплуатационные свойства и даст представление об особенностях их реализации, в том числе и в промышленных целях.
В нашем случае в устройство управления бытовым вентилятором добавляются функции местного управления скоростью вращения с помощью кнопки, расположенной на его корпусе, передачи текущего значения скорости в WebUI с использованием технологии AJAX и сохранения этого значения в ППЗУ модуля NodeMCU для последующего включения без использования WebUI.
Изменения, вносимые в принципиальную схему, минимальны, поэтому она не приводится. Следует лишь добавить кнопку с контактами на замыкание и са-мовозвратом, которую надо установить между выводом D5 NodeMCU (на схеме не показан) и любым из выводов (контактов) GND. Рекомендуется также подключить параллельно контактам кнопки конденсатор ёмкостью 0,1..0,22 мкФ для подавления дребезга.
В большей степени изменения затронули программную часть сервера. На всех этапах программирования NodeMCU по-прежнему используется Arduino IDE, все установки для работы с платформой ESP8266 подробно описаны в [1]. Код серверной части приведён в файле FanControl3.ino.
Для обработки нажатий на кнопки задействован механизм прерываний. Особенностью работы с ESP8266 в Arduino IDE является обязательная инициализация всех функций обработки прерываний перед процедурой setup() с помощью инструкции, подобной этой:
void ICACHE_RAM_ATTR manSpdCtrl();
//init ISR function
В этом случае инициализируется функция ручного управления скоростью manSpdCtrl(). Далее, внутри процедуры setup() обычным образом назначается обработчик прерывания по спаду высокого уровня на выводе SPD_PIN:
attachInterrupt(digitalPinToInterru pt(SPD_PIN), manSpdCtrl, FALLING).
Отметим, что предварительно SPD_PIN активирован как вход с "подтяжкой" с помощью функции pinMode(SPD_PIN, INPUT_PULLUP), поэтому подключения внешнего "подтягивающего" резистора не требуется.
Сама функция обработки прерывания предельно лаконична, что соответствует требованиям, предъявляемым к такого рода функциям:
void manSpdCtrl(){
//флаг ручного управления скоростью
manCtrl = true;
}
Здесь только устанавливается соответствующий флаг, а логическая обработка нажатий на кнопку происходит в основном цикле:
if (manCtrl) {
if (pwmOut < N_PWM) pwmOut++; else pwmOut = 0;
eeWrite();
manCtrl = false;
}
Как видно, процедура обработки проста и циклически увеличивает при каждом нажатии переменную pwmOut, определяющую коэффициент программной ШИМ и собственно скорость вращени я. Подробно о необходимости введения программной ШИМ и алгоритме её реализации рассказано в [1].
Отсюда же вызывается функция eeWrite(), служащая для записи в ППЗУ установленного значения переменной pwmOut. Она содержит стандартную последовательность инструкций:
void eeWrite() {
//запись в EEPROM byte 0
EEPROM.write(0, pwmOut); EEPROM.commit();
}
Вызов метода commit() является обязательным. С его помощью подтверждается запись всех данных, ранее подготовленных с помощью метода write(). Естественно, перед работой с функциями EEPROM необходимо подключить соответствующую библиотеку <EEPROM.h> в секции #include и выделить область памяти в 1 байт методом EEPROM.begin(1) в процедуре setup(). Там же происходит чтение сохранённых данных при запуске устройства:
//считывание сохранённого значения скорости
pwmOut = EEPROM.read(0);
if (pwmOut > N_PWM) { //чистая память
pwmOut = 0;
eeWrite(); //запись pwmOut в память
powerOn = false;
}
Если выделенная область памяти ни разу не использовалась (при первом включении считывается значение FF), в неё записываются нули, и устройство находится в выключенном статусе до первой команды на запуск, т. е. до изменения параметра скорости.
Рассмотрим теперь изменения в коде программы клиентской части на примере файла index.html, содержимое которого загружается с сервера в пользовательский интерфейс в обработчике запроса корневого URL:
void handleRoot() {
//отправка индексной html-страницы
server.send(200, "text/html", idx_page);
}
В этом случае строковая переменная idx_page содержит html-код индексной веб-страницы. Сама переменная idx_page назначается в процедуре setup() с помощью макроса F, который определяет, что содержимое переменной будет загружено во флэш-память с целью высвобождения ОЗУ. HTML-код в отформатированном удобочитаемом виде с комментариями приведён в файле index.htm. "Чистый" html-код, помещаемый в переменную idx_page, приведён в файле index_.htm.
Изменения кода index.htm незначительны, так как он создавался в расчёте на перспективное внедрение новых функций. Для автоматического обновления данных (параметра скорости) в WebUI используется технология AJAX, не требующая перезагрузки всей страницы. Посколькуjs-функция loadParms() уже используется для первичной загрузки параметров с сервера по событию <body onload>, достаточно добавить её вызов по таймеру для периодического обновления данных. Для этого реализован таймер:
lettimerId = setTimeout(function t() { loadParms();
timerId = setTimeout(t, 2000);
}, 2000);
Период опроса составляет 2 с (2000 мс). Это является оптимальным эмпирическим значением для автоматической системы управления технологическим процессом в целом.
Помимо этого, из интерфейса удалён чекбокс ON|OFF. Для отключения устройства достаточно установить ноль параметра скорости с помощью регулятора скорости или локальной кнопкой. Включение происходит при любом значении скорости, отличном от нуля. Внешний вид обновлённого интерфейса показан на рисунке.
Внешний вид обновлённого интерфейса
Соответственно из кода клиентской и серверной частей удалены функции обработки состояния чекбокса On | OFF. Отметим также, что программное обеспечение в целом подверглось заметной оптимизации кода, который снабжён достаточно подробными комментариями, поэтому полное его описание приводить не будем.
Схема, конструкция, применяемые детали и налаживание подробно описаны в [1]. Кнопка управления скоростью может быть применена любая слаботочная без фиксации, например, RWD-304, DS-316 [2]. Её устанавливают на корпусе устройства.
Дополнительный конденсатор - К10-17б или аналогичный керамический (или плёночный) ёмкостью 0,1...0,22 мкФ. Его желательно разместить ближе к контактам платы NodeMCU.
Упомянутая в тексте программа находится здесь.
Литература
1.Панкратьев Д. Web-интерфейс Wi-Fi ДУ на модуле NodeMCU. - Радио, 2020, № 12, с. 44-47.
2.Кнопки DS-316. - URL: https:// asenergi.com/catalog/knopki/ds/ds-316.html (07.09.22).
Автор: Д. Панкратьев, г. Ташкент, Узбекистан