Irrigation controller with EspHome

I just want to share my irrigation controller based on a ESP32 device and a 8 channel relay module. The programming is done using EspHome. With my setup I control six valves and the main pump.

What’s so special about it is, that the automation runs completely on the ESP device and the Home Assistant frontend is only used to feed in the programming. My irrigation controller is quite far from my access point, so I can’t rely on a stable Wi-Fi signal all the time. Therefore the automation still works even if the signal is lost or the Home Assistant server crashes.


Installation instructions are in the README.

18 Likes

awesome!!! great job @alengwenus, I was thinking to build something similar… but now I only need to study your implementation. thank you for sharing

there is a point I was thinking about and I would like to know how you managed, there is a control to stop the zone in case the zone remains open longer than expected?

I have another question: I don’t have a main pump; shall I remove it and keep only the zones ?

regards

Hello, I have the same exact setup only mine is in a plastic tub half finished. :sweat_smile: This really is motivating me want to finish. You mentioned that you have your valves at the main pump. How does that pump get water? Do you have a water tank? If so, do you have to fill it up manually or is that automated too? I guess what I am asking is, do you have more pictures, or more information on how the pumps/valves are setup?

Thank you and great work!

My pump gets groundwater via a suction pipe. The borehole is about 5 metres away (outside the garage). The groundwater level is at about 4.5 metres below the ground surface.
The water in the pressure line is then fed to the individual magnetic valves using a “splitter”.
Here is an annotated picture of my hardware setup. I hope that helps. :wink:

2 Likes

This is really cool. Thank you for posting that. Final question, I notice you have the id: write_led. What purpose does that serve?

I have a very similar setup with a 2 zone system. I also have 2 manual run buttons.

https://www.wesley.email/index.php/automation/watering-controller


You have a very nice tidy setup. Great idea with the baluns too. :+1:

The write_led was just for debugging purposes. As ESPs have limited write cycles for permanent storage, I wanted to ensure that there are no endless write attempts because of some kind of bug in the code.

Little Bump, can you share wiring diagram too ?
My setup is bit different, each zone need 2 relays, one to open one to close. Trying to adjust your ESPHome template to my needs

There is a sprinkler component incoming to esphome - might come in handy:

Dear alengwenus,
thank you very much for sharing this wonderful work. I copied your code, adjusted it to my needs and run it on a ESP8266. It works well so far, but I observe some strange behaviour. After the ESP8266 looses connection from time to time one zone starts again and again. The others don’t. I have not found a reason for this yet. Do you have any idea?

Awesome!
I have just started building this!
Now, in your code, I see you use a pushbutton to start manually, disable automation and re-enable automation, depending on how long the button is pushed?
I can see the debugging showing these activities indeed, though don’t see it reflected in the dashboard?

Then, just to make sure I understand properly:
The “Irrigation time” parameter is to increase or decrease by a certain percentage? What would you say is the use case you had in mind?
The “Skip days” parameter is to skip a ‘fixed’ amount of days in the schedule? So basically like ‘every n days’?

