Зачем это делать самому
Автополив — это тот случай, когда самоделка выигрывает у готового решения. Готовые системы продаются, но у них один недостаток: вы не знаете, что внутри, как они решают, когда поливать, и что произойдёт, если датчик откажет. Для растений цена ошибки высока: два дня перелива убивают корни быстрее, чем неделя засухи. Поэтому здесь важны не только датчик и помпа, но и логика, которая умеет отказывать безопасно.
ESP32 для этой задачи подходит лучше, чем классический Arduino, по трём причинам: Wi-Fi на борту, достаточная вычислительная мощность для веб-интерфейса и хорошие режимы энергосбережения. Проект получается не «умным» ради модного слова, а действительно удобным: вы открываете браузер на телефоне и видите влажность почвы в горшке, историю поливов и текущее состояние помпы.
Начнём с границы, которую надо провести сразу, чтобы не разочароваться в середине сборки.
Граница: что этот проект делает и что нет
Автополив на ESP32 решает одну задачу: поддерживать влажность почвы в заданном диапазоне. Он не определяет потребности конкретного растения по виду листьев, не заменяет наблюдение за растением и не гарантирует, что помпа не откажет.
Второе, что надо понять: ESP32 не питает помпу. Никакой пин микроконтроллера не даёт достаточного тока, чтобы крутить мотор. Пин управляет ключом — реле или MOSFET, — а ключ уже подаёт питание на помпу от отдельного источника. Попытка запитать помпу прямо от платы приводит к перезагрузкам ESP32, сбросу Wi-Fi и порче пина.
Третье: влажность почвы — это не абсолютная величина. Датчик измеряет не «сколько воды в земле», а сопротивление или ёмкость между электродами, которая зависит от типа грунта, температуры, минерализации и плотности посадки. Поэтому любой датчик влажности нужно калибровать под конкретный горшок и конкретную почву. Без калибровки цифры на экране будут меняться, но смысла в них не будет.
С этими оговорками можно переходить к выбору компонентов.
Ёмкостный датчик вместо резистивного
Самый распространённый в продаже датчик влажности почвы — резистивный, с двумя оголёнными штырями. Он дешёвый и работает, но у него есть смертельный недостаток: постоянный ток между электродами вызывает электролиз, штыри окисляются и разрушаются за считаные недели. Датчик, который выглядел рабочим при сборке, через месяц начинает врать, а через два — перестаёт реагировать.
Ёмкостный датчик лишён этого недостатка. Он измеряет не сопротивление между электродами, а ёмкость, которую создаёт почва вокруг чувствительной площадки. Постоянного тока между электродами нет, окисления нет, срок службы — годы. Внешне такой датчик выглядит как плата с плоской гребёнкой без оголённых штырей, сверху обычно стоит микросхема-таймер, генерирующая сигнал.
У ёмкостного датчика на выходе аналоговое напряжение, которое меняется в зависимости от влажности. Обычно сухая почва даёт одно значение, мокрая — другое, и это значение нужно прочитать АЦП ESP32, а потом перевести в понятный процент.
Важная деталь: ёмкостные датчики часто рассчитаны на питание 3.3 вольта, и это идеально подходит для ESP32. Если датчик рассчитан на 5 вольт, а вы подадите на него 3.3, он будет работать, но с меньшим диапазоном выходного напряжения. Если подадите 5 вольт на выход датчика, который подключён к АЦП ESP32, вы сожжёте вход. АЦП ESP32 рассчитан максимум на 3.3 вольта.
У АЦП ESP32 есть ещё одна особенность: он нелинейный и шумный. Не стоит ожидать от него точности лабораторного прибора. Для полива этого достаточно, но наивная формула «сырое значение делить на 4095 и умножить на 100» даст цифры, которые плохо соответствуют реальности. Правильнее откалибровать два значения — «сухо на воздухе» и «мокро в воде» — и потом линейно интерполировать между ними.
Помпа: какая подходит и как её питать
Для комнатного растения нужна небольшая помпа, которая поднимает воду из бутылки или канистры на высоту горшка. Обычно используют две разновидности.
Первая — перистальтическая помпа. Это маленький моторчик, который прокачивает воду через гибкую трубку, сжимая её роликами. Плюсы: не контактирует с водой напрямую, не боится сухого хода, легко дозируется по времени. Минусы: шумная, дороже, требует периодической замены трубки. Для автополива — хороший выбор, потому что даёт точную дозировку.
Вторая — погружная вибрационная помпа. Она опускается в ёмкость с водой и качает воду через шланг. Плюсы: тише, дешевле, производительнее. Минусы: не любит сухой ход, боится мусора в воде, занимает место в ёмкости. Для автополива тоже подходит, но нужно следить, чтобы она не работала вхолостую.
Питание помпы — отдельная история. Большинство перистальтических помп рассчитаны на 6 или 12 вольт, вибрационные — на 220 вольт или на 12 вольт. Ни в одном из случаев нельзя питать помпу от ESP32. Нужен отдельный источник: блок питания на 12 вольт для 12-вольтовой помпы, или блок питания на 5 вольт для 5-вольтовой. При этом источник питания ESP32 и источник питания помпы — это обычно два разных блока, соединённых только по сигнальному проводу.
Почему не один блок питания на всё? Потому что при запуске помпа даёт бросок тока и просадку напряжения, от которой ESP32 может перезагрузиться. Особенно если блок питания слабый или провода тонкие. Если очень хочется один блок, нужно брать его с запасом по току и ставить конденсатор по питанию ESP32 не меньше 470 микрофарад, но надёжнее — разнести питание на два блока.
Ключ для управления помпой: реле или MOSFET
Пин ESP32 выдаёт 3.3 вольта и ток порядка 12 миллиампер. Этого недостаточно для мотора, но достаточно для управления ключом. Ключ выбирается по типу питания помпы.
Если помпа на 220 вольт, нужен модуль реле с оптоизоляцией. Обязательно с оптоизоляцией — это защита ESP32 от помех со стороны силовой цепи. Реле подключается низковольтной стороной к пину ESP32 и к общему проводу, силовая сторона коммутирует фазовый провод помпы. Ноль помпы идёт напрямую. Землю ESP32 с фазой или нулём помпы не соединяем ни в коем случае.
Если помпа на 12 вольт, лучший вариант — MOSFET с логическим уровнем. Модуль на базе IRLZ44N или похожего транзистора, который полностью открывается при 3.3 вольтах на затворе. Обычные MOSFET для 10 вольт на затворе здесь не подойдут: ESP32 даст 3.3 вольта, транзистор откроется наполовину, начнёт греться и в итоге выйдет из строя.
Схема подключения MOSFET-модуля проста: плюс питания помпы идёт на помпу, минус помпы идёт на сток транзистора, исток транзистора идёт на минус блока питания, затвор — на пин ESP32, землю ESP32 нужно соединить с минусом блока питания помпы, чтобы у них была общая точка отсчёта. Без общей земли MOSFET не сработает, потому что затвор не увидит разницы потенциалов.
Параллельно помпе стоит поставить диод — защитный, в обратном направлении. При выключении индуктивная нагрузка даёт выброс напряжения, который может пробить транзистор. Диод шунтирует этот выброс. Это не опция, а необходимость для любой индуктивной нагрузки.
Логика полива: гистерезис и максимальное время
Самая частая ошибка новичка — включать помпу при влажности ниже порога и выключать при влажности выше того же порога. Это приводит к тому, что помпа дёргается каждые несколько секунд: полила, влага распространилась, датчик показал чуть выше порога, помпа выключилась, влага впиталась глубже, датчик снова показал ниже. Такое мигание раздражает и убивает помпу.
Решение — гистерезис. Включаем полив при влажности ниже, скажем, 30 процентов, выключаем при 45 процентах. Разница в 15 процентов даёт стабильность. Конкретные значения подбираются под растение: суккуленты любят пересыхание, папоротники — постоянную влажность.
Второй важный элемент — максимальное время полива. Даже если датчик упорно показывает сухо, помпа не должна работать дольше, скажем, 30 секунд за один цикл. Причины две. Первая: датчик может быть неисправен или отсоединён, и тогда без ограничения помпа выльет всю воду из ёмкости в горшок. Вторая: вода может не дойти до датчика, если он стоит сбоку горшка, а намок только один край. Ограничение по времени защищает от обоих случаев.
Третье — минимальная пауза между поливами. Даже если датчик снова показывает сухо через минуту после полива, помпа не должна запускаться сразу. Влага должна распространиться по грунту, и только потом имеет смысл новое измерение. Пауза в 10–30 минут устраняет ложные срабатывания.
Карта логики выглядит так.
Состояние: помпа выключена.
Если влажность < порог_включения (30%)
и с последнего полива прошло больше минимальной паузы (например, 30 минут):
включить помпу
запомнить время запуска
перейти в состояние "полив"
Состояние: помпа включена.
Если влажность > порог_выключения (45%):
выключить помпу
запомнить время последнего полива
перейти в состояние "пауза"
Если помпа работает дольше максимального времени (30 секунд):
выключить помпу аварийно
поднять флаг ошибки
запомнить время последнего полива
перейти в состояние "пауза"Флаг ошибки потом отображается в веб-интерфейсе, чтобы вы видели, что было аварийное отключение, и могли проверить датчик.
Датчик влажности почвы: как калибровать
Калибровка ёмкостного датчика — это два замера. Первый: датчик воткнут в сухую почву, показания АЦП записаны. Второй: датчик воткнут в ту же почву, только что политую до состояния, которое вы считаете «полностью мокро», показания АЦП записаны.
Между этими двумя значениями влажность интерполируется линейно. Если сухая почва даёт 3000 условных единиц, а мокрая — 1200, то значение 2100 — это примерно середина диапазона, что соответствует 50 процентам влажности.
Но есть тонкость: разные датчики ведут себя по-разному, а один и тот же датчик в разных грунтах даёт разные значения. Универсальной формулы нет. Калибровать нужно в том горшке и с той почвой, где датчик будет стоять постоянно.
Второе: датчик нужно правильно ставить в горшок. Он не должен торчать у самой стенки, потому что там почва пересыхает быстрее, чем в центре. Оптимально — вкрутить его в грунт между растением и краем горшка, но не вплотную к стенке. Глубина — чтобы площадка с электродами полностью оказалась в почве.
Третье: показания нужно усреднять. АЦП ESP32 шумит, отдельные замеры могут отличаться на сотни единиц. Простой способ — сделать 10–20 замеров в цикле и взять среднее. Это уберёт случайные выбросы и не потребует сложной фильтрации.
Веб-интерфейс: минимальный, но полезный
ESP32 может обслуживать HTTP-запросы прямо на себе, без Home Assistant и без облака. Это не самый гибкий вариант, но для одной платы это самый простой и автономный путь. Открываете браузер, вводите локальный адрес платы, видите страницу с текущей влажностью, состоянием помпы и кнопкой ручного полива.
Веб-интерфейс держим минимальным: одна HTML-страница с автоперезагрузкой раз в 10 секунд, одно поле для влажности, одна кнопка для ручного полива на 5 секунд, и, если есть аварийный флаг, красная плашка с сообщением. Ничего больше не нужно. Каждый лишний элемент — это код и место для ошибок.
У платы должен быть постоянный IP-адрес в локальной сети, иначе каждый раз придётся искать новый. Это решается либо статической настройкой IP на самой плате, либо настройкой резервирования адреса по MAC на роутере. Первый вариант проще, второй гибче.
Для доступа извне квартиры — только через VPN или обратный прокси. Открывать ESP32 прямо в интернет нельзя, потому что у неё нет никакой аутентификации из коробки, и любой сканер найдёт её за считаные часы. Если хочется видеть горшок из отпуска, лучше поднять локальный MQTT-брокер и Home Assistant, а уже к ним подключаться безопасно. Это отдельная тема и отдельная статья.
Скетч: ключевые фрагменты
Полный скетч получится длинным, поэтому разберём ключевые части. Первая — чтение влажности с усреднением.
// Чтение аналогового значения с ёмкостного датчика с усреднением.
// Пин АЦП — 34. Это вход ADC1, он работает, когда включён Wi-Fi.
// Пины ADC2 (например, 25, 26, 27) при активном Wi-Fi не работают.
const int SOIL_PIN = 34;
const int SOIL_SAMPLES = 20;
// Калибровочные значения: подставляются после двух замеров.
// ВНИМАНИЕ: эти числа примерные, их нужно заменить на свои.
const int SOIL_DRY_VALUE = 3000; // показания в сухой почве
const int SOIL_WET_VALUE = 1200; // показания в мокрой почве
int readSoilPercent() {
long sum = 0;
for (int i = 0; i < SOIL_SAMPLES; i++) {
sum += analogRead(SOIL_PIN);
delay(5);
}
int raw = sum / SOIL_SAMPLES;
// Линейная интерполяция между сухим и мокрым значением.
// На выходе — процент влажности от 0 до 100.
int percent = map(raw, SOIL_DRY_VALUE, SOIL_WET_VALUE, 0, 100);
// Ограничиваем диапазон, потому что map не умеет ограничивать.
if (percent < 0) percent = 0;
if (percent > 100) percent = 100;
return percent;
}Обратите внимание на выбор пина. АЦП ESP32 разделён на два блока: ADC1 и ADC2. Когда включён Wi-Fi, ADC2 недоступен. Пины 32, 33, 34, 35, 36, 39 относятся к ADC1 — их можно использовать при активном Wi-Fi. Пины 0, 2, 4, 12, 13, 14, 15, 25, 26, 27 относятся к ADC2 — при включённом Wi-Fi analogRead на них вернёт мусор. Это неочевидная ловушка, из-за которой новички часами ищут причину «плавающих» показаний.
Вторая часть — логика полива. Она должна быть неблокирующей: никаких delay на секунды, потому что за это время ESP32 не будет обслуживать веб-запросы, и страница будет висеть.
// Логика полива с гистерезисом, минимальной паузой и максимальным временем.
// Значения подбираются под растение.
const int PUMP_PIN = 26; // пин управления MOSFET или реле
const int HUMIDITY_LOW = 30; // порог включения, проценты
const int HUMIDITY_HIGH = 45; // порог выключения, проценты
const unsigned long MIN_PAUSE_MS = 30UL * 60UL * 1000UL; // 30 минут
const unsigned long MAX_WATER_MS = 30UL * 1000UL; // 30 секунд
unsigned long pumpStartedAt = 0;
unsigned long lastWateringEnd = 0;
bool pumpOn = false;
bool errorOverflow = false;
void updateWatering(int humidity) {
unsigned long now = millis();
if (!pumpOn) {
// Проверяем, можно ли запустить полив.
bool dry = humidity < HUMIDITY_LOW;
bool pausePassed = (lastWateringEnd == 0) ||
(now - lastWateringEnd > MIN_PAUSE_MS);
if (dry && pausePassed) {
digitalWrite(PUMP_PIN, HIGH);
pumpOn = true;
pumpStartedAt = now;
errorOverflow = false;
}
} else {
// Помпа работает. Проверяем условия остановки.
bool wet = humidity > HUMIDITY_HIGH;
bool tooLong = (now - pumpStartedAt > MAX_WATER_MS);
if (wet || tooLong) {
digitalWrite(PUMP_PIN, LOW);
pumpOn = false;
lastWateringEnd = now;
if (tooLong && !wet) {
errorOverflow = true;
}
}
}
}Здесь нет ни одного delay. Функция вызывается в loop, читает текущее время через millis, принимает решение и возвращается. Веб-сервер в это время продолжает отвечать на запросы.
Третья часть — веб-сервер. На ESP32 можно использовать стандартную библиотеку WebServer из ядра Arduino для ESP32, она достаточна для одной страницы.
// Веб-сервер на ESP32: одна страница и одна кнопка ручного полива.
// Библиотеки входят в ядро ESP32 для Arduino IDE.
#include <WiFi.h>
#include <WebServer.h>
const char* WIFI_SSID = "ваш_ssid";
const char* WIFI_PASSWORD = "ваш_пароль";
WebServer server(80);
int lastHumidity = 0;
bool manualWatering = false;
unsigned long manualWateringUntil = 0;
void handleRoot() {
String page = "<!DOCTYPE html><html><head>";
page += "<meta charset='utf-8'>";
page += "<meta http-equiv='refresh' content='10'>";
page += "<title>Автополив</title></head><body>";
page += "<h2>Влажность почвы: ";
page += lastHumidity;
page += " %</h2>";
page += "<p>Помпа: ";
page += (pumpOn ? "включена" : "выключена");
page += "</p>";
if (errorOverflow) {
page += "<p style='color:red'>АВАРИЯ: превышено максимальное время полива</p>";
}
page += "<form action='/water' method='GET'>";
page += "<button type='submit'>Полить 5 секунд</button>";
page += "</form></body></html>";
server.send(200, "text/html; charset=utf-8", page);
}
void handleWater() {
// Ручной полив: запускаем помпу на 5 секунд и возвращаемся на главную.
// Реализация — через отдельную переменную и updateWatering.
manualWatering = true;
manualWateringUntil = millis() + 5000;
server.sendHeader("Location", "/");
server.send(303);
}
void setup() {
Serial.begin(115200);
pinMode(PUMP_PIN, OUTPUT);
digitalWrite(PUMP_PIN, LOW);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.print("Адрес платы: ");
Serial.println(WiFi.localIP());
server.on("/", handleRoot);
server.on("/water", handleWater);
server.begin();
}
void loop() {
server.handleClient();
lastHumidity = readSoilPercent();
updateWatering(lastHumidity);
delay(100); // небольшой шаг, чтобы не крутить loop слишком часто
}Обратите внимание на переменную manualWatering. В приведённом фрагменте она объявлена, но не обработана в updateWatering. Это сделано намеренно, чтобы не раздувать пример. Логика ручного полива такая же, как у автоматического: если включён ручной режим и время до manualWateringUntil не истекло, помпа работает. По истечении времени помпа выключается, и manualWatering сбрасывается.
Что проверить до запуска в горшок
Собрать макет и запустить помпу — это половина дела. Вторая половина — убедиться, что система не навредит растению, если что-то пойдёт не так. Ниже — короткий список, который экономит растения и нервы.
Чек-лист перед первым поливом
- Откалибровали датчик в конкретном горшке с конкретной почвой, записали два значения — сухое и мокрое.
- Проверили, что датчик подключён к пину ADC1 (например, 34), а не к ADC2. При активном Wi-Fi ADC2 не работает.
- Убедились, что помпа питается от отдельного источника, а не от платы ESP32. Землю ESP32 соединили с минусом источника помпы.
- Поставили защитный диод параллельно помпе, в обратном направлении, чтобы выброс индуктивности не пробил транзистор.
- Для MOSFET выбрали транзистор с логическим уровнем, который полностью открывается при 3.3 вольтах на затворе.
- Для помпы на 220 вольт использовали модуль реле с оптоизоляцией и не соединяли низковольтную часть с силовой.
- Задали три защитных параметра: порог включения, порог выключения и максимальное время полива. Без максимального времени помпа может вылить всю воду в горшок при отказе датчика.
- Задали минимальную паузу между поливами, чтобы датчик не запускал помпу повторно, пока влага не распространилась по грунту.
- Установили датчик в горшок не у самой стенки и не вплотную к растению. Проверили, что площадка с электродами полностью в почве.
- Прогнали ручной режим и убедились, что вода идёт в горшок, а не мимо. Проверили, что помпа не хватает воздух из пустой ёмкости.
- Оставили доступ к веб-интерфейсу и знаете, где в квартире розетка, из которой всё питается, чтобы быстро выключить при необходимости.
Итог
Автополив на ESP32 — это проект, где правильная логика важнее красивой железки. Ёмкостный датчик вместо резистивного, отдельное питание помпы, MOSFET с логическим уровнем или реле с оптоизоляцией, гистерезис, минимальная пауза и максимальное время полива — вот что отличает работающую систему от поделки, которая на второй день заливает подоконник.
Веб-интерфейс на самой плате делает проект удобным без облаков и подписок, но не открывайте его в интернет без защиты. Если нужен доступ извне, правильный путь — Home Assistant с MQTT, а не публикация ESP32 напрямую.
И главное: любая автоматика не отменяет наблюдения за растением. Датчик может врать, помпа может засориться, шланг может слететь. Автополив снимает рутину, но не отменяет ответственности.
Эта статья продолжает цепочку блога: чтение документации и первоисточников разбиралось в Как читать даташит, выбор платформы — в ESP32-S3 и Новинках процессоров, практическая поделка с датчиком и дисплеем — в Термогигрометре с OLED на Arduino, вопросы питания, критичные и для помпы, и для ESP32, — в Питании ESP32 и ESP32-S3, общая картина умного дома — в Умном доме на Arduino, а новинки отечественной электроники, которые тоже могут пригодиться в подобных проектах, — в Новинках российской электроники.
Официальные ориентиры по библиотекам и модулям, упомянутым в статье, — в документации: WebServer из ядра ESP32 для Arduino, модули ёмкостных датчиков влажности почвы и MOSFET-модули с логическим уровнем. Там же точные сигнатуры функций и характеристики компонентов, которые я намеренно не воспроизводил по памяти.
