Датчик почвенной влажности soil-1 + второй релейный модуль под fan-1

По фото: у нас два одинаковых 2-канальных релейных модуля (не один) —
второй закрывает fan-1 по-настоящему (GPIO18), больше не "пока не куплено".

Добавлен soil-1: компараторный модуль почвенной влажности, читаем A0 через
ADC (GPIO34, input-only), публикуем sensor_type=soil_moisture в процентах.
Raw->% калибруется через SOIL_RAW_DRY/SOIL_RAW_WET в config.h — заводские
значения приблизительные, точную калибровку раньше сделать было нельзя (не
было физического доступа к датчику), нужно измерить на месте.

soil-1 в Postgres/Laravel платформы ещё не заведён (не трогаем
home_automatization) — телеметрия будет идти в ClickHouse, но в Laravel UI
устройство не появится до отдельной регистрации device_type/devices-записи.

Веб-интерфейс и /api/state дополнены полем "soil".
This commit is contained in:
2026-08-18 12:57:49 +05:00
parent 0456d4e447
commit 6a7d512b22
5 changed files with 127 additions and 44 deletions
+48 -27
View File
@@ -1,9 +1,9 @@
# growbox (ESP32-контроллер)
Прошивка для реального ESP32, обслуживающая зону "Гроубокс" платформы
[home_automatization](../../home_automatization). Одна плата владеет четырьмя
устройствами: `sensor-1` (DHT22) и три реле-актуатора — `light-1`, `pump-1`,
`fan-1`.
[home_automatization](../../home_automatization). Одна плата владеет пятью
устройствами: `sensor-1` (DHT22, температура/влажность воздуха), `soil-1`
(влажность почвы) и три реле-актуатора — `light-1`, `pump-1`, `fan-1`.
## Протокол (MQTT, mosquitto из docker-compose платформы, порт 1883)
@@ -22,39 +22,52 @@
device_id в конфиге должны совпадать с `devices.external_id`, засеянными в
Laravel (`DemoGrowboxSeeder` использует `sensor-1`/`fan-1`), а `zone_id`с
`zones.id` зоны "Гроубокс" в Postgres.
`zones.id` зоны "Гроубокс" в Postgres. `soil-1` — новое устройство, в
Laravel/Postgres пока не заведено (нужен `device_type` и строка в `devices`
— это в этом репозитории не делаем); до тех пор его телеметрия просто ни к
чему не привязана на стороне платформы, ingest-service это не блокирует
(zone_id едет прямо в payload, в 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 с распаянными проводами, компараторный модуль почвенной влажности
(потенциометр + разъём `A0 D0 GND VCC`, используем только `A0`) и **два
одинаковых 2-канальных** релейных модуля (SRD-05VDC-SL-C×2 каждый, общий
разъём `GND IN1 IN2 VCC`) — вместе четыре канала на три реле, один канал
второй платы свободен про запас.
| Назначение | Пин (по умолчанию) | Примечание |
|---------------------|---------------------|------------|
| DHT22 DATA | GPIO4 | провод жёлтый на нашем модуле |
| Реле IN1 — light-1 | GPIO16 | **на шёлкографии платы подписан `RX2`**, не «16» |
| Реле IN2pump-1 | GPIO17 | **на шёлкографии платы подписан `TX2`**, не «17» |
| Реле IN — fan-1 | GPIO18 | нужен третий канал реле, пока не подключено |
| Назначение | Пин (по умолчанию) | Примечание |
|--------------------------|---------------------|------------|
| DHT22 DATA | GPIO4 | провод жёлтый на нашем модуле |
| Почва, A0 | GPIO34 | ADC1_CH6, input-only; нужна калибровка `SOIL_RAW_DRY`/`SOIL_RAW_WET` |
| Реле №1, IN1light-1 | GPIO16 | **на шёлкографии платы подписан `RX2`**, не «16» |
| Реле №1, IN2pump-1 | GPIO17 | **на шёлкографии платы подписан `TX2`**, не «17» |
| Реле №2, IN1 — fan-1 | GPIO18 | второй такой же модуль |
| Реле №2, IN2 | — | свободный канал, не задействован |
На этой конкретной 30-пиновой плате GPIO16/17 не подписаны номерами — они
выведены как пины UART2 и промаркированы `RX2`/`TX2`. Физически это те же
GPIO, `config.h`/прошивку менять не нужно, важно только не перепутать их при
пайке/монтаже на плате.
Реле-модуль (2-канальный, SRD-05VDC-SL-C) активен по LOW —
Оба релейных модуля (2-канальные, SRD-05VDC-SL-C) активны по LOW —
`RELAY_ACTIVE_LOW` в `config.h` уже стоит в `true`. Перемычка `JD-VCC` на
модуле по умолчанию установлена (питание катушек реле — от той же VCC, без
гальванической развязки) — для этого проекта этого достаточно, снимать её
незачем.
каждом модуле по умолчанию установлена (питание катушек реле — от той же
VCC, без гальванической развязки) — для этого проекта этого достаточно,
снимать её незачем.
DHT22 требует подтягивающий резистор ~10кОм между DATA и VCC — на нашем
модуле, похоже, уже встроен (компактная плата-переходник с 3 проводами), но
если показания не читаются — проверьте отдельным резистором.
Модуль почвенной влажности — сырое ADC-значение на `A0` **уменьшается** с
ростом влажности (суше — выше сопротивление датчика — выше напряжение).
Заводские `SOIL_RAW_DRY`/`SOIL_RAW_WET` в `config.h.example` — грубая оценка,
не калибровка: замерьте raw-значение на воздухе и после погружения щупа в
воду (печатается в Serial-логе `telemetryTick()`) и подставьте свои числа,
иначе проценты будут врать.
### Схема подключения
```
@@ -62,10 +75,12 @@ DHT22 требует подтягивающий резистор ~10кОм ме
┌───────────────────────┐
DHT22 DATA ───────┤ GPIO4 │
(жёлтый провод) │ │
Почва A0 ─────────┤ GPIO34 │
│ │
Реле IN1 (light-1)┤ GPIO16 (на плате: RX2)
Реле IN2 (pump-1) ┤ GPIO17 (на плате: TX2)
Реле IN (fan-1) ──┤ GPIO18 ← пока не подключено
Реле №1 IN1 (light-1) ┤ GPIO16 (на плате: RX2)
Реле №1 IN2 (pump-1) ┤ GPIO17 (на плате: TX2)
Реле №2 IN1 (fan-1) ┤ GPIO18
Реле №2 IN2 (свободно) ┤ —
│ │
3V3 ────┤ 3V3 │
GND ────┤ GND │
@@ -75,9 +90,13 @@ DHT22 требует подтягивающий резистор ~10кОм ме
DHT22 (готовый модуль, 3 провода):
оранжевый(+/VCC) -> 3V3 жёлтый(out/DATA) -> GPIO4 зелёный(-/GND) -> GND
Реле, 2-канальный модуль (разъём GND IN1 IN2 VCC):
Почва (компараторный модуль, разъём A0 D0 GND VCC — используем A0):
VCC -> 3V3 GND -> GND A0 -> GPIO34
Реле, два одинаковых 2-канальных модуля (разъём GND IN1 IN2 VCC):
VCC -> VIN (5V) GND -> GND (общий с ESP32)
IN1 -> GPIO16/RX2 (light-1) IN2 -> GPIO17/TX2 (pump-1)
Модуль №1: IN1 -> GPIO16/RX2 (light-1) IN2 -> GPIO17/TX2 (pump-1)
Модуль №2: IN1 -> GPIO18 (fan-1) IN2 -> свободен
⚠️ Реле коммутируют цепь самой нагрузки (свет/насос/вентилятор, обычно
12V/220V) через винтовые клеммы COM/NO/NC каждого канала — это
@@ -102,9 +121,9 @@ DHT22 (готовый модуль, 3 провода):
Каждая плата поднимает у себя простую страницу и JSON API на порту 80 —
удобно наблюдать/управлять локально, не дожидаясь Laravel/MQTT:
- `GET /` — HTML-страница: показания DHT22 + кнопки Вкл/Выкл для
- `GET /` — HTML-страница: показания DHT22 и почвы + кнопки Вкл/Выкл для
light-1/pump-1/fan-1.
- `GET /api/state` — JSON `{"sensor":{"has_reading","temperature","humidity"},"devices":{"light-1":{"power"},...}}`.
- `GET /api/state` — JSON `{"sensor":{"has_reading","temperature","humidity"},"soil":{"has_reading","percent"},"devices":{"light-1":{"power"},...}}`.
- `POST /api/command` — JSON-тело `{"device_id","action","level"?}`, тот же
формат, что и в MQTT-команде.
@@ -172,7 +191,9 @@ Arduino IDE (GUI-приложение) это обычно не требуетс
## Проверка end-to-end
При работающем `docker compose` в `home_automatization` и засеянных
Postgres-данных (зона + `sensor-1`/`light-1`/`pump-1`/`fan-1`):
Postgres-данных (зона + `sensor-1`/`light-1`/`pump-1`/`fan-1`; `soil-1` пока
не засеян — его телеметрию ClickHouse примет, но в Laravel UI устройство не
появится, пока не завести `devices`-запись):
- телеметрия должна доходить до ClickHouse через ingest-service;
- команда через Laravel UI (или напрямую через `grpcurl` в