Why I Automated My Sprinkler System (And You Should Too)
After dealing with brown patches on my lawn for two summers straight, I finally decided to tackle the irrigation problem the only way I know how — with Home Assistant and way too much engineering. What started as “let’s just add a smart timer” turned into a complete DIY irrigation control system that’s saved me hundreds on my water bill and given me the healthiest lawn in the neighborhood.
I’m Wayne, a software engineer at eBay, and I’ve been running Home Assistant for over 2 years now. My smart home setup includes vehicle tracking for my Mercedes E450 and Ford F450, Frigate NVR security with Coral TPU, and enough presence sensors to know when my dog goes outside. But this sprinkler project? This one actually pays for itself.
Here’s what we’re building: a complete smart irrigation system that monitors weather, soil moisture, and even checks if your car is in the driveway before watering (because nobody wants to get soaked walking to their car). By the end of this guide, you’ll have an intelligent watering system that beats any store-bought smart timer.
What You’ll Need for This Project
I tested three different approaches before landing on this setup. Don’t waste time like I did — here’s exactly what works:
Hardware Components
- ESP32 Development Board – The brains of the operation (ESP32 DevKit V1)
- 8-Channel Relay Module – Controls up to 8 zones (SainSmart 8-Channel Relay)
- 24V AC Transformer – Powers the solenoid valves
- Capacitive Soil Moisture Sensors – Way better than the cheap resistive ones (Capacitive Soil Sensors 3-Pack)
- Outdoor Enclosure – Protect your electronics from weather
- Wire and connectors – For linking everything together
Software Requirements
- Home Assistant (obviously)
- ESPHome add-on
- Weather integration (I use OpenWeatherMap)
- Optional: Frigate for monitoring the lawn
Total cost for my 6-zone setup: about $120. Compare that to a Rachio 3 at $230, and you can see why I went DIY. Plus, our version does things the commercial controllers can’t.
Understanding Your Irrigation System
Before you start ripping into your current setup, let’s talk about how sprinkler systems actually work. Most residential systems use 24V AC to control solenoid valves — one wire is common (usually white), and each zone gets its own control wire.
I learned this the hard way when I accidentally shorted the common wire while installing my first relay. Pro tip: turn off the power before working on anything electrical. Your neighbors don’t need to see you dancing around the yard after getting zapped.
Zone Planning
Map out your zones before you start. I’ve got:
- Zone 1-2: Front lawn (split for better coverage)
- Zone 3-4: Back lawn
- Zone 5: Flower beds
- Zone 6: Vegetable garden
Different areas need different watering schedules. My veggie garden gets daily attention, while the lawn only needs water 2-3 times per week. The flower beds? Those drought-resistant plants barely get watered unless it’s been dry for a week.
Building the ESP32 Control Board
Here’s where things get fun. We’re essentially building a smart irrigation controller from scratch that’ll integrate perfectly with Home Assistant.
ESPHome Configuration
First, create a new ESPHome device. Here’s my configuration file — adapt the GPIO pins based on your wiring:
esphome:
name: sprinkler-controller
platform: ESP32
board: esp32dev
wifi:
ssid: "YourWiFiSSID"
password: "YourWiFiPassword"
api:
password: "YourAPIPassword"
ota:
password: "YourOTAPassword"
logger:
# Relay outputs for sprinkler zones
switch:
- platform: gpio
pin: GPIO2
name: "Zone 1 - Front Lawn East"
id: zone1
- platform: gpio
pin: GPIO4
name: "Zone 2 - Front Lawn West"
id: zone2
- platform: gpio
pin: GPIO5
name: "Zone 3 - Back Lawn North"
id: zone3
- platform: gpio
pin: GPIO18
name: "Zone 4 - Back Lawn South"
id: zone4
- platform: gpio
pin: GPIO19
name: "Zone 5 - Flower Beds"
id: zone5
- platform: gpio
pin: GPIO21
name: "Zone 6 - Vegetable Garden"
id: zone6
# Soil moisture sensors
sensor:
- platform: adc
pin: A0
name: "Soil Moisture Zone 1"
unit_of_measurement: "%"
filters:
- calibrate_linear:
- 2.8 -> 0.0
- 1.2 -> 100.0
- lambda: if (x < 0) return 0; else if (x > 100) return 100; else return x;
update_interval: 60s
- platform: adc
pin: A3
name: "Soil Moisture Zone 3"
unit_of_measurement: "%"
filters:
- calibrate_linear:
- 2.8 -> 0.0
- 1.2 -> 100.0
- lambda: if (x < 0) return 0; else if (x > 100) return 100; else return x;
update_interval: 60s
# Master valve (if you have one)
- platform: gpio
pin: GPIO22
name: "Master Valve"
id: master_valve
Wiring the Relay Module
This is where I almost made a costly mistake. The relay module needs to be wired properly to avoid frying your ESP32:
- VCC → 5V (if your relay needs 5V) or 3.3V
- GND → GND
- IN1-IN8 → GPIO pins as defined in your ESPHome config
For the sprinkler side, wire the common terminal of each relay to your zone wires, and connect the other terminal to the 24V AC transformer. The common wire from your sprinkler system goes directly to the transformer — don’t run it through the relays.
Home Assistant Automation Logic
Now comes the magic. We’re not just turning zones on and off — we’re building intelligence into the system.
Weather-Based Watering
First, let’s set up weather tracking. I use OpenWeatherMap, but any weather integration works:
automation:
- alias: "Cancel Watering if Rain Expected"
trigger:
- platform: time
at: "05:00:00"
condition:
- condition: numeric_state
entity_id: weather.openweathermap
attribute: forecast
value_template: "{{ state_attr('weather.openweathermap', 'forecast')[0].precipitation }}"
above: 0.1
action:
- service: input_boolean.turn_off
target:
entity_id:
- input_boolean.water_front_lawn
- input_boolean.water_back_lawn
This checks if rain is expected in the next 24 hours. If so, it skips watering. Simple, but effective.
Soil Moisture-Based Watering
Here’s where the soil moisture sensors really shine. Instead of watering on a schedule regardless of conditions, we water based on actual need:
automation:
- alias: "Water Zone 1 Based on Moisture"
trigger:
- platform: time
at: "06:00:00"
condition:
- condition: numeric_state
entity_id: sensor.soil_moisture_zone_1
below: 30
- condition: state
entity_id: weather.openweathermap
state:
- 'clear-night'
- 'sunny'
- 'partly-cloudy'
action:
- service: switch.turn_on
target:
entity_id: switch.zone_1_front_lawn_east
- delay: "00:15:00"
- service: switch.turn_off
target:
entity_id: switch.zone_1_front_lawn_east
This only waters if moisture is below 30% AND the weather is clear. No more soggy lawns!
Vehicle Presence Detection
Here’s a feature you won’t find on any commercial controller. Since I track both my Mercedes E450 and Ford F450 through Home Assistant, I can avoid watering when either vehicle is in the driveway:
condition:
- condition: state
entity_id: device_tracker.mercedes_e450
state: 'away'
- condition: state
entity_id: device_tracker.fordpass_tracker
state: 'away'
Nobody wants to walk out to a sprinkler-soaked truck. Been there, got the wet socks.
Advanced Features That Make This System Shine
Once you have the basics working, these advanced features really set your system apart:
Zone Sequencing
Running multiple zones simultaneously can drop water pressure. Here’s how to sequence them properly:
script:
water_front_lawn_sequence:
sequence:
- service: switch.turn_on
target:
entity_id: switch.zone_1_front_lawn_east
- delay: "00:15:00"
- service: switch.turn_off
target:
entity_id: switch.zone_1_front_lawn_east
- delay: "00:02:00" # Brief pause between zones
- service: switch.turn_on
target:
entity_id: switch.zone_2_front_lawn_west
- delay: "00:15:00"
- service: switch.turn_off
target:
entity_id: switch.zone_2_front_lawn_west
Seasonal Adjustment
Different times of year need different watering amounts. I adjust watering duration based on temperature and season:
automation:
- alias: "Adjust Watering Duration for Season"
trigger:
- platform: state
entity_id: sensor.outdoor_temperature
action:
- service: input_number.set_value
target:
entity_id: input_number.lawn_watering_minutes
data:
value: >
{% if states('sensor.outdoor_temperature')|float > 85 %}
20
{% elif states('sensor.outdoor_temperature')|float > 75 %}
15
{% else %}
10
{% endif %}
Hot days get longer watering times. In spring (like now), 10-15 minutes is plenty.
Water Usage Monitoring
Want to track how much water you’re using? Add a flow sensor to your main line. I use a YF-S201 Hall Effect Flow Sensor connected to another GPIO pin:
sensor:
- platform: pulse_counter
pin: GPIO15
name: "Water Flow Rate"
unit_of_measurement: "L/min"
filters:
- multiply: 0.1
total:
name: "Total Water Usage"
unit_of_measurement: "L"
Now I can track exactly how much water each zone uses and optimize accordingly.
Dashboard and Notifications
A good dashboard makes managing everything so much easier. Here’s how I set up my irrigation panel in Home Assistant:
Lovelace Card Configuration
type: vertical-stack
cards:
- type: entities
title: Irrigation Control
entities:
- switch.zone_1_front_lawn_east
- switch.zone_2_front_lawn_west
- switch.zone_3_back_lawn_north
- switch.zone_4_back_lawn_south
- switch.zone_5_flower_beds
- switch.zone_6_vegetable_garden
- type: entities
title: Soil Moisture Levels
entities:
- sensor.soil_moisture_zone_1
- sensor.soil_moisture_zone_3
- type: history-graph
title: Watering History
hours_to_show: 168
entities:
- switch.zone_1_front_lawn_east
- switch.zone_3_back_lawn_north
Mobile Notifications
Get notified when watering starts, stops, or if there’s a problem:
automation:
- alias: "Notify Watering Started"
trigger:
- platform: state
entity_id:
- switch.zone_1_front_lawn_east
- switch.zone_2_front_lawn_west
to: 'on'
action:
- service: notify.mobile_app_waynes_phone
data:
message: "🌱 Watering started for {{ trigger.to_state.attributes.friendly_name }}"
- alias: "Notify Low Soil Moisture"
trigger:
- platform: numeric_state
entity_id:
- sensor.soil_moisture_zone_1
- sensor.soil_moisture_zone_3
below: 20
action:
- service: notify.mobile_app_waynes_phone
data:
message: "⚠️ Low soil moisture detected in {{ trigger.to_state.attributes.friendly_name }}"
Troubleshooting Common Issues
After running this system for 8 months, I’ve hit every possible snag. Here’s how to fix the most common problems:
Relays Not Triggering
If your relays aren’t switching, check your wiring first. I spent two hours debugging what turned out to be a loose connection on GPIO4. Also verify your relay module voltage requirements — some need 5V, others work fine with 3.3V.
Inconsistent Soil Moisture Readings
Cheap resistive sensors corrode quickly. That’s why I switched to capacitive sensors — they last longer and give more accurate readings. If you’re still getting weird readings, check that your sensors aren’t installed too close to metal sprinkler heads.
WiFi Connectivity Issues
ESP32s can be finicky about WiFi. If you’re seeing frequent disconnections, add a static IP configuration to your ESPHome config:
wifi:
ssid: "YourWiFiSSID"
password: "YourWiFiPassword"
manual_ip:
static_ip: 192.168.1.100
gateway: 192.168.1.1
subnet: 255.255.255.0
Zones Running Too Long
Always include safety shutoffs in your automations. I learned this when a automation bug left Zone 2 running for 3 hours. My water bill that month was… educational.
automation:
- alias: "Safety Shutoff for All Zones"
trigger:
- platform: state
entity_id:
- switch.zone_1_front_lawn_east
- switch.zone_2_front_lawn_west
to: 'on'
for: "00:30:00" # Max run time
action:
- service: switch.turn_off
target:
entity_id: "{{ trigger.entity_id }}"
- service: notify.mobile_app_waynes_phone
data:
message: "🚨 Emergency shutoff: {{ trigger.to_state.attributes.friendly_name }} ran too long"
Results: What This System Actually Delivers
Let’s talk numbers. After running this for most of 2025 and into 2026:
- Water savings: 35% reduction in usage compared to my old timer-based system
- Lawn health: Zero brown patches, most even growth I’ve ever seen
- Cost savings: $240 saved on water bills in the first 8 months
- Maintenance: Practically zero — ESPHome is rock solid
The soil moisture sensors make the biggest difference. Instead of watering every Tuesday/Thursday/Saturday like my old timer, we now water when plants actually need it. During rainy weeks in spring, the system might skip watering for 5-6 days. During hot July stretches, it waters daily.
The integration with my vehicle tracking has saved me from getting soaked more times than I can count. When I’m working from the garage on my F450, the system knows to wait until I’m done before watering nearby zones.
Expanding the System
Once you’ve got the basics working, there are tons of ways to expand:
Drip Line Monitoring
Add individual pressure sensors to detect clogged emitters or broken lines:
sensor:
- platform: adc
pin: A6
name: "Zone 5 Pressure"
unit_of_measurement: "psi"
Fertilizer Injection
With additional pumps and sensors, you can automate liquid fertilizer application. I haven’t implemented this yet, but it’s on my 2026 project list.
Integration with Weather Stations
If you have a Tempest Weather Station (like I do), you can use hyperlocal weather data instead of regional forecasts. This gives you more accurate rainfall and evapotranspiration data.
Maintenance and Long-Term Operation
This system is remarkably low-maintenance, but there are a few things to check seasonally:
Spring Startup
- Test all zones manually
- Check soil sensor calibration
- Clean any debris from sensors
- Update seasonal schedules
Summer Monitoring
- Adjust watering durations for heat
- Monitor water usage trends
- Check for any connectivity issues
Fall Shutdown (if needed)
- Gradually reduce watering schedules
- Blow out lines if you live in a freeze zone
- Update automations for dormant season
The ESP32 board and relays have run continuously through a Colorado winter with no issues. The outdoor enclosure keeps everything dry, and the system automatically handles any brief WiFi outages.
Cost Breakdown and ROI
Let’s be real about the investment:
Initial Build Cost:
- ESP32 board: $15
- 8-channel relay module: $25
- Soil moisture sensors (3): $30
- 24V transformer: $20
- Outdoor enclosure: $15
- Wire and misc: $15
- Total: $120
Comparable Commercial Solution:
- Rachio 3 (8-zone): $230
- Soil moisture sensors (if available): $150
- Total: $380
And here’s the kicker — our DIY version does things Rachio can’t, like vehicle presence detection and deep integration with your existing smart home automations.
Final Thoughts: Why This Project Matters
Look, I could’ve bought a Rachio and called it a day. But where’s the fun in that? This project gave me exactly the integration I wanted with my existing Home Assistant setup, vehicle tracking, weather station, and security system.
More importantly, it actually works better than commercial alternatives. The combination of real soil moisture monitoring, weather integration, and smart scheduling has given me the healthiest lawn I’ve ever had while cutting my water bill significantly.
If you’re already running Home Assistant and have any interest in lawn care or gardening, this is one of those projects that pays for itself quickly and just keeps delivering value. My neighbors constantly ask how my lawn stays so green while theirs goes brown during dry spells.
The answer? Smart automation that actually understands what plants need, not just what the calendar says.
What’s Next?
I’m planning to add frost protection sensors for 2026’s growing season and integrate with my Frigate camera system to monitor plant health visually. But honestly, the current system handles 95% of what I need automatically.
Want to see more smart home automation projects? Check out my energy monitoring setup or learn how I automated my garage door with ESPHome.
And if you found this helpful, subscribe to my newsletter for more engineering-focused smart home content. No marketing fluff — just real projects that actually work.