Добрый день, уважаемые читатели!
Если вы читали мои статьи про термостат, теплицу, и другие устройства на базе этой же прошивки, то наверное заметили, что в любой такой конструкции присутствует так называемый “системный” светодиод, с помощью которого можно навскидку определить состояние устройства. Многие, наверняка, уже залезли в недра моего г…кода и выяснили, как он мигает в различных случаях и где это просмотреть и изменить. Сам я пока об этом не рассказывал, что ж, исправляю эту оплошность.
Что такое системный светодиод, и зачем он нужен
Устройство на базе ESP32 – штука сложная. К контроллеру, как правило, подключены датчики и исполнительные устройства (реле, ключи и т.д.). Сам контроллер в нормальном состоянии подключен к WiFi, MQTT-брокеру и другим сервисам. Любой из перечисленных компонентов системы в любой момент времени может “отвалиться” по любой причине. Если вы подключены к ESP32 кабелем и смотрите с неё логи с в терминале – то вы без труда определите причину проблем и по возможности сможете устранить её. А что, если устройство давно покинуло рабочий стол и находится в коробочке на месте постоянной дислокации? Конечно, при наличии в устройстве дисплея – можно решить этот вопрос выводом ошибки на дисплей, но – далеко не в каждом устройстве нужен дисплей, да и место на экране “не резиновое”.
Если у вас есть автомобиль, а на этом автомобиле у вас установлена сигнализация, то вы наверное заметили, что индикаторный светодиод мигает не всегда одинаково. Когда охрана отключена – он “молчит”, когда авто просто “на охране” – один режим мигания, когда авто “на автозапуске” – другой режим. Похожие методы часто используют производители и других устройств.
Что-то похожее воспроизвел и я. С помощью одного единственного светодиода можно отображать различные проблемы в работе устройства. Ниже будет рассказано какие именно последовательности что отображают, а также где это можно изменить при необходимости.
Отображаемые состояния
Системный светодиод отображает следующие состояния:
- Нормальное состояние – wifi подключен, mqtt подключен, все службы и датчики работают нормально. В этом случае светодиод вспыхивает один раз в 5 секунд, длительность вспышки – 75 мс.
- Отправка данных – обмен данными с внешним миром может дополнительно индицироваться с помощью внеочередной серии из 3 вспышек длительностью 50 и интервалом между ними 75 мс. После окончания передачи режим мигания будет восстановлен на предыдущий (например нормальный).
- OTA – обновление прошивки – при обновлении прошивки светодиод непрерывно мигает сериями по 3 вспышки длительностью 75 мс с интервалом 250 мс между сериями.
- Что-то пошло не так – общая ошибка, где и что – не совсем понятно,
берем молоток и зубило для исследования. В этом случае светодиод непрерывно мигает с частотой 2 Гц – вспышка 1с, пауза 1с. - Подключение к WiFi – пока соединение с WiFi не установлено, светодиод непрерывно мигает с частотой 20 Гц и скважностью 0,5, то есть 100 мс вспышка и 100 мс – пауза.
- Обновление системного времени – после подключения к сети интернет производится проверка доступа к сети (с помощью ping-а) и получение системного времени с серверов NTP. В этот период светодиод мигает сериями по две вспышки 100 мс с паузой 0,5 с между сериями.
- Нет доступа к сети интернет – если в процессе ping-а выяснится, что подключение к сети сеть, но “интернет кончился”, то светодиод мигает сериями уже по 3 вспышки 100 мс с паузой 0,5 с между сериями.
- Сбой сенсора – если вдруг не удалось пообщаться с каким-либо из сенсоров, который важен для нормального функционирования устройства, то это может быть отображено двумя вспышками длительностью 250 мс с паузой 3 секунды. Увеличенная длительность вспышек позволяет легко отличить их от других режимов.
- Сбой MQTT – при невозможности подключения к MQTT-брокеру (основному и резервному) светодиод мигает сериями по 3 вспышки длительностью 250 мс с паузой 3 секунды.
- Сбой внешних сервисов накопления данных – при невозможности отправки данных на внешние сервисы (ThingSpeak, Народный мониторинг, Open Monitoring и другие) светодиод мигает сериями по 4 вспышки длительностью 250 мс с паузой 3 секунды.
- Сбой telegram – при невозможности отправки сообщения в telegram светодиод мигает сериями по 5 вспышек длительностью 250 мс с паузой 3 секунды.
- Сбой SMTP – при невозможности отправки сообщения электронной почты светодиод мигает сериями по 5 вспышек длительностью 250 мс с паузой 3 секунды. Зарезервировано.
В текущей версии системный светодиод не умеет отображать сразу несколько проблем, поэтому используется некая приоритезация:
- ОТА update
- General error
- Sensors failure
- WiFi state
- Inet available
- Time error
- MQTT error
- OpenMon / NarodMon / ThingSpeak error
- Telegram error
- SMTP error
И только если все это в порядке, то отображается режим Normal mode. После устранения проблемы режим мигания возвращается к предыдущему состоянию – в идеале к нормальному режиму.
Как изменить режимы мигания
Если вас не устраивают перечисленные выше режимы, то вы можете их изменить. Для этого откройте папку C:\Projects\PlatformIO\libs\consts и найдите файл def_led_modes.h. В нем, с помощью макросов препроцессора, обозначены все вышеперечисленные режимы мигания – изменяйте как хотите, но имена макросов должны остаться точно такими, какие они есть:
- #define CONFIG_LEDSYS_xxx_QUANTITY – количество миганий в серии
- #define CONFIG_LEDSYS_xxx_DURATION – длительность вспышки в миллисекундах
- #define CONFIG_LEDSYS_xxx_INTERVAL – длительность паузы между сериями в миллисекундах
По умолчанию индикация передачи данных отключена. Но вы можете задействовать её с помощью макроса CONFIG_SYSLED_SEND_ACTIVITY
, который вы должны будете определить в любом удобном месте в файле project_config.h
:
#define CONFIG_SYSLED_SEND_ACTIVITY 1
Можно, конечно, и в def_led_modes.h этот макрос запихнуть – тогда он будет действовать для всех ваших проектов сразу.
Ссылка на файл: https://github.com/kotyara12/consts/blob/master/def_led_modes.h
Как использовать SysLed в своих корыстных целях
Вы также можете использовать системный светодиод и в своем коде – например добавить “свои” режимы мигания или просто включать светодиод на время выполнения каких-либо операций. Только следует делать это достаточно аккуратно, чтобы не сломать логику основной системы.
Итак, в первую очередь следует добавить #include “reStates.h” – сейчас все функции управления системным светодиодом пока находятся здесь (в будущей версии прошивки они вероятнее всего переедут в другой модуль). Далее вы можете воспользоваться одной из следующих функций:
- void ledSysOn(const bool fixed); – включить системный светодиод в постоянном режиме
- void ledSysOff(const bool fixed); – отменить постоянный режим
- void ledSysSet(const bool newState); – переключить постоянный режим (по сути это универсальная замена ledSysOn и ledSysOff)
- void ledSysSetEnabled(const bool newEnabled); – разрешить или запретить работу системного светодиода. Используется при переключении тихого режима
- void ledSysActivity(); – обозначить активность устройства (быстренько-шустренько помигать три раза)
- void ledSysFlashOn(const uint16_t quantity, const uint16_t duration, const uint16_t interval); – помигать заданное количество раз и успокоиться, интервал задает интервал между импульсами
- void ledSysBlinkOn(const uint16_t quantity, const uint16_t duration, const uint16_t interval); – включить режим постоянного мигания с заданным количеством импульсов в серии и паузой между сериями
- void ledSysBlinkOff(); – отключить режим постоянного мигания
Более подробно про все эти режимы я когда-то писал здесь, можете ознакомиться более подробно. Стоит только помнить, что для системного светодиода режим постоянного мигания в приоритете, и библиотека всегда запоминает последний режим мигания. Поэтому ledSysOn + ledSysOff вызовет не гашение светодиода, а возврат к последнему режиму мигания. Для того, чтобы полностью погасить светодиод, нужно дополнительно вызвать ledSysBlinkOff() еще раз – вот тогда будет отменен последний сохраненный режим мигания.
Ссылка на библиотеку reLed: https://github.com/kotyara12/reLed
Ссылка на библиотеку reStates: https://github.com/kotyara12/reStates
Ночной (тихий) режим
Если устройство установлено в жилом помещении, то вспышки светодиода могут мешать сну и раздражать в ночное время. Дабы устранить это недоразумение, предусмотрен “тихий” режим, который отключает индикацию и звуки в ночное время. По умолчанию эта опция гасит только системных светодиод, но можно отключать и другие светодиоды и экраны, а также, например, звуки.
Ночной режим определяется с помощью макросов CONFIG_SILENT_MODE_ENABLE и CONFIG_SILENT_MODE_INTERVAL, первый определяет доступность данной опции в прошивке, второй – интервал времени суток для тихого режима в ЧЧММ-ЧЧММ, по умолчанию это 22000600UL или 22:00-06:00 в нормальном представлении. После запуска устройства это значение записывается в память, и в дальнейшем им можно управлять через MQTT (как любым параметром устройства), для этого используется пара топиков %location%/%device%/config/silent_mode/timespan и %location%/%device%/confirm/silent_mode/timespan. При этом вы можете спокойно использовать интервалы “с переходом через 0”. Для отключения опции можно установить интервал 00:00-00:00, для включения на все время 00:00-24:00 (да, да, именно так).
В случае использования только одного единственного системного светодиода больше ничего, собственно, и не требуется. В прошивке уже есть весь необходимый код. А вот если вам необходимо “погасить” дополнительные экран или светодиод, то нужно поймать специальные сообщения о переключении тихого режима.
Делается это так. В начале необходимо написать обработчик событий для RE_TIME_SILENT_MODE_ON и RE_TIME_SILENT_MODE_OFF:
static void sensorsTimeEventHandler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { if (event_id == RE_TIME_SILENT_MODE_ON) { // Начало тихого режима - отключаем звуки через активный зуммер ledTaskSend(buzzer, lmEnable, 0, 0, 0); } else if (event_id == RE_TIME_SILENT_MODE_OFF) { // Окончание тихого режима - разрешаем звуки через активный зуммер ledTaskSend(buzzer, lmEnable, 1, 0, 0); }; ... }
Здесь в качестве примера использовано “гашение” звуков активного зуммера, но для светодиода всё выглядит в точности так же. Очень походим образом можно погасить подсветку экрана, например. В данном конкретном случае все довольно просто, потому как функция ledTaskSend сама по себе своя собственная потокобезопасна, и поэтому не требуется дополнительных ухищрений и синхронизаций.
Затем необходимо зарегистрировать наш обработчик (один раз, разумеется):
eventHandlerRegister(RE_TIME_EVENTS, ESP_EVENT_ANY_ID, &sensorsTimeEventHandler, nullptr);
Вот, собственно и всё. Когда наступит время начала или окончания системный шедулер разошлет системное оповещение, наша функция его прочитает и выполнит всё, что требуется.
На этом разрешите откланяться, надеюсь материал был вам полезен. С сами был Александр aka kotyara12. Благодарю за внимание.
💠 Полный архив статей вы найдете здесь
Пожалуйста, оцените статью:
Самое сложное (для меня, во всяком случае) – запомнить и не забыть через неделю, какой режим мигания что означает. Я бы предложил индицировать двумя цифрами по азбуке Морзе, а рядом с устройством – памятка с описанием
Это да, согласен ?
Но поверьте – запомнить сложно только первое время. Потом привыкаешь. Особенно когда устройств в доме перевалило за десяток