[Из песочницы] Автоматическая система полива сада на Home Assistant, ESP8266 и MiFlora

87-ywilifgui1kkhe06izsbt7ag.png

Некоторое время назад у моей семьи появился дом с небольшим садом в очень теплом и засушливом месте, и перед нами встала проблема регулярного полива.

Хотелось, чтобы система полива была автоматической, при этом при ее выборе приходилось учитывать следующие условия:

  • очень дорогая вода, которую надо экономить всеми доступными способами
  • разные по потребностям во влаге растения в саду, от суккулентов до влаголюбивых
  • необходимость полностью автономного полива во время отсутствия людей в доме, желательно с возможностью удаленного контроля
  • засушливый климат, не прощающий ошибок с поливом


Оценив готовые решения, которые удалось найти в местных DIY сетях и на Amazon и почитав отзывы об их надежности (как правило, не самой высокой), решили попробовать сделать что-то самостоятельно.
Disclaimer: Автор не является IT-специалистом, и не претендует на профессиональное знание описываемой темы. Уровень исполнения проекта — хобби. Об уровне своих знаний в сфере программирования и электроники автор прекрасно осведомлен и будет очень признателен за предложения по улучшению и оптимизации использованных решений.

Принципиальная схема


Сад был разбит на 4 зоны полива, каждая из них снабжается индивидуальным датчиком влажности почвы и может поливаться по индивидуальному графику и разным количеством воды.
По земле проложены ПНД-трубки капельного полива с перфорацией, которые подключены к трубам сходящимся в водоразборном узле и подключенным через электромагнитные клапаны к водопроводу. Клапаны управляются реле подключенными к ESP8266 (Sonoff 4Ch).

Полив осуществляется по таймерам, в ночное время, чтобы увеличить количество воды, которое впитается в землю и не будет испарено солнцем.

При наступлении запланированного времени полива проверяется соответствие нескольким условиям:

  • влажность почвы ниже заданной величины
  • отсутствуют прогнозируемые осадки в достаточно большом количестве на ближайшие 2 дня
  • не превышен лимит воды по поливу заданного для этой линии


Использованное оборудование


Raspberry Pie с установленным HassIO (уже была)

ESP32 DevKit, прошитая ESPHome, выступающая bluetooth-гейтвеем для MiFlora и принимающая данные от проводных датчиков влажности. Расположена в саду

Проводные датчики влажности Capacitive Soil Moisture Sensor v1.2, измеряющие влажность в ближних к месту установки ESP32 зонам полива

Датчики MiFlora, подключены к ESP32 по BLE, измеряющие влажность в удаленных зонах полива.

SONOFF 4Ch, прошитый ESPHome, расположен в водоразборном узле, куда приходят трубы от всех зон полива

4 Нормально-закрытых электромагнитных клапана на 220В расположены в водоразборном узле и подключены к Sonoff 4Ch. Открывают подачу воды для полива. Выбрана нормально-закрытая модель, с тем чтобы вероятность «наводнения» в случае каких-либо сбоев электрики и электроники была минимальной, и чтобы минимизировать количество требуемых выходов реле.

Импульсный водосчетчик, стоящий на входе в систему полива в водоразборном узле и подключенный к Sonoff 4ch. Позволил полностью передать данные о расходе воды в Home Asssistant и реализовать функционал полива заданным количеством. Весьма удачным оказалось то, что на этой версии sonoff уже распаяны контакты для прошивки и даже есть один свободный GPIO02 — на него и был повешен импульсный счетчик.

eczzd9zfq4drf8katpm4ofyn0b4.jpeg
Так выглядит коллектор с установленными клапанами и счетчиком воды. Контроллер (sonoff 4Ch) в кадр не попал, он установлен на расстоянии в полметра в щитке IP65

Настройки ESPHome и Home Assistant


Sonoff 4Ch
Код ESPHome для него максимально примитивен, но на всякий случай приведу:
switch:
  - platform: gpio
    name: "Система полива линия 1"
    pin: GPIO12
    id: sw1
    icon: mdi:water
  - platform: gpio
    name: "Система полива линия 2"
    pin: GPIO5
    id: sw2
    icon: mdi:water
  - platform: gpio
    name: "Система полива линия 3"
    pin: GPIO4
    id: sw3
    icon: mdi:water
  - platform: gpio
    name: "Система полива линия 4"
    pin: GPIO15
    id: sw4
    icon: mdi:water
