По факту: 30-контактная ESP32 (GPIO16/17 подписаны RX2/TX2, не номерами), готовый модуль DHT22 с проводами оранжевый/жёлтый/зелёный (VCC/DATA/GND), один 2-канальный релейный модуль (SRD-05VDC-SL-C×2, общий разъём GND/IN1/IN2/VCC) — закрывает sensor-1/light-1/pump-1. Канал под fan-1 в прошивке заложен (GPIO18), но физически ещё не куплен — явно отмечено. Пины в config.h.example не менялись, только комментарий про RX2/TX2.
12 KiB
growbox (ESP32-контроллер)
Прошивка для реального ESP32, обслуживающая зону "Гроубокс" платформы
home_automatization. Одна плата владеет четырьмя
устройствами: sensor-1 (DHT22) и три реле-актуатора — light-1, pump-1,
fan-1.
Протокол (MQTT, mosquitto из docker-compose платформы, порт 1883)
devices/{device_id}/telemetry— публикует контроллер, JSON{"device_id","zone_id","sensor_type","value","timestamp"}, timestamp — RFC3339 UTC.sensor-1шлёт по одному сообщению наtemperatureиhumidityраз вTELEMETRY_INTERVAL_MS.devices/{device_id}/commands— подписывается контроллер (wildcarddevices/+/commands, фильтрует по своим 3 актуаторам), JSON{"action":"turn_on"|"turn_off"|"set_level","level"?}.devices/{device_id}/ack— публикует контроллер после применения команды, JSON{"state":{"power":"on"|"off","level"?}}.
Реального диммирования нет (обычные реле), поэтому set_level трактуется как
порог: level > 0 включает реле, level <= 0 выключает.
device_id в конфиге должны совпадать с devices.external_id, засеянными в
Laravel (DemoGrowboxSeeder использует sensor-1/fan-1), а zone_id — с
zones.id зоны "Гроубокс" в Postgres.
Железо
По фото реального комплекта: 30-контактная ESP32 DevKit, готовый модуль
DHT22 с распаянными проводами и один 2-канальный релейный модуль
(SRD-05VDC-SL-C×2, общий разъём GND IN1 IN2 VCC) — закрывает sensor-1,
light-1, pump-1. Для fan-1 нужен ещё один канал реле (третий модуль или
4-канальная плата) — в прошивке/config.h он уже заложен на GPIO18, физически
пока не подключён.
| Назначение | Пин (по умолчанию) | Примечание |
|---|---|---|
| DHT22 DATA | GPIO4 | провод жёлтый на нашем модуле |
| Реле IN1 — light-1 | GPIO16 | на шёлкографии платы подписан RX2, не «16» |
| Реле IN2 — pump-1 | GPIO17 | на шёлкографии платы подписан TX2, не «17» |
| Реле IN — fan-1 | GPIO18 | нужен третий канал реле, пока не подключено |
На этой конкретной 30-пиновой плате GPIO16/17 не подписаны номерами — они
выведены как пины UART2 и промаркированы RX2/TX2. Физически это те же
GPIO, config.h/прошивку менять не нужно, важно только не перепутать их при
пайке/монтаже на плате.
Реле-модуль (2-канальный, SRD-05VDC-SL-C) активен по LOW —
RELAY_ACTIVE_LOW в config.h уже стоит в true. Перемычка JD-VCC на
модуле по умолчанию установлена (питание катушек реле — от той же VCC, без
гальванической развязки) — для этого проекта этого достаточно, снимать её
незачем.
DHT22 требует подтягивающий резистор ~10кОм между DATA и VCC — на нашем модуле, похоже, уже встроен (компактная плата-переходник с 3 проводами), но если показания не читаются — проверьте отдельным резистором.
Схема подключения
ESP32 (30 pin)
┌───────────────────────┐
DHT22 DATA ───────┤ GPIO4 │
(жёлтый провод) │ │
│ │
Реле IN1 (light-1)─┤ GPIO16 (на плате: RX2)
Реле IN2 (pump-1) ─┤ GPIO17 (на плате: TX2)
Реле IN (fan-1) ──┤ GPIO18 ← пока не подключено
│ │
3V3 ────┤ 3V3 │
GND ────┤ GND │
USB/5V ─┤ VIN │
└───────────────────────┘
DHT22 (готовый модуль, 3 провода):
оранжевый(+/VCC) -> 3V3 жёлтый(out/DATA) -> GPIO4 зелёный(-/GND) -> GND
Реле, 2-канальный модуль (разъём GND IN1 IN2 VCC):
VCC -> VIN (5V) GND -> GND (общий с ESP32)
IN1 -> GPIO16/RX2 (light-1) IN2 -> GPIO17/TX2 (pump-1)
⚠️ Реле коммутируют цепь самой нагрузки (свет/насос/вентилятор, обычно
12V/220V) через винтовые клеммы COM/NO/NC каждого канала — это
ОТДЕЛЬНАЯ силовая цепь со своим источником питания, к GPIO ESP32 она не
подключается. К плате идёт только сигнальный IN каждого канала.
Библиотеки
Через Arduino Library Manager (Sketch → Include Library → Manage Libraries):
PubSubClient(Nick O'Leary) — MQTT-клиентArduinoJson(Benoit Blanchon, v7) — сериализация/парсинг JSONDHT sensor library(Adafruit) + зависимостьAdafruit Unified Sensor- Board support:
esp32(Espressif Systems) через Boards Manager
WebServer (веб-интерфейс) и WiFi идут в комплекте с board support
esp32 — отдельно ставить не нужно.
Веб-интерфейс
Каждая плата поднимает у себя простую страницу и JSON API на порту 80 — удобно наблюдать/управлять локально, не дожидаясь Laravel/MQTT:
GET /— HTML-страница: показания DHT22 + кнопки Вкл/Выкл для light-1/pump-1/fan-1.GET /api/state— JSON{"sensor":{"has_reading","temperature","humidity"},"devices":{"light-1":{"power"},...}}.POST /api/command— JSON-тело{"device_id","action","level"?}, тот же формат, что и в MQTT-команде.
Команда с веб-UI применяется через тот же код и публикует тот же ack в
devices/{id}/ack, что и команда из device-control-service — device shadow
платформы (Redis) не расходится с реальным состоянием железа независимо от
того, кто его переключил.
Включается/выключается флагом ENABLE_WEB_UI в config.h (1/0) — при
0 HTTP-сервер не поднимается вообще, порт 80 не слушается. У сервера нет
авторизации — только для локальной сети, как и mosquitto платформы; для
выхода за пределы LAN сначала нужно добавить хотя бы Basic Auth.
Настройка и прошивка через Arduino IDE
- Поддержка ESP32. Arduino IDE → Settings → «Additional boards manager
URLs» → добавить:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - Ядро. Tools → Board → Boards Manager → найти
esp32→ установить пакетesp32 by Espressif Systems. - Библиотеки. Tools → Manage Libraries → поставить по одной:
PubSubClient,ArduinoJson(v7),DHT sensor library(IDE предложит доустановить зависимостьAdafruit Unified Sensor— согласиться). - Скетч. File → Open →
controllers/growbox/growbox.ino— остальные.h/.cppподхватятся вкладками автоматически. - Конфиг.
cp config.h.example config.h, заполнить Wi-Fi SSID/пароль, IP хоста с поднятымdocker composeплатформы (mosquitto слушает0.0.0.0:1883— доступен по IP машины в локальной сети),zone_idиdevice_id. Если IDE уже была открыта — переоткрыть скетч. - Плата и порт. Подключить ESP32 по USB (кабель именно с передачей
данных). Tools → Board → esp32 →
ESP32 Dev Module(или точная модель). Tools → Port → появившийся/dev/cu.usbserial-*//dev/cu.SLAB_USBtoUART. - Заливка. Кнопка Upload. Часть плат просит зажать кнопку
BOOTна плате до появления точек соединения в логе. - Проверка. Serial Monitor, 115200 бод — лог подключения к Wi-Fi/NTP/MQTT/веб-сервера, публикации телеметрии/команд и IP платы для похода в веб-интерфейс.
Если не заливается:
- порта нет в списке — нужен драйвер USB-UART моста платы (CP2102 обычно ставится сам на современной macOS, CH340 — вручную);
Failed to connect to ESP32/No serial data received— зажатьBOOTна плате на время заливки;- заливка обрывается или очень долгая — Tools → Upload Speed → понизить с 921600 до 115200.
Сборка через arduino-cli (если не через IDE)
arduino-cli core install esp32:esp32
arduino-cli lib install "PubSubClient" "ArduinoJson" "DHT sensor library"
arduino-cli compile --fqbn esp32:esp32:esp32 growbox
arduino-cli upload --fqbn esp32:esp32:esp32 -p /dev/cu.usbserial-XXXX growbox
На macOS arduino-cli по умолчанию ставит библиотеки в
~/Documents/Arduino/libraries — если этот каталог защищён sandbox'ом
(Operation not permitted при установке библиотек, встречалось в среде этого
агента), перенаправьте sketchbook в доступное место:
arduino-cli config set directories.user ~/путь/без/ограничений. Через саму
Arduino IDE (GUI-приложение) это обычно не требуется — она сама запрашивает
нужные разрешения у macOS.
Проверка end-to-end
При работающем docker compose в home_automatization и засеянных
Postgres-данных (зона + sensor-1/light-1/pump-1/fan-1):
- телеметрия должна доходить до ClickHouse через ingest-service;
- команда через Laravel UI (или напрямую через
grpcurlв device-control-service) должна прийти на плату и вызвать щелчок реле, а затем ack — обновитьreported_state/last_seenв Redis device shadow.