Files
cacto 4fcca2701b Уточнить README по фото реального комплекта железа
По факту: 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.
2026-08-18 04:18:18 +05:00

181 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# growbox (ESP32-контроллер)
Прошивка для реального ESP32, обслуживающая зону "Гроубокс" платформы
[home_automatization](../../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` — подписывается контроллер (wildcard
`devices/+/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) — сериализация/парсинг JSON
- `DHT 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
1. **Поддержка ESP32.** Arduino IDE → Settings → «Additional boards manager
URLs» → добавить:
`https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json`
2. **Ядро.** Tools → Board → Boards Manager → найти `esp32` → установить
пакет `esp32 by Espressif Systems`.
3. **Библиотеки.** Tools → Manage Libraries → поставить по одной:
`PubSubClient`, `ArduinoJson` (v7), `DHT sensor library` (IDE предложит
доустановить зависимость `Adafruit Unified Sensor` — согласиться).
4. **Скетч.** File → Open → `controllers/growbox/growbox.ino` — остальные
`.h`/`.cpp` подхватятся вкладками автоматически.
5. **Конфиг.** `cp config.h.example config.h`, заполнить Wi-Fi SSID/пароль,
IP хоста с поднятым `docker compose` платформы (mosquitto слушает
`0.0.0.0:1883` — доступен по IP машины в локальной сети), `zone_id` и
`device_id`. Если IDE уже была открыта — переоткрыть скетч.
6. **Плата и порт.** Подключить ESP32 по USB (кабель именно с передачей
данных). Tools → Board → esp32 → `ESP32 Dev Module` (или точная модель).
Tools → Port → появившийся `/dev/cu.usbserial-*` /
`/dev/cu.SLAB_USBtoUART`.
7. **Заливка.** Кнопка Upload. Часть плат просит зажать кнопку `BOOT` на
плате до появления точек соединения в логе.
8. **Проверка.** 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)
```bash
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.