binary_sensor:
  - platform: gpio
    name: "WaterCounter"
    id: button
    pin:
      number: GPIO2
      mode: INPUT_PULLUP


Capacitive Soil Moisture Sensor v1.2
Кусок кода для ESPHome:
sensor:
  - platform: adc
    pin: GPIO34
    filters:
      - lambda: |-
          if (x > 3.22) {
            return 0;
          } else if (x < 1.65) {
            return 100;
          } else {
            return (3.22-x) / (3.22-1.65) * 100.0;
          }
    name: "Датчик влажности почвы 1 линия проводной"
    update_interval: 60s
    attenuation: 11db
    unit_of_measurement: "%"
    accuracy_decimals: 0
    icon: mdi:water-percent

Подключать датчик можно только к аналоговым входам (ADC) микроконтроллера
Датчик придется калибровать, задав предельные значения напряжения для сухого датчика (в моем случае 3.22 В) и погруженного в воду (1,65 В). Я это делал включив демонстрацию log’ов в плагине ESPHome для HassIO и записав показания датчика в сухом виде и при погружении в воду.

sbtfb4ckgxx7kltxe6kk8a5q0r4.png

После перепрошивки ESP32 в Home Assistant ничего настраивать не надо, там автоматически появляется датчик влажности с правильными единицами измерения


Импульсный счетчик воды
Я использовал счетчик «Пульсар», но вообще должен подойти любой счетчик с импульсным выходом (идентифицируется по торчащему проводу). Принцип действия таких счетчиков очень простой — рядом с колесиками счетчика расположен геркон, который активируется магнитом, расположенном на одной из цифр колеса учета (у меня — цифра 3 на колесике 10 литров).
Соответственно, подключив провода от счетчика к GND и одному из GPIO мы можем получить простейший бинарный сенсор.

Код для ESPHome при этом примитивен:

binary_sensor:
  - platform: gpio
    name: "WaterCounter"
    id: counter
    pin:
      number: GPIO2
      mode: INPUT_PULLUP

В Home Assistant все немного сложнее:

Там я сделал несколько счетчиков (counter), сенсор и автоматизацию для работы с ними
При этом есть общий счетчик истраченной за все время воды (фактически, это виртуальный «двойник» механического счетчика). Он реализован в двух ипостасях — как counter, измеряемый в литрах и растущий в результате реакции на изменения бинарного сенсора из ESPHome, и как sensor, измеряемый в кубических метрах и берущий данные из предыдущего counter (для удобства сравнения цифр со счетами за воду).

Для целей управления поливом и сбора статистики были также созданы по 2 счетчика на каждую линию полива — один за все время, а второй за «сегодня». Так как физический счетчик у нас один, а линий четыре, для получения точных данных расхода по каждой линии полив каждой линии был разнесен по разным временным интервалам и запрещено одновременное их включение.

Кусок кода для автоматизации (внутри automations.yaml или отдельный файл)
- alias: Подсчет воды по общему счетчику
  trigger:
  - entity_id: binary_sensor.watercounter
    platform: state
    from: 'on'
    to: 'off'
  action:
  - data:
      entity_id:
      - counter.my_water_counter
    service: counter.increment
- alias: Подсчет воды по 1 линии
  trigger:
  - entity_id: binary_sensor.watercounter
    platform: state
    from: 'on'
    to: 'off'
  condition:
    - condition: state
      entity_id: switch.sistema_poliva_liniia_1
      state: 'on'
  action:
  - data:
      entity_id:
      - counter.my_water_line1, counter.my_water_line1t
    service: counter.increment    


Кусок кода configuration.yaml общий счетчик воды + два счетчика по одной линии полива

sensor:
  - platform: template
    sensors:
      water_counter:    
        unit_of_measurement: 'M3'
        value_template: "{{ (states('counter.my_water_counter')| float)/1000 }}"    
counter:
  my_water_counter:
    initial: 2.667
    step: 10
  my_water_line1:
    name: "Полив 1 линия за все время (л)"
    initial: 0
    step: 10
  my_water_line1t:
    name: "Полив 1 линия сегодня (л)"
    initial: 0
    step: 10



Датчик MiFlora
Датчик MiFlora при использовании ESPHome настраивается очень просто, инструкцию можно найти на сайте проекта esphome.io
В Home Assistant после такой настройки сразу появляются имеющиеся на датчике сенсоры — влажность, температура, освещенность и «фертильность» почвы. Единственный недостаток — странная работа сенсора заряда батареи, но для моих целей это не было критично.


