Автополив на балконе на ESP32: DIY, грабли и один бракованный чип (Часть 1)
Есть два типа людей: одни вовремя поливают цветы, а другие делают систему автополива на балконе, чтобы вовремя поливать цветы. Я, конечно же, из вторых — потому что зачем тратить 10 секунд в день, если можно потратить два месяца, кучу проводов и немного нервных клеток.
Это рассказ о том, как я собираю новую версию домашней системы полива на ESP32: какое железо использую, по какой логике оно работает, как всё соединяется — и, главное, на какие грабли я наступил. А наступил я на все.
Идея: лень как двигатель прогресса
На балконе живёт 6 растений: 4 больших и 2 маленьких. Задача — чтобы система сама следила за влажностью почвы, поливала каждое ровно столько, сколько нужно, управляла подсветкой и умела всё это показывать. Управление тройное: энкодер + кнопка + дисплей для локального тыканья и Wi-Fi + веб-морда для дивана.
Философия проекта: один мозг (ESP32), много рук (датчики, насосы, реле) и полное отсутствие ручного труда. В идеале растения не должны замечать, что за ними ухаживает микроконтроллер, а не заботливый хозяин.
Железо: собираем зоопарк
Список закупок с AliExpress выглядит так, будто я собирался не поливать герань, а запускать спутник:
- ESP32 DevKit V4 — единый мозг всей системы. Wi-Fi, куча пинов, дешёвый. Идеальный кандидат, чтобы потом три дня выяснять, какой из этих пинов нельзя трогать.
- Ёмкостные датчики влажности (Capacitive Soil Moisture v1.3) — 9 штук и будет больше. Меряют сухость почвы. Чем суше — тем больше число. Запомните это, пригодится.
- Мультиплексор 74HC4067 — 16 аналоговых каналов на один вход АЦП. Потому что датчиков много, а нормальных аналоговых пинов у ESP32 — кот наплакал.
- Расширитель портов MCP23017 — ещё 16 цифровых ног по I2C. Для реле и кнопок, которые не влезли на ESP32.
- Платы реле (8 + 2 канала) — включать насосы и лампы подсветки (220 В, по реле на лампу, чтобы делать красивое последовательное включение).
- Насосы 5 В — 4 штуки, по одному на растение. Сопло планирую сделать трубкой с дырочками, чтобы поливать равномерно по всей длине горшка.
- Расходомеры YF-S401 — 3 штуки, с крыльчаткой внутри. Считают, сколько миллилитров реально налилось в самый капризный горшок.
- Дисплей 2.4" ST7789 (320×240) с энкодером EC11 и кнопкой на одной плате — для локального управления и красивой картинки.
Как это всё соединяется (и почему ESP32 боится пяти вольт)
Главный принцип разводки: быстрые линии — напрямую на ESP32 (дисплей по SPI, энкодер, расходомеры на прерываниях, мультиплексор), а медленные — через MCP23017 по I2C (реле, кнопки). Так хватает пинов на весь зоопарк, ещё и с запасом.
Распиновка ESP32
123456789101112131415
Функция GPIO Плата
------------------- ----------- -----
TFT SCK 18
TFT MOSI (SDA) 23
TFT CS 5
TFT DC 17
TFT RES 16
TFT BLK (подсветка) 3.3 В
I2C SDA -> MCP23017 21
I2C SCL 22
MUX SIG (ADC1) 36 VP
MUX S0..S3 13,14,27,26
Энкодер A / B 25 / 33
Расходомеры F1..F3 32, 19, 4
Резерв (ADC1) 34,35,39 VN
Пины 36 и 39 на плате часто подписаны как VP и VN — это те же самые GPIO, просто из «сенсорной» группы (только вход, идеальны под аналог). Пины 34/35/39 оставлены в резерв под будущий датчик уровня воды.
Питание — от отдельной платы, которая раздаёт стабильные 5 В и 3.3 В. Насосы и катушки реле — на 5 В, вся логика и датчики — на 3.3 В. И тут первое правило клуба любителей ESP32:
Разводка питания и земля
1234567
Плата питания
├─ 5В ───┬── реле-катушки + насосы (+ bulk-кап, диоды)
│ └── ESP32 (пин 5V) (+ кап у ESP32)
├─ 3.3В ──┬── логика MCP23017 / TFT / оптопары реле
│ └── MUX + датчики влажности (стабильная точка!)
└─ GND ─┬─ силовая земля (насосы, реле)
└─ чистая земля (логика, датчики) ← «звезда» в одну точку
ESP32 НЕ пятивольтотолерантен. Подашь 5 В на его ногу — попрощаешься с ногой (а то и со всей платой). Поэтому I2C, датчики и сигналы расходомеров — строго через 3.3 В или делители/сдвиг уровня.
Отдельная песня — земля. Насосы при старте дают бросок тока, и если земля общая «как-нибудь», ёмкостные датчики начинают показывать погоду на Марсе. Лечится «звездой»: силовая земля (насосы, реле) и тихая земля (логика, датчики) сходятся в одной точке у блока питания.
Мораль, оплаченная нервами: без bulk-конденсаторов на 5 В (470–1000 мкФ у реле и 220–470 мкФ у ESP32) микроконтроллер уходит в перезагрузку при каждом старте насоса. Просадка питания → brownout → reset. Конденсаторы — не роскошь, а обязательный ритуал.
Логика полива
Сердце системы — «карта растений». У каждого растения свой набор параметров: какие каналы влажности к нему относятся, какой насос его поливает, есть ли расходомер, сколько миллилитров ему налить и через сколько секунд принудительно вырубить насос.
- Большие горшки — по 2 датчика влажности в разных концах, берём среднее. Земля большая, в одном углу может быть сухо, в другом — болото.
- Дозирование по объёму — если у растения есть расходомер, крутим насос, считаем импульсы крыльчатки и останавливаемся ровно на нужных миллилитрах.
- Дозирование по времени — если расходомера нет, один раз калибруем производительность насоса (мл/сек) и льём расчётное время.
- Защита по таймауту — у каждого растения свой максимум времени полива. Не налилось за него? Стоп и флаг ошибки. Потому что пустой бак или перегнутая трубка не должны превращать балкон в аквапарк.
- Полив последовательный — по одному насосу за раз. Так однозначно понятно, какому расходомеру приписывать воду, и питание не проседает.
Датчика уровня воды пока нет (едет с Али), так что в этой версии единственная страховка от перелива — тот самый таймаут. Живём на грани, но с фитильком безопасности.
Грабли, на которые я наступил (спойлер: на все)
А вот и самая честная часть статьи. Если вы думаете, что DIY-электроника — это «спаял по схеме и заработало», то садитесь, сейчас будет терапия.
1. Дисплей вверх ногами
Первый запуск экрана: картинка есть, цвета есть, всё прекрасно… только вверх тормашками. Лечится одной строчкой setRotation(). Пять секунд работы и приятное ощущение, что хоть что-то решается быстро. Наслаждался я этим ощущением недолго.
2. 80 МГц и пляшущие цифры
Захотелось «побольше FPS» — разогнал SPI дисплея до 80 МГц. Получил 33 fps и красиво мигающие цифры, которые периодически исчезали. Оказалось: на макетке с проводами-соплями 80 МГц — это уже за гранью добра и целостности сигнала. Откатил на честные 40 МГц (а на дефолт — вообще без глюков). Высокий FPS вернём, когда всё будет спаяно короткими проводами.
Правило прототипа: длинные провода + высокая частота = гарантированные приключения. Скорость раздаём после пайки, а не на «соплях».
3. Призрачная перекрёстка каналов
Подключаю 4 датчика, опускаю первый в воду — а меняются показания сразу у двух каналов. Магия? Нет, физика: у АЦП есть конденсатор выборки-хранения, а выход ёмкостного датчика высокоомный. Переключили канал — конденсатор ещё «помнит» прошлый, и сосед подтягивается к нему.
Лечится паузой после переключения канала и парой холостых замеров, чтобы сбросить память АЦП. Плюс сверху EMA-фильтр, чтобы значения не «дышали». Простая экспонента творит чудеса:
12
// Сглаживание во времени: меньше alpha = плавнее, но медленнее реагирует
ema[ch] = EMA_ALPHA * raw + (1.0f - EMA_ALPHA) * ema[ch];
4. S0, припаянный «куда-то туда»
Дальше стало веселее. Показания каналов пошли парами: C0 = C1, C2 = C3. Классический симптом того, что младший бит адреса мультиплексора (S0) не переключается. Полез проверять — а он и правда припаян не на ту ногу. Перепаял на GPIO13. Пары исчезли, я возгордился. Рано.
5. Экранированный кабель (тут я, внезапно, всё сделал правильно)
Провода к датчикам длинные и идут рядом, поэтому взял экранированный кабель. Экран (оплётку) заземлил только с одного конца — со стороны ESP32, а на датчиках оставил висеть в воздухе. И это, о чудо, правильно: заземлить экран с двух концов — значит поймать «земляную петлю», по которой потечёт ток, и оплётка сама станет антенной для наводок. Один конец — и никаких петель.
6. Бракованный мультиплексор — гранд-финал
А вот и кульминация. После починки S0 началась совсем чертовщина: большинство каналов вообще не реагировали на замыкание входа на землю, а заземление входа C3 роняло в ноль сразу C1, C2 и C3. Я героически проверил всё: SIG (в порядке), питание чипа (стабильные 3.2 В), EN (на земле), код (адресация идеальная, тут даже придраться не к чему).
Залил диагностический режим (по OTA, что символично) — он держит по одному каналу и показывает, какие уровни должны быть на S0–S3. Взял тестер, прозвонил ноги чипа и… S0 и S1 оказались замкнуты между собой прямо на плате мультиплексора. С завода. Два независимых бита адреса, соединённых дорожкой, которой там быть не должно. Отсюда и весь цирк: адресация схлопывалась, половина каналов была недостижима.
Полдня диагностики, чтобы выяснить, что виноват не ты, не код и не пайка, а китайский контроль качества. Бесценно.Я, глядя на прозвонку
Вывод на будущее: новую плату из коробки не грех прозвонить ДО того, как впаивать её в проект. Особенно соседние ноги адресных линий. Пять минут тестером экономят полдня отладки.
Бонус-грабли: OTA и упрямый загрузчик
Прошивать по USB на макетке — то ещё удовольствие: ESP32 периодически отказывался входить в режим загрузки (привет, Wrong boot mode 0x13). Поэтому прикрутил OTA — прошивку по Wi-Fi. Теперь на экране во время апдейта гордо горит «Firmware update» с процентами и прогресс-баром, а провод больше не нужен:
$ arduino-cli upload -p 192.168.x.x --fqbn esp32:esp32:esp32 \$ --upload-field password=ВАШ_OTA_ПАРОЛЬ HardwareTest
Ирония в том, что диагностику бракованного мультиплексора я в итоге залил именно по OTA — USB-порт к тому моменту гордо отвалился. Технический прогресс спасает там, где подводит железо.
Что дальше
Впереди: заменить бракованный мультиплексор, подключить MCP23017 с реле, повесить расходомеры и энкодер, а потом взяться за основную прошивку — модель данных «карты растений», экранный UI (сводный экран + карточка растения) и веб-морду на Vue. И, конечно, дождаться датчик уровня воды, чтобы окончательно застраховаться от потопа.
Но каркас уже жив: экран работает, мультиплексор (исправный) читается, фильтрация настроена, OTA летает. Осталось немного — и растения перейдут на полное гособеспечение.
Мораль истории: автополив на ESP32 — это не про «спаял и забыл», а про «спаял, прозвонил, проклял, перепаял, снова прозвонил — и вот тогда забыл». Зато процесс затягивает сильнее, чем сам результат. Продолжение следует — как только приедет новый мультиплексор и я снова поверю в китайскую электронику. 🌱