Прошивка Wemos D1 Mini для мониторинга трёх насосов: OLED, веб-панель, webhook-уведомления, сброс Wi-Fi кнопкой. Адрес webhook задаётся через веб-панель и хранится в EEPROM; в исходнике не хранится, так как содержит секретный токен. Добавлены README.md (техдокументация) и MANUAL.md (руководство). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
11 KiB
Pump Controller v8.2 (OLED)
Контроллер мониторинга насосной станции на Wemos D1 Mini (ESP8266).
Следит за состоянием трёх насосов (два основных + резервный), выдаёт сухие контакты аварии, показывает статус на OLED-дисплее, публикует веб-панель в локальной сети и отправляет события на HTTPS-webhook (n8n).
1. Состав репозитория
| Файл | Назначение |
|---|---|
pump_controller_8_2_OLED_DONE.ino |
Весь прошивочный код (single-file Arduino sketch) |
README.md |
Техническая документация (этот файл) |
MANUAL.md |
Руководство пользователя / монтажника |
2. Аппаратная часть
2.1 Плата
Wemos D1 Mini (ESP8266, 4 МБ Flash). Питание 5 В по microUSB или 3.3 В на пин 3V3.
2.2 Распиновка
| Пин | Имя в коде | Режим | Логика |
|---|---|---|---|
D5 |
IN_PUMP_1 |
INPUT_PULLUP |
LOW = насос 1 работает |
D6 |
IN_PUMP_2 |
INPUT_PULLUP |
LOW = насос 2 работает |
D7 |
IN_PUMP_EMERGENCY |
INPUT_PULLUP |
LOW = резервный насос работает |
D3 |
BTN_WIFI_RESET |
INPUT_PULLUP |
LOW (замыкание на GND) = кнопка нажата |
D8 |
OUT_ALARM_MAIN |
OUTPUT |
HIGH = авария основных насосов |
D0 |
OUT_ALARM_EMERGENCY |
OUTPUT |
HIGH = работает резерв |
D1 |
I2C SDA | — | OLED |
D2 |
I2C SCL | — | OLED |
Замечания по особенностям ESP8266:
D3(GPIO0) иD8(GPIO15) участвуют в выборе режима загрузки.D8должен быть подтянут к GND при старте — не вешайте на него нагрузку, тянущую пин вверх. Кнопку наD3при старте держать нажатой нельзя (плата уйдёт в режим прошивки).D0(GPIO16) не имеет внутреннего pull-up (только pull-down) и не поддерживает прерывания — используется только как выход.
2.3 Дисплей
SSD1306 128×64, I2C, адрес по умолчанию 0x3C (константа OLED_ADDR).
Если экран не найден — в лог уходит сообщение, прошивка продолжает работать
без дисплея (oledOK = false).
2.4 Подключение датчиков
Датчик — сухой контакт (реле пускателя, датчик потока, контакт КМ). Замкнут на GND → насос считается работающим. Внешние резисторы не нужны, используется внутренняя подтяжка.
3. Зависимости
Устанавливаются через Arduino Library Manager:
- Adafruit SSD1306
- Adafruit GFX Library
- WiFiManager (tzapu)
Входят в ESP8266 core: ESP8266WiFi, ESP8266WebServer, ESP8266HTTPClient,
WiFiClientSecure, EEPROM, Wire.
Board: LOLIN(WEMOS) D1 R2 & mini, Upload speed 921600, Flash size 4MB.
4. Логика работы
4.1 Антидребезг
updatePumpState() для каждого входа:
если чтение изменилось -> сбросить таймер lastDebounceTime
если чтение стабильно > 3000 мс -> зафиксировать stableState
debounceDelay = 3000 мс — длинный намеренно: фильтрует пусковые дребезги
пускателя и кратковременные просадки.
4.2 Готовность системы
systemReady становится true через debounceDelay + 500 мс после старта.
До этого момента аварии не формируются и webhook не отправляется — иначе
при включении питания система рапортовала бы ложную аварию.
4.3 Основная авария
Условие: оба основных насоса стоят (!p1 && !p2).
bothStopped -> запуск таймера mainAlarmStartTime
выдержка alarmDelay = 5000 мс
-> OUT_ALARM_MAIN = HIGH
-> webhook {"event":"MAIN PUMPS","status":"ALARM"} (однократно)
любой насос запустился
-> OUT_ALARM_MAIN = LOW
-> webhook {"event":"MAIN PUMPS","status":"OK"} (однократно)
Суммарная задержка от факта остановки до аварии: 3 с (дребезг) + 5 с
(выдержка) ≈ 8 секунд.
4.4 Резервный насос
Реакция без дополнительной выдержки, сразу после стабилизации входа:
pE = работает -> OUT_ALARM_EMERGENCY = HIGH, webhook EMERGENCY PUMP / STARTED
pE = стоит -> OUT_ALARM_EMERGENCY = LOW, webhook EMERGENCY PUMP / STOPPED
Флаги mainAlarmSent / emergencyActiveSent гарантируют отправку ровно
одного webhook на каждый переход состояния.
5. Webhook
POST на webhook_url, Content-Type: application/json:
{"event":"MAIN PUMPS","status":"ALARM","device":"Wemos_D1_Pump"}
event |
status |
|---|---|
MAIN PUMPS |
ALARM / OK |
EMERGENCY PUMP |
STARTED / STOPPED |
TLS-соединение поднимается через WiFiClientSecure с setInsecure() —
сертификат сервера не проверяется. Достаточно для отправки в доверенную
локальную/корпоративную инфраструктуру, но не защищает от MITM.
Отправка синхронная и блокирующая: на время POST (до нескольких секунд при недоступном сервере) основной цикл приостанавливается. Дисплей в этот момент не обновляется.
6. Хранение настроек (EEPROM)
Эмулируемая EEPROM, 256 байт.
| Адрес | Размер | Содержимое |
|---|---|---|
0 |
2 | Magic 0xA55A — признак инициализации |
2 |
220 | Webhook URL, \0-терминированный |
При первом старте (magic не совпал) записывается значение константы
webhook_url_default — она намеренно пустая, чтобы секретный токен не попадал
в исходник и в git. Пока URL не задан через /set_webhook, sendPostWebhook()
сразу выходит и пишет в лог [HTTP] Webhook URL не задан.
Учётные данные Wi-Fi хранит WiFiManager в своей области флеша, не в этой EEPROM.
7. Веб-интерфейс
Сервер на порту 80.
| Маршрут | Метод | Описание |
|---|---|---|
/ |
GET |
HTML-панель мониторинга |
/status |
GET |
JSON {"p1":0,"p2":0,"pE":0} |
/reset_wifi |
POST |
Стереть настройки Wi-Fi и перезагрузиться |
/set_webhook |
POST |
Параметр url (≤220 симв.), сохранить в EEPROM |
Панель опрашивает /status каждые 2 секунды и перезагружает страницу при
изменении состояния. Шрифты подгружаются с Google Fonts — при отсутствии
интернета у клиента интерфейс отрисуется системным моноширинным шрифтом.
Аутентификации нет: любой в той же сети может сбросить Wi-Fi и подменить webhook. Контроллер рассчитан на изолированный технологический сегмент.
8. OLED
Обновление раз в секунду (DISPLAY_INTERVAL).
PUMP CONTROLLER v8
────────────────────────
PUMP 1 : RUNNING
PUMP 2 : STOPPED
BACKUP : STANDBY
────────────────────────
192.168.1.42
STATUS: OK
Строка статуса:
| Условие | Текст |
|---|---|
!systemReady |
INIT... |
| оба основных стоят | !! ALARM: NO PUMPS !! (инверсия, мигание 500 мс) |
| работает резерв | WARN: BACKUP RUNNING |
| иначе | STATUS: OK |
9. Кнопка сброса Wi-Fi
Пин D3, удержание BTN_HOLD_MS = 3000 мс. Во время удержания на дисплее
рисуется прогресс-бар с обратным отсчётом. По достижении порога —
wm.resetSettings() и ESP.restart(). Отпускание до порога отменяет операцию.
10. Известные ограничения
setInsecure()— TLS без проверки сертификата.- Веб-интерфейс и
/reset_wifiне защищены паролем. - Webhook отправляется синхронно и блокирует цикл; при недоступном сервере реакция контроллера замедляется на время таймаута.
- События, произошедшие без Wi-Fi, не буферизуются — webhook просто теряется
(в лог пишется
[HTTP] Нет Wi-Fi). - Логика аварии — «оба стоят»: остановка одного насоса штатной ситуацией не считается и никак не сигнализируется.
- Webhook URL хранится в EEPROM в открытом виде и отдаётся веб-панелью всем, кто может её открыть. Если URL содержит секретный токен — доступ к панели равносилен доступу к токену.
11. Сборка
arduino-cli compile --fqbn esp8266:esp8266:d1_mini pump_controller_8_2_OLED_DONE.ino
arduino-cli upload -p COM3 --fqbn esp8266:esp8266:d1_mini pump_controller_8_2_OLED_DONE.ino
Монитор порта: 115200 бод.