My plans for this built is to:

  • Include 2 buttons (One (green) to manually open the pump valve, another (red) to stop all current activities. Red will also have to postpone the schedule by a day, and disable all automation.
  • Add a display to show the remaining running time, maybe the time until the next run, as well as the actions performed by the buttons.
  • Include the weather forecast and sunset as part of the automation.

And maybe, add a flowmeter to detect problems, but haven’t really thought that through yet.

First, thanks to all who developed this.

Curious if anyone has worked out a functional evaporation feedback for this?

The idea is using online weather to scale the watering schedule daily based on local evaporation rates. My rainmachine controller does this and it has worked very well for me over the years. Together with this, it’s also nice to have a feature that moves the start time so all watering finishes at a certain time everyday (like sunrise).

I honestly was fine with an old school timer, and got interested in doing the smart sprinkler thing just for the ability to test/inspect irrigation quickly (ie switch valves from my phone). I went with the big rainmachine model. Normally I prefer DIY, but RM is an ‘cloud free’ device and it was prepandemic when I got it.

Old question but that happen if use a pin to relay controller that pull up on restart. It better to use ESP32.

Hi, would it be possible for you to share the wiring diagram of your irrigation system with us? Thanks

HI,

with the release of the Sprinkler control, this project should give new ideas

DIY 8 station irrigation based on ESPhome on KC868-A8 relay board - Share your Projects! - Home Assistant Community (home-assistant.io)

I sell a 9 valve sprinkler controller on Tindie. It is based on the ESP32 and uses the sprinkler component in ESPHome. Here’s a picture of it:

You can buy it on Tindie. Here’s the link:

1 Like

Due to changes in esphome I had to setup my esp8266 from scratch. I have no pump and so I deleted this part.
I setup multiple entities card via hacs and adjusted/ added the lines in my configuration.yaml. After restarting haos I add the node in esphome integration. The esp8266 node shows up, but I find only one device with one entity (update). There are no other entities to find and thus all the switches are not available in the dashboard. I see weather forecast and time only of course.
Deleted the node from the ha integration and reconfigured it, api encryption key deleted, did not change.
Has someone an idea where all the entities are gone or why they don’t show up :thinking:?

INFO Reading configuration /config/esphome/gartenbewaesserung.yaml...
INFO Detected timezone 'Europe/Berlin'
INFO Generating C++ source...
INFO Compiling app...
Processing gartenbewaesserung (board: esp01_1m; framework: arduino; platform: platformio/[email protected])
--------------------------------------------------------------------------------
Library Manager: Installing esphome/ESPAsyncTCP-esphome @ 1.2.3
INFO Installing esphome/ESPAsyncTCP-esphome @ 1.2.3
Unpacking  [####################################]  100%
Library Manager: [email protected] has been installed!
INFO [email protected] has been installed!
Library Manager: Installing esphome/ESPAsyncWebServer-esphome @ 2.1.0
INFO Installing esphome/ESPAsyncWebServer-esphome @ 2.1.0
Unpacking  [####################################]  100%
Library Manager: [email protected] has been installed!
INFO [email protected] has been installed!
Library Manager: Resolving dependencies...
INFO Resolving dependencies...
Library Manager: Installing ottowinter/ESPAsyncTCP-esphome
INFO Installing ottowinter/ESPAsyncTCP-esphome
Unpacking  [####################################]  100%
Library Manager: [email protected] has been installed!
INFO [email protected] has been installed!
HARDWARE: ESP8266 80MHz, 80KB RAM, 1MB Flash
Dependency Graph
|-- ESPAsyncTCP-esphome @ 1.2.3
|-- ESPAsyncWebServer-esphome @ 2.1.0
|-- DNSServer @ 1.1.1
|-- ESP8266WiFi @ 1.0
|-- ESP8266mDNS @ 1.2
.
Compiling ...
.
Archiving /data/gartenbewaesserung/.pioenvs/gartenbewaesserung/libFrameworkArduino.a
Linking /data/gartenbewaesserung/.pioenvs/gartenbewaesserung/firmware.elf
RAM:   [====      ]  44.9% (used 36768 bytes from 81920 bytes)
Flash: [=====     ]  46.1% (used 471929 bytes from 1023984 bytes)
Building /data/gartenbewaesserung/.pioenvs/gartenbewaesserung/firmware.bin
esp8266_copy_factory_bin(["/data/gartenbewaesserung/.pioenvs/gartenbewaesserung/firmware.bin"], ["/data/gartenbewaesserung/.pioenvs/gartenbewaesserung/firmware.elf"])
======================== [SUCCESS] Took 401.06 seconds ========================
INFO Successfully compiled program.
INFO Connecting to 192.168.188.102
INFO Uploading /data/gartenbewaesserung/.pioenvs/gartenbewaesserung/firmware.bin (476080 bytes)
INFO Compressed to 325808 bytes
Uploading: [============================================================] 100% Done...

INFO Waiting for result...
INFO OTA successful
INFO Successfully uploaded program.
INFO Starting log output from 192.168.188.102 using esphome API
INFO Successfully connected to 192.168.188.102
[19:49:29][I][app:102]: ESPHome version 2023.6.2 compiled on Jun 28 2023, 19:44:52
[19:49:29][C][wifi:543]: WiFi:
[19:49:29][C][wifi:379]:   Local MAC: C8:C9:A3:66:A1:B3
[19:49:29][C][wifi:380]:   SSID: 'FRITZBox-7590-5293180'[redacted]
[19:49:29][C][wifi:381]:   IP Address: 192.168.188.102
[19:49:29][C][wifi:382]:   BSSID: 3C:37:12:4B:39:76[redacted]
[19:49:29][C][wifi:384]:   Hostname: 'gartenbewaesserung'
[19:49:29][C][wifi:386]:   Signal strength: -67 dB ▂▄▆█
[19:49:29][C][wifi:390]:   Channel: 6
[19:49:29][C][wifi:391]:   Subnet: 255.255.255.0
[19:49:29][C][wifi:392]:   Gateway: 192.168.188.1
[19:49:29][C][wifi:393]:   DNS1: 0.0.0.0
[19:49:29][C][wifi:394]:   DNS2: 0.0.0.0
[19:49:29][C][logger:301]: Logger:
[19:49:29][C][logger:302]:   Level: DEBUG
[19:49:29][C][logger:303]:   Log Baud Rate: 115200
[19:49:29][C][logger:305]:   Hardware UART: UART0
[19:49:29][C][template.select:065]: Template Select 'Zone 1 start'
[19:49:29][C][template.select:066]:   Update Interval: 60.0s
[19:49:29][C][template.select:069]:   Optimistic: YES
[19:49:29][C][template.select:070]:   Initial Option: 20:00
[19:49:29][C][template.select:071]:   Restore Value: YES
[19:49:29][C][template.select:065]: Template Select 'Zone 2 start'
[19:49:29][C][template.select:066]:   Update Interval: 60.0s
[19:49:29][C][template.select:069]:   Optimistic: YES
[19:49:29][C][template.select:070]:   Initial Option: 18:00
[19:49:29][C][template.select:071]:   Restore Value: YES
[19:49:29][C][template.select:065]: Template Select 'Zone 3 start'
[19:49:29][C][template.select:066]:   Update Interval: 60.0s
[19:49:29][C][template.select:069]:   Optimistic: YES
[19:49:29][C][template.select:070]:   Initial Option: 20:30
[19:49:29][C][template.select:071]:   Restore Value: YES
[19:49:29][C][template.select:065]: Template Select 'Zone 4 start'
[19:49:29][C][template.select:066]:   Update Interval: 60.0s
[19:49:29][C][template.select:069]:   Optimistic: YES
[19:49:29][C][template.select:070]:   Initial Option: 19:30
[19:49:29][C][template.select:071]:   Restore Value: YES
[19:49:29][C][template.select:065]: Template Select 'Zone 5 start'
[19:49:29][C][template.select:066]:   Update Interval: 60.0s
[19:49:29][C][template.select:069]:   Optimistic: YES
[19:49:29][C][template.select:070]:   Initial Option: 18:45
[19:49:29][C][template.select:071]:   Restore Value: YES
[19:49:29][C][template.select:065]: Template Select 'Zone 6 start'
[19:49:29][C][template.select:066]:   Update Interval: 60.0s
[19:49:29][C][template.select:069]:   Optimistic: YES
[19:49:29][C][template.select:070]:   Initial Option: 17:15
[19:49:29][C][template.select:071]:   Restore Value: YES
[19:49:29][C][template.number:050]: Template Number 'Zone 1 duration'
[19:49:29][C][template.number:050]:   Unit of Measurement: 'min'
[19:49:29][C][template.number:051]:   Optimistic: YES
[19:49:29][C][template.number:052]:   Update Interval: 60.0s
[19:49:29][C][template.number:050]: Template Number 'Zone 2 duration'
[19:49:29][C][template.number:050]:   Unit of Measurement: 'min'
[19:49:29][C][template.number:051]:   Optimistic: YES
[19:49:29][C][template.number:052]:   Update Interval: 60.0s
[19:49:29][C][template.number:050]: Template Number 'Zone 3 duration'
[19:49:29][C][template.number:050]:   Unit of Measurement: 'min'
[19:49:29][C][template.number:051]:   Optimistic: YES
[19:49:29][C][template.number:052]:   Update Interval: 60.0s
[19:49:29][C][template.number:050]: Template Number 'Zone 4 duration'
[19:49:29][C][template.number:050]:   Unit of Measurement: 'min'
[19:49:29][C][template.number:051]:   Optimistic: YES
[19:49:29][C][template.number:052]:   Update Interval: 60.0s
[19:49:29][C][template.number:050]: Template Number 'Zone 5 duration'
[19:49:29][C][template.number:050]:   Unit of Measurement: 'min'
[19:49:29][C][template.number:051]:   Optimistic: YES
[19:49:29][C][template.number:052]:   Update Interval: 60.0s
[19:49:29][C][template.number:050]: Template Number 'Zone 6 duration'
[19:49:29][C][template.number:050]:   Unit of Measurement: 'min'
[19:49:29][C][template.number:051]:   Optimistic: YES
[19:49:29][C][template.number:052]:   Update Interval: 60.0s
[19:49:29][C][template.number:050]: Template Number 'Time Multiplier'
[19:49:29][C][template.number:050]:   Unit of Measurement: '%'
[19:49:29][C][template.number:051]:   Optimistic: YES
[19:49:29][C][template.number:052]:   Update Interval: 60.0s
[19:49:29][C][template.number:050]: Template Number 'Skip Days'
[19:49:29][C][template.number:051]:   Optimistic: YES
[19:49:29][C][template.number:052]:   Update Interval: 60.0s
[19:49:29][C][template.sensor:022]: Template Sensor 'Zone 1 remaining'
[19:49:29][C][template.sensor:022]:   State Class: ''
[19:49:29][C][template.sensor:022]:   Unit of Measurement: 'min'
[19:49:29][C][template.sensor:022]:   Accuracy Decimals: 0
[19:49:29][C][template.sensor:023]:   Update Interval: 60.0s
[19:49:29][C][template.sensor:022]: Template Sensor 'Zone 2 remaining'
[19:49:29][C][template.sensor:022]:   State Class: ''
[19:49:29][C][template.sensor:022]:   Unit of Measurement: 'min'
[19:49:29][C][template.sensor:022]:   Accuracy Decimals: 0
[19:49:29][C][template.sensor:023]:   Update Interval: 60.0s
[19:49:29][C][template.sensor:022]: Template Sensor 'Zone 3 remaining'
[19:49:29][C][template.sensor:022]:   State Class: ''
[19:49:29][C][template.sensor:022]:   Unit of Measurement: 'min'
[19:49:29][C][template.sensor:022]:   Accuracy Decimals: 0
[19:49:29][C][template.sensor:023]:   Update Interval: 60.0s
[19:49:29][C][template.sensor:022]: Template Sensor 'Zone 4 remaining'
[19:49:29][C][template.sensor:022]:   State Class: ''
[19:49:29][C][template.sensor:022]:   Unit of Measurement: 'min'
[19:49:29][C][template.sensor:022]:   Accuracy Decimals: 0
[19:49:29][C][template.sensor:023]:   Update Interval: 60.0s
[19:49:29][C][template.sensor:022]: Template Sensor 'Zone 5 remaining'
[19:49:29][C][template.sensor:022]:   State Class: ''
[19:49:29][C][template.sensor:022]:   Unit of Measurement: 'min'
[19:49:29][C][template.sensor:022]:   Accuracy Decimals: 0
[19:49:29][C][template.sensor:023]:   Update Interval: 60.0s
[19:49:29][C][template.sensor:022]: Template Sensor 'Zone 6 remaining'
[19:49:29][C][template.sensor:022]:   State Class: ''
[19:49:29][C][template.sensor:022]:   Unit of Measurement: 'min'
[19:49:29][C][template.sensor:022]:   Accuracy Decimals: 0
[19:49:29][C][template.sensor:023]:   Update Interval: 60.0s
[19:49:29][C][template.switch:068]: Template Switch 'Irrigation Zone 1'
[19:49:29][C][template.switch:090]:   Restore Mode: always OFF
[19:49:29][C][template.switch:060]:   Restore State: NO
[19:49:29][C][template.switch:061]:   Optimistic: NO
[19:49:29][C][template.switch:068]: Template Switch 'Irrigation Zone 2'
[19:49:29][C][template.switch:090]:   Restore Mode: always OFF
[19:49:29][C][template.switch:060]:   Restore State: NO
[19:49:29][C][template.switch:061]:   Optimistic: NO
[19:49:29][C][template.switch:068]: Template Switch 'Irrigation Zone 3'
[19:49:29][C][template.switch:090]:   Restore Mode: always OFF
[19:49:29][C][template.switch:060]:   Restore State: NO
[19:49:29][C][template.switch:061]:   Optimistic: NO
[19:49:30][C][template.switch:068]: Template Switch 'Irrigation Zone 4'
[19:49:30][C][template.switch:090]:   Restore Mode: always OFF
[19:49:30][C][template.switch:060]:   Restore State: NO
[19:49:30][C][template.switch:061]:   Optimistic: NO
[19:49:30][C][template.switch:068]: Template Switch 'Irrigation Zone 5'
[19:49:30][C][template.switch:090]:   Restore Mode: always OFF
[19:49:30][C][template.switch:060]:   Restore State: NO
[19:49:30][C][template.switch:061]:   Optimistic: NO
[19:49:30][C][template.switch:068]: Template Switch 'Irrigation Zone 6'
[19:49:30][C][template.switch:090]:   Restore Mode: always OFF
[19:49:30][C][template.switch:060]:   Restore State: NO
[19:49:30][C][template.switch:061]:   Optimistic: NO
[19:49:30][C][template.switch:068]: Template Switch 'Zone 1 enabled'
[19:49:30][C][template.switch:090]:   Restore Mode: always OFF
[19:49:30][C][template.switch:060]:   Restore State: YES
[19:49:30][C][template.switch:061]:   Optimistic: YES
[19:49:30][C][template.switch:068]: Template Switch 'Zone 2 enabled'
[19:49:30][C][template.switch:090]:   Restore Mode: always OFF
[19:49:30][C][template.switch:060]:   Restore State: YES
[19:49:30][C][template.switch:061]:   Optimistic: YES
[19:49:30][C][template.switch:068]: Template Switch 'Zone 3 enabled'
[19:49:30][C][template.switch:090]:   Restore Mode: always OFF
[19:49:30][C][template.switch:060]:   Restore State: YES
[19:49:30][C][template.switch:061]:   Optimistic: YES
[19:49:30][C][template.switch:068]: Template Switch 'Zone 4 enabled'
[19:49:30][C][template.switch:090]:   Restore Mode: always OFF
[19:49:30][C][template.switch:060]:   Restore State: YES
[19:49:30][C][template.switch:061]:   Optimistic: YES
[19:49:30][C][template.switch:068]: Template Switch 'Zone 5 enabled'
[19:49:30][C][template.switch:090]:   Restore Mode: always OFF
[19:49:30][C][template.switch:060]:   Restore State: YES
[19:49:30][C][template.switch:061]:   Optimistic: YES
[19:49:30][C][template.switch:068]: Template Switch 'Zone 6 enabled'
[19:49:30][C][template.switch:090]:   Restore Mode: always OFF
[19:49:30][C][template.switch:060]:   Restore State: YES
[19:49:30][C][template.switch:061]:   Optimistic: YES
[19:49:30][C][template.switch:068]: Template Switch 'Automation enabled'
[19:49:30][C][template.switch:090]:   Restore Mode: always OFF
[19:49:30][C][template.switch:060]:   Restore State: YES
[19:49:30][C][template.switch:061]:   Optimistic: YES
[19:49:30][C][switch.gpio:068]: GPIO Switch 'irrigation_channel6'
[19:49:30][C][switch.gpio:090]:   Restore Mode: always OFF
[19:49:30][C][switch.gpio:031]:   Pin: GPIO2
[19:49:30][C][switch.gpio:068]: GPIO Switch 'irrigation_channel5'
[19:49:30][C][switch.gpio:090]:   Restore Mode: always OFF
[19:49:30][C][switch.gpio:031]:   Pin: GPIO0
[19:49:30][C][switch.gpio:068]: GPIO Switch 'irrigation_channel4'
[19:49:30][C][switch.gpio:090]:   Restore Mode: always OFF
[19:49:30][C][switch.gpio:031]:   Pin: GPIO15
[19:49:30][C][switch.gpio:068]: GPIO Switch 'irrigation_channel3'
[19:49:30][C][switch.gpio:090]:   Restore Mode: always OFF
[19:49:30][C][switch.gpio:031]:   Pin: GPIO13
[19:49:30][C][switch.gpio:068]: GPIO Switch 'irrigation_channel2'
[19:49:30][C][switch.gpio:090]:   Restore Mode: always OFF
[19:49:30][C][switch.gpio:031]:   Pin: GPIO12
[19:49:30][C][switch.gpio:068]: GPIO Switch 'irrigation_channel1'
[19:49:30][C][switch.gpio:090]:   Restore Mode: always OFF
[19:49:30][C][switch.gpio:031]:   Pin: GPIO14
[19:49:30][C][gpio.binary_sensor:015]: GPIO Binary Sensor 'manual_gpio'
[19:49:30][C][gpio.binary_sensor:016]:   Pin: GPIO5
[19:49:30][C][homeassistant.time:010]: Home Assistant Time:
[19:49:30][C][homeassistant.time:011]:   Timezone: 'CET-1CEST,M3.5.0,M10.5.0/3'
[19:49:30][C][restart.button:017]: Restart Button 'Irrigation Restart'
[19:49:30][C][status:034]: Status Binary Sensor 'Irrigation Status'
[19:49:30][C][status:034]:   Device Class: 'connectivity'
[19:49:30][C][captive_portal:088]: Captive Portal:
[19:49:30][C][mdns:108]: mDNS:
[19:49:30][C][mdns:109]:   Hostname: gartenbewaesserung
[19:49:30][C][ota:093]: Over-The-Air Updates:
[19:49:30][C][ota:094]:   Address: 192.168.188.102:8266
[19:49:30][C][ota:097]:   Using Password.
[19:49:30][C][api:138]: API Server:
[19:49:30][C][api:139]:   Address: 192.168.188.102:6053
[19:49:30][C][api:143]:   Using noise encryption: NO
[19:49:30][C][wifi_signal.sensor:009]: WiFi Signal 'Irrigation Wifi'
[19:49:30][C][wifi_signal.sensor:009]:   Device Class: 'signal_strength'
[19:49:30][C][wifi_signal.sensor:009]:   State Class: 'measurement'
[19:49:30][C][wifi_signal.sensor:009]:   Unit of Measurement: 'dBm'
[19:49:30][C][wifi_signal.sensor:009]:   Accuracy Decimals: 0
[19:49:38][D][sensor:093]: 'Zone 6 remaining': Sending state 0.00000 min with 0 decimals of accuracy
[19:49:38][D][sensor:093]: 'Zone 2 remaining': Sending state 0.00000 min with 0 decimals of accuracy
[19:49:40][D][sensor:093]: 'Zone 5 remaining': Sending state 0.00000 min with 0 decimals of accuracy
[19:49:44][D][sensor:093]: 'Zone 1 remaining': Sending state 0.00000 min with 0 decimals of accuracy
[19:49:52][D][sensor:093]: 'Zone 3 remaining': Sending state 0.00000 min with 0 decimals of accuracy
[19:49:55][D][sensor:093]: 'Zone 4 remaining': Sending state 0.00000 min with 0 decimals of accuracy
[19:50:02][D][sensor:093]: 'Irrigation Wifi': Sending state -75.00000 dBm with 0 decimals of accuracy

Solution:

Obviously ESP8266 cannot load libraries needed for text sensors. I figured this out after months of trials and search and changed to an ESP32. Now it runs again like a charm.

Hi @alengwenus
I would like to start a project like yours. I have an ESP8266 8 relay board, and I would like to create a micro irrigation system for pots.

  • 1 pump, 5 valves.

However, I would like to be able to choose the skip of the day for each individual valve, for example valve 1 active every day, valve 2 active one day and one day not.
(this is because I water some plants every day, and some every 3 days etc.)

Could you help me edit your file? Thanks