Виртуальный сенсор прогнозируемых осадков
Смысл этого сенсора — выдавать в числовом виде прогноз осадков на ближайшие два дня. Эта цифра впоследствии используется в автоматизации и если она превышает заданный порог, полив не происходит.

Изначально сенсор построен на базе данных сервиса darksky. К сожалению, за время настройки системы этот сервис успела купить компания Apple и объявила о постепенном сворачивании работы сервиса «на сторону». API пока работает, но, судя по всему, скоро потребуется искать альтеранативу этому решению, благо в HA довольно много других сервисов погоды. Здесь я привожу настройки для darksky, думаю, что даже с другим сервисом большая их часть сохранит актуальность.

Сначала создаем 2 сенсора по количеству осадков на завтра и послезавтра:

Кусок кода configuration.yaml или sensors.yaml для сенсоров прогноза

sensor:
  - platform: darksky
    api_key: xxxx_your_API_key_xxxx
    forecast:
      - 1
      - 2
    monitored_conditions:
      - precip_intensity

В результате в HA появляются два сенсора: sensor.dark_sky_precip_intensity_1d и sensor.dark_sky_precip_intensity_2d, которые выдают цифры интенсивности осадков на завтра и послезавтра измеряемые в мм в час.

Затем делаем на основе трех прогнозов один template-sensor:
Кусок кода configuration.yaml или sensors.yaml для обобщенного сенсора осадков

sensor:
  - platform: template
    sensors:
       rain2days:    
        unit_of_measurement: 'mm'
        value_template: "{{ (((states('sensor.dark_sky_precip_intensity_2d')| float)+(states('sensor.dark_sky_precip_intensity_1d')| float))*24)| round(3) }}"    

В HA появляется sensor.rain2days который уже выдает общие осадки в мм на ближайшие 2 дня.
По опыту использования, прогноз от Darksky не особо точен если речь идет о слабеньком дождике, но сильные ливни он предсказывает очень неплохо и для моих целей этого вполне достаточно


После того, как все данные собраны, можно приступать непосредственно к поливу.

Вот так у меня выглядит кусок интерфейса с одной из зон в Home Assistant:

pfl6ut8aoieytcg0kxlk-mjslcu.png

Здесь можно задать количество воды для полива (ползунком) и посмотреть значения основных сенсоров и счетчиков. Я привел интерфейс для одной из линий, для остальных все аналогично, только на линиях с проводными датчиками данных несколько меньше.

В интерфейсе можно заметить одну «лишнюю» деталь — вспомогательный сенсор «Достигнута норма». Его пришлось ввести, т.к. мне не удалось заставить работать condition: template для остановки автоматизации при достижении нормы по количеству воды, и в результате автоматизация просто проверяет значение этого сенсора. Уверен, что эту часть автоматизации можно сделать проще и элегантней, но моего уровня для этого не хватило.

Ниже код получившегося «костыльного» темплейт-сенсора:

Сенсор достаточности полива (внутри configuration.yaml или отдельный файл)
  - platform: template
    sensors:
      line4_status:
        friendly_name: "Линия 4 - достигнута норма"
        value_template: >-
          {% if states('counter.my_water_line4t')|float > states('input_number.slider4')|float %}
            yes
          {% elif states('counter.my_water_line4t')|float == states('input_number.slider4')|float  %}
            yes
          {% else %}
            no
          {% endif %}


Автоматизация для запуска полива в конечном итоге выглядит так:

Запуск полива (внутри automations.yaml или отдельный файл)
- alias: Включение полива 4я линия в 23.01
  trigger:
    platform: time
    at: "23:01:00"
  condition:
   condition: and
   conditions:
# ПРОВЕРЯЕМ НОРМУ ПО ОСАДКАМ
    - condition: numeric_state
      entity_id: sensor.rainfor2days
      below: 5
# ПРОВЕРЯЕМ НОРМУ ПО ПОКАЗАНИЮ ДАТЧИКА ВЛАЖНОСТИ
    - condition: numeric_state
      entity_id: sensor.miflora_1_moisture
      below: 50
