ESP32 DevKit v1 · pinport · взяли себе: 1
готово
⋮

Автополив и фитолампа на ESP32: веб-админка и MQTT

Третий вариант прибора: к веб-админке ESP32 добавлен MQTT. Состояние — климат, лампа, насосы, всё расписание — уходит брокеру, команды «полить», «остановить», новое расписание и время приходят из тем …/set, а Home Assistant находит прибор сам. Экран, ручка и страница в браузере остались.

Что на схеме

Плата ESP32 DevKit v1, к ней подключены:

  • Реле — rl1
  • Реле — rl2
  • Реле — rl3
  • Ввод 230 В — in
  • Автоматический выключатель — qf1
  • Выключатель одноклавишный — sw1
  • Светильник 230 В — la1, тип: импульсный
  • Блок питания 12 В — ps
  • Тумблер — sw2
  • Тумблер — sw3
  • Мотор 12 В — m1
  • Мотор 12 В — m2
  • LCD 16x2 (I2C) — lcd1
  • Часы реального времени DS3231 (I2C) — rtc1
  • Датчик HTU21D: температура и влажность (I2C) — ht1, влажность 45 %, температура 23.5 °C
  • Энкодер KY-040 (ручка с кнопкой) — enc1

Задействованы выводы платы: 3V3, GND, D21, D22, D18, D19, D5, D25, D26, D27. Всего соединений на схеме: 43.

MQTT

Прибор подключается к брокеру и держит там своё состояние; команды принимает из тем …/set. В модели любой адрес брокера ведёт на встроенный брокер PinPort — всё, что уходит и приходит, видно на вкладке «MQTT» внизу, и оттуда же можно публиковать. На железе впишите в BROKER адрес своего Mosquitto или брокера Home Assistant, а в MQTT_USER и MQTT_PASSWORD — пользователя MQTT.

Что прибор публикует (BASE = pinport/greenhouse):

  • BASE/status — online, а при обрыве связи брокер сам ставит offline (завещание, retain);
  • BASE/climate — {"t":23.5,"h":45} раз в 10 секунд;
  • BASE/lamp — on / off при смене, retain;
  • BASE/pump/1, BASE/pump/2 — on / off при смене, retain;
  • BASE/state — всё состояние в JSON (то же, что /api/state у страницы): при каждой смене и раз в минуту.

Какие команды принимает:

  • BASE/pump/1/set — on полить сейчас, off остановить;
  • BASE/settings/set — те же поля, что у формы страницы: lampOff=20:00, s1=120&period1=2, left2=0; меняется только то, что передано;
  • BASE/time/set — секунды местного времени, как у кнопки «Часы по этому компьютеру».

Поля настроек страница и MQTT разбирают одной функцией (applySetting), поэтому пределы у них одинаковые: секунды 5…995, период 1…9 дней, «осталось» не больше периода.

Home Assistant

С HA_DISCOVERY = true при каждом подключении прибор публикует объявления в homeassistant/…/config (retain), и Home Assistant заводит устройство «Автополив» сам: датчики температуры и влажности, фитолампу (вкл/выкл) и два выключателя «Насос P1», «Насос P2». Выключатель насоса в Home Assistant — это полить сейчас или остановить; расписание по-прежнему живёт в приборе и работает без Home Assistant и без сети.

Веб-админка, экран и ручка

Всё как у варианта «с веб-админкой»: страница с состоянием, расписанием, «Полить сейчас» и часами по времени браузера — теперь ещё и с карточкой «MQTT: на связи». Экран и ручка — как у версии на Nano; в модели ими удобнее управлять с пульта в углу схемы. Настройки, изменённые с ручки, со страницы или по MQTT, сохраняются в NVS и сразу уходят брокеру в BASE/state.

Как считается полив

«Осталось дней» уменьшается при смене суток (номер суток хранится в NVS — пропущенные выключенным прибором сутки засчитываются). Счётчик дошёл до нуля и наступил час — насос качает заданное число секунд, счётчик снова равен периоду. Включённый позже часа полива прибор польёт сразу.

Силовая часть и отличия от железа

Схема та же: лампа — от сети через qf1, sw1, rl1; насосы — от блока 12 В через sw2/sw3 и rl2/rl3; цепи 230 В и 12 В считаются раздельно. В модели LCD и реле питаются от 3V3 — на железе берите для них 5 В с VIN; реле с оптронами часто включаются низким уровнем — константа RELAY_ON. Сеть не подключилась за 15 секунд — точка доступа Greenhouse (страница на 192.168.4.1); MQTT тогда молчит, а расписание работает.

Библиотеки

Пример собирается с библиотеками:

  • WiFi
  • WebServer
  • Preferences
  • PubSubClient
  • LiquidCrystal I2C
  • RTClib
  • Adafruit BusIO

Они уже установлены на сервере сборки — отмечать их в проекте вручную не нужно, список приезжает вместе с примером.

Как это устроено в коде

Основное, чем пользуется скетч:

  • WebServer — веб-сервер прямо на плате: страницы и обработчики адресов
  • Preferences — хранение настроек во flash, переживает перезапуск
  • RTClib — работа с часами реального времени
  • LiquidCrystal_I2C — текстовый экран 16×2 по двум проводам
  • DS3231 — точные часы с собственным термокомпенсированным генератором
  • digitalRead() — читает уровень на выводе
  • delay() — пауза, на время которой ядро занято ожиданием
  • constrain() — зажимает значение в границах
  • WiFiClient — TCP-соединение с сервером
  • millis() — миллисекунды с запуска: на них строят работу без остановки
  • Serial.printf() — печатает в монитор порта с форматированием
  • Serial.println() — печатает строку в монитор порта

В скетче 750 строк; свои функции: loadSettings(), saveSettings(), onEncoder(), htuRead(), readClimate(), lampShouldBeOn(), startPump(), stopPump(); подключено заголовков: 7. Сам скетч открыт на соседней вкладке — его можно менять и запускать заново.

Что попробовать изменить

  1. Нажмите «Запустить»: сценарий дождётся сети, поставит часы на 19:59:40 и переведёт P1 на «полить сегодня»; после 20:00 он включит P2 командой MQTT и погасит лампу, поменяв расписание через pinport/greenhouse/settings/set.
  2. Откройте вкладку «MQTT»: там pinport/greenhouse/status, climate раз в 10 секунд, lamp, pump/1, pump/2 и state, а в homeassistant/… — объявления для Home Assistant.
  3. Опубликуйте в pinport/greenhouse/pump/1/set текст off — полив P1 остановится, мотор m1 на схеме встанет, в pump/1 уйдёт off.
  4. Откройте «Веб-интерфейс»: карточка «MQTT: на связи»; поменяйте в форме время насоса — новое состояние тут же уйдёт в pinport/greenhouse/state.
  5. Опубликуйте в pinport/greenhouse/settings/set строку s2=30&period2=1&left2=0 — насос P2 станет поливать каждый день по 30 секунд, и сегодня польёт сразу, если час уже настал.

Смотрите также

← Все примеры галереи

Схема
Проект из галереи — запускать можно, менять нельзя.

      
Сборка ещё не запускалась.

    Печатайте в Serial числа — они станут графиком. Serial.println(t); — один ряд, Serial.printf("t:%.1f h:%.1f\n", t, h); — два с подписями. Формат тот же, что понимает плоттер Arduino IDE.