Automatic garden watering system for Home Assistant, ESP8266 and MiFlora



Some time ago my family had a house with a small garden in a very warm and arid place, and we faced the problem of regular watering.

I wanted the irrigation system to be automatic, while choosing it I had to take into account the following conditions:

  • very expensive water that must be saved in all available ways
  • different plants in the garden for moisture requirements, from succulents to moisture-loving
  • the need for fully autonomous watering during the absence of people in the house, preferably with the possibility of remote control
  • arid climate that does not forgive irrigation errors

After evaluating the ready-made solutions that were found on local DIY networks and on Amazon and reading reviews about their reliability (usually not the highest), we decided to try to do something on our own.

Disclaimer: The author is not an IT specialist, and does not claim to be a professional knowledge of the topic. The level of project execution is a hobby. The author is well aware of the level of his knowledge in programming and electronics and will greatly appreciate suggestions for improving and optimizing the solutions used.

Circuit diagram


The garden was divided into 4 irrigation zones, each of them is equipped with an individual soil moisture sensor and can be watered according to an individual schedule and a different amount of water.
On the ground, PND-pipes of drip irrigation with perforation are laid, which are connected to pipes converging in the water-collecting unit and connected through the electromagnetic valves to the water supply. The valves are controlled by relays connected to the ESP8266 (Sonoff 4Ch).

Watering is carried out by timers, at night, to increase the amount of water that is absorbed into the ground and will not be evaporated by the sun.

At the scheduled watering time, compliance with several conditions is checked:

  • soil moisture below a predetermined value
  • there are no predicted precipitation in a large enough amount for the next 2 days
  • water limit for irrigation set for this line is not exceeded

Used equipment


Raspberry Pie with HassIO installed (already had)

ESP32 DevKit , an ESPHome firmware, acting as a bluetooth gateway for MiFlora and receiving data from wired humidity sensors. Located in the garden.

Wired moisture sensors Capacitive Soil Moisture Sensor v1.2 , which measure humidity in the watering zones closest to the ESP32 installation site. MiFlora

sensors are connected to the ESP32 via BLE, which measure moisture in remote watering zones.

SONOFF 4Ch , stitched with ESPHome, is located in the water intake unit, where pipes from all watering zones come

4 Normally-closed solenoid valves for 220Vlocated in the water stand and connected to the Sonoff 4Ch. Open the water supply for irrigation. A normally-closed model was chosen so that the probability of “flooding” in the event of any failure of the electrics and electronics was minimized, and in order to minimize the number of required relay outputs.

A pulsed water meter at the entrance to the irrigation system in the water intake unit and connected to the Sonoff 4ch. Allowed to fully transfer water flow data to Home Asssistant and implement the irrigation functionality with a given amount. It turned out to be very successful that on this version of sonoff the contacts for firmware were already soldered and even there was one free GPIO02 - a pulse counter was hung on it.


It looks like a collector with installed valves and a water meter. The controller (sonoff 4Ch) did not get into the frame, it is installed at a distance of half a meter in the IP65 shield

ESPHome and Home Assistant Settings


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 .



ESP32 Home Assistant ,

Pulse Water Meter
«», ( ). — , , ( — 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 Sensor
MiFlora ESPHome , esphome.io
Home Assistant — , , «» . — , .

Virtual rainfall sensor
— . , .

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 ,


After all the data is collected, you can proceed directly to watering.

This is how I look at a piece of the interface from one of the zones in the Home Assistant:



Here you can set the amount of water for irrigation (with a slider) and see the values ​​of the main sensors and counters. I gave the interface for one of the lines, for the rest everything is the same, only on lines with wired data sensors it is slightly less.

In the interface, you can notice one “superfluous” detail - the auxiliary sensor “The norm has been reached”. It had to be introduced, because I was not able to get condition: template to work to stop the automation when the norm for the amount of water was reached, and as a result, the automation just checks the value of this sensor. I am sure that this part of automation can be made simpler and more elegant, but my level was not enough for this.

Below is the code for the resulting “crutch” template sensor:

Watering sufficiency sensor (inside configuration.yaml or a separate file)
  - 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 %}


Automation to start watering ultimately looks like this:

Start watering (inside automations.yaml or a separate file)
- 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


Watering starts late in the evening, with each line starting at its own time interval. Separation by start time allows you to use one inlet water meter to obtain data on 4 lines.

At startup, three conditions are checked:

  • Is the limit on the amount of water for today not exceeded (if, for example, manual watering was turned on)
  • does the humidity exceed 50% (according to observations in our conditions, freshly spilled soil has a moisture content of not more than 60%)
  • precipitation greater than 5 mm is not expected in the next two days.

The next automation is disabling watering:

Disabling watering (inside automations.yaml or a separate file)
- 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


In automation, as many as 4 variants of triggers were used, but in most cases it works according to the first - a “crutch” sensor, which monitors the excess of the limit by the amount of water. The rest of the triggers are made to a large extent for safety reasons.

Well, the last automation related to the problem is resetting the daily counter

Zeroing the daily counter (inside automations.yaml or a separate file)

- alias:    4 
  trigger:
  - platform: time
    at: "00:00:01"
  action:
  - service: counter.reset
    entity_id: counter.my_water_line4t


Project economics


The costs for the control part of the irrigation system were as follows:

(Raspberry PIE with HassIO on board and a WiFi router with a coating in the garden were already before the start of the project, I don’t take them into account)

UNIPUMP BCX-15 1/2 "solenoid valve (normally closed) 4 * 20 euros
Sonoff 4CH 17 euros
Pulse meter Pulsar 8 euros
ESP32 DevKitC 3.5 euros
Capacitive Soil Moisture Sensor v1.2 2 * 0.67 euros
MiFlora sensors 2 * 16 euros
Guards, collector, wires, fittings all together about 50 euros

TOTAL: about 190 euros

The time spent on setting up the sensors and MK is approximately 3-4 pm for several hours, but most of the time was spent on “inventing bicycles” and inventing “crutches”, in general, there is not much work. The physical assembly of the system took about 2 evenings.
In general, water savings of about 20-50% are expected compared to the “silly" timer system and at local water prices, the system should pay off in one or two seasons.

Shortcomings and plans for revision


As a result of the project, some nuances and opportunities for further improvement were revealed.

In particular, I would replace 220V solenoid valves with a 24V model - this voltage is standard for irrigation systems. In this case, you would have to add a 24V transformer to the system and change the Sonoff 4Ch to something with a dry contact (for example, Sonoff 4CH Pro or something self-assembled). Valves themselves are cheaper (from 8 euros) and reduce the likelihood of electric shock.

It also turned out that for working with plastic pipelines, the pressure from the water supply is too high, and the fittings can leak during the irrigation cycle. In my case, this is not critical, all fittings are located above the watering ground, but in a good way you need to add a reducer at the inlet to lower the pressure.

I was even more upset by the impossibility of accounting for the amount of water for irrigation in volumes less than 10 liters - this volume is the minimum measurable quantity for such a meter. This problem can be solved by disassembling the counter and swapping the wheels, but until then hands have not reached it.

All Articles