# ПРОВЕРЯЕМ, НАДО ЛИ ЕЩЕ ПОЛИВАТЬ СЕГОДНЯ ПО КОЛИЧЕСТВУ
    - condition: state
      entity_id: 'sensor.line4_status'
      state: 'no'
  action:
   - service: switch.turn_on
     entity_id: switch.sistema_poliva_liniia_4


Полив запускается поздно вечером, при этом каждая линия запускается в свой временной интервал. Разделение по времени запуска позволяет использовать один счетчик воды на входе для получения данных по 4 линиям.

При запуске проверяются три условия:

  • не превышен ли лимит по количеству воды на сегодня (если, например, включали полив вручную)
  • не превышает ли влажность 50% (по наблюдениям в наших условиях свежеполитая почва имеет влажность не более 60%)
  • не ожидается ли осадков более 5 мм в ближайшие два дня.


Следующая автоматизация — отключение полива:

Отключение полива (внутри automations.yaml или отдельный файл)
- alias: Выключение полива 4й линии
  trigger:
#Отключение по достижению лимита воды на полив
  - entity_id: sensor.line4_status
    platform: state
    to: 'yes'
    for: 
      seconds: 5    
#Отключение по времени 
  - platform: time
    at: "23:59:00"
#Отключение по достижению предельной влажности 
  - platform: numeric_state
    entity_id: sensor.miflora_1_moisture
    above: 65
#Отключение по времени нахождения крана в открытом состоянии
  - platform: state
    entity_id: switch.sistema_poliva_liniia_4
    to: 'on'
    for: 
      minutes: 60
  action:
   - service: switch.turn_off
     entity_id: switch.sistema_poliva_liniia_4


В автоматизации использовано целых 4 варианта триггеров, но в большинстве случаев она срабатывает по первому — «костыльному» сенсору, который отслеживает превышение лимита по количеству воды. Остальные триггеры сделаны в большой степени для подстраховки.

Ну и последняя относящаяся к проблеме автоматизация — обнуление ежедневного счетчика

Обнуление ежедневного счетчика (внутри automations.yaml или отдельный файл)

- alias: Обнуление ежедневного таймера 4я линия
  trigger:
  - platform: time
    at: "00:00:01"
  action:
  - service: counter.reset
    entity_id: counter.my_water_line4t


Экономика проекта


Затраты на управляющую часть системы полива получились следующие:

(Raspberry PIE c HassIO на борту и WiFi router с покрытием в саду уже были до начала проекта, их я не учитываю)

Электромагнитный клапан UNIPUMP BCX-15 ½» (нормально закрытый) 4×20 евро
Sonoff 4CH 17 евро
Счетчик импульсный Пульсар 8 евро
ESP32 DevKitC 3.5 евро
Capacitive Soil Moisture Sensor v1.2 2×0.67 евро
Датчики MiFlora 2×16 евро
Щитки, коллектор, провода, фиттинги все вместе около 50 евро

ИТОГО: около 190 евро

Затраты времени на настройку датчиков и МК — примерно 3–4 вечера по нескольку часов, но большая часть времени была потрачена на «изобретение велосипедов» и придумывание «костылей», в целом работы там немного. Физическая сборка системы заняла около 2 вечеров.
В целом, ожидается экономия воды примерно в 20–50% по сравнению с «глуповатой» системой на таймерах и при местных ценах на воду система должна окупиться за один-два сезона.

Недостатки и планы по доработке


По итогам выполнения проекта вскрылись некоторые нюансы и возможности для дальнейшего совершенствования.

В частности, я бы заменил электромагнитные клапана 220В на модель 24В — это напряжение являются стандартными для систем полива. В этом случае пришлось бы добавить в систему трансформатор на 24В и сменить Sonoff 4Ch на что-то с сухим контактом (например, Sonoff 4CH Pro или что-то самосборное). Сами клапана при этом стоят дешевле (от 8 евро) и снижают вероятность поражения электрическим током.

Также выяснилось, что для работы с пластиковыми трубопроводами давление из водопровода является слишком высоким, и фитинги могут подтекать во время цикла полива. В моем случае это не критично, все фитинги расположены над поливаемой землей, но по-хорошему надо добавить на входе редуктор для понижения давления.

Еще немного расстроила невозможность учета количества воды для полива в объемах меньших чем 10 литров — именно этот объем является минимальной измеряемой величиной для такого счетчика. Эту проблему можно решить, разобрав счетчик и поменяв местами колесики, но пока до этого не дошли руки.

© Habrahabr.ru