Building a 4-Zone Irrigation Controller with ESPHome - Part 2
ESPHome Configuration
Here’s a sample YAML config for a 4-zone irrigation controller:
esphome:
name: esphome-web-806180
friendly_name: ESPHome Garden Irrigation Controller
min_version: 2025.5.0
name_add_mac_suffix: false
esp32:
board: esp32dev
framework:
type: esp-idf
# Enable logging
logger:
# Enable Home Assistant API
# Enable Home Assistant API
api:
# Allow Over-The-Air updates
ota:
- platform: esphome
text_sensor:
- platform: version
name: "ESPHome Version"
hide_timestamp: true
wifi:
ap: {}
globals:
- id: selected_index
type: int
restore_value: no
initial_value: '0'
one_wire:
- platform: gpio
pin: GPIO16
i2c:
sda: GPIO23
scl: GPIO22
binary_sensor:
- platform: gpio
pin:
number: GPIO0
mode:
input: true
pullup: true
inverted: true
id: mode_button
on_press:
then:
- select.next: run_mode
light:
- platform: status_led
name: run_led
id: run_led
pin: GPIO15
sensor:
- platform: internal_temperature
name: "Internal Temperature"
id: ic_temp
- platform: dallas_temp
name: "Temperature"
id: outside_temp
select:
- platform: template
name: "mode"
id: run_mode
options:
- "OFF"
- "AUTO"
- "MANUAL"
initial_option: "OFF"
optimistic: true
- platform: template
name: "run_state"
id: run_state
options:
- "READY"
- "RUNNING"
initial_option: "READY"
optimistic: true
on_value:
then:
- if:
condition:
lambda: 'return id(run_state).state == "RUNNING";'
then:
- light.turn_on: run_led
else:
- light.turn_off: run_led
switch:
- platform: gpio
pin: GPIO5
name: "Irrigation Zone 1"
inverted: true
interlock: &interlock_group [zone_1, zone_2, zone_3, zone_4]
id: zone_1
on_turn_on:
then:
- select.set_index:
id: run_state
index: 1
on_turn_off:
then:
- select.set_index:
id: run_state
index: 0
- platform: gpio
pin: GPIO18
name: "Irrigation Zone 2"
inverted: true
interlock: *interlock_group
id: zone_2
on_turn_on:
then:
- select.set_index:
id: run_state
index: 1
on_turn_off:
then:
- select.set_index:
id: run_state
index: 0
- platform: gpio
pin: GPIO19
name: "Irrigation Zone 3"
inverted: true
interlock: *interlock_group
id: zone_3
on_turn_on:
then:
- select.set_index:
id: run_state
index: 1
on_turn_off:
then:
- select.set_index:
id: run_state
index: 0
- platform: gpio
pin: GPIO21
name: "Irrigation Zone 4"
inverted: true
interlock: *interlock_group
id: zone_4
on_turn_on:
then:
- select.set_index:
id: run_state
index: 1
on_turn_off:
then:
- select.set_index:
id: run_state
index: 0
time:
- platform: homeassistant
id: homeassistant_time
font:
- file: "https://github.com/IdreesInc/Monocraft/releases/download/v3.0/Monocraft.ttf"
id: web_font_title
size: 16
- file: "https://github.com/IdreesInc/Monocraft/releases/download/v3.0/Monocraft.ttf"
id: web_font_time
size: 10
- file: "https://github.com/IdreesInc/Monocraft/releases/download/v3.0/Monocraft.ttf"
id: web_font_text
size: 9
display:
- platform: ssd1306_i2c
model: "SSD1306 128x64"
address: 0x3C
lambda: |-
it.printf(0, 0, id(web_font_title), "%s", id(run_state).state.c_str());
it.strftime(it.get_width(), 0, id(web_font_time), TextAlign::TOP_RIGHT, "%H:%M", id(homeassistant_time).now());
it.printf(0, 16, id(web_font_text), "Zne1: %s", id(zone_1).state ? "ON" : "OFF");
it.printf(it.get_width(), 16, id(web_font_text), TextAlign::TOP_RIGHT, "Zne2: %s", id(zone_2).state ? "ON" : "OFF");
it.printf(0, 25, id(web_font_text), "Zne3: %s", id(zone_3).state ? "ON" : "OFF");
it.printf(it.get_width(), 25, id(web_font_text), TextAlign::TOP_RIGHT, "Zne4: %s", id(zone_4).state ? "ON" : "OFF");
it.printf(0, 34, id(web_font_text), "Mode: %s", id(run_mode).state.c_str());
it.printf(0, 53, id(web_font_text), "Out:%.1f°C", id(outside_temp).state);
it.printf(it.get_width(), 52, id(web_font_text), TextAlign::TOP_RIGHT, "IC:%.1f°C", id(ic_temp).state);Upload this config via ESPHome, and you’ll see four switches in Home Assistant — one for each irrigation zone.
Adding Automations
While you can toggle zones manually, automation makes irrigation shine. Examples:
- Time-based schedule: Run Zone 1 for 10 minutes every morning at 6 AM.
- Weather-aware watering: Skip irrigation if rain is forecast.
- Soil-moisture integration: Only water if soil is below a threshold.
Example Home Assistant automation (YAML):
alias: Irrigation Morning Run
trigger:
- platform: time
at: "06:00:00"
action:
- service: switch.turn_on
target:
entity_id: switch.zone_1
- delay: "00:10:00"
- service: switch.turn_off
target:
entity_id: switch.zone_1
- service: switch.turn_on
target:
entity_id: switch.zone_2
- delay: "00:10:00"
- service: switch.turn_off
target:
entity_id: switch.zone_2
# repeat for zones 3 & 4
Benefits of DIY Irrigation Controller
- Flexible – Adjust zones and schedules without proprietary controllers.
- Smart – Integrates with sensors, weather APIs, and voice assistants.
- Affordable – Uses inexpensive ESP hardware and relays.
- Fun – A practical project that improves your home and teaches you electronics.
Conclusion
With ESPHome and a simple 4-channel relay, you can build a smart irrigation controller that rivals commercial products — but with much more flexibility. Once set up, your garden or lawn can be watered automatically, intelligently, and efficiently.
This project is a great example of how home automation can move beyond lights and switches to something tangible, useful, and rewarding.
