I have been running Home Assistant for more than 6 years. I have always wanted to automate my watering systems, but I have always put off because I needed to fix my rainwater tanks. This year I decided I am finally going to do it. After research I found a few videos that I inspired me and gave me ideas that I put together. See the bottom of the article. Here is a video of working.
I made a design first
. The idea is to use an ESP32 to control servos that will open and close water valves. I am using waterproof 20kg servos (see the link below).
I power the ESP32 with a Mini USB power supply. The ESP32 cannot power the servos directly so I am using a 16 Channel PWM Servo Driver Controller Module I2C PCA9685 12bit to power them. Some people say you can power 1 servo with ESP but I found that not true. My ESP32 crashed every time I tried to run 1 servo directly from it. NOTE: you need to ensure you are supplying the right Ampere for both the ESP32 and PCA9685.
Here is the wiring between the ESP32 board and the PCA9685. It is very simple and it worked from the first time for me. NOTE: the servo’s three wires must match the colours of the terminals on PCA9685.
I used ESPHome Builder in Home Assistant to write the code. It took me a few YouTube videos and a few tweaks to get the code right but it is pretty straightforward.
esphome:
name: esphome-web-54dc14
friendly_name: Smart Garden Controller
min_version: 2025.9.0
name_add_mac_suffix: false
esp32:
variant: esp32
framework:
type: arduino
logger:
api:
ota:
- platform: esphome
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
i2c:
sda: GPIO18
scl: GPIO19
scan: true
id: bus_a
pca9685:
id: pca9685_hub1
i2c_id: bus_a
address: 0x40
frequency: 50
output:
- platform: pca9685
pca9685_id: pca9685_hub1
id: pca_channel_0
channel: 0
- platform: pca9685
pca9685_id: pca9685_hub1
id: pca_channel_1
channel: 12
servo:
- id: servo_front_garden
transition_length: 0s
auto_detach_time: 5s
output: pca_channel_0
min_level: 5% # Optional - Default 3%
idle_level: 7.3% # Optional - Default 7.5%
max_level: 12.5% # Optional - Default 12.5%
- id: servo_back_lawn
transition_length: 0s
auto_detach_time: 5s
output: pca_channel_1
min_level: 2.5% # Optional - Default 3%
idle_level: 7.3% # Optional - Default 7.5%
max_level: 12.5% # Optional - Default 12.5%
cover:
- platform: template
name: "Front Garden Valve"
id: front_garden_valve
device_class: damper
has_position: true
optimistic: true
assumed_state: false
open_action:
- servo.write:
id: servo_front_garden
level: 0.0
- cover.template.publish:
id: front_garden_valve
position: 0.0
close_action:
- servo.write:
id: servo_front_garden
level: 1.0
- cover.template.publish:
id: front_garden_valve
position: 1.0
stop_action:
- servo.detach: servo_front_garden
position_action:
- lambda: |-
float angle = 0.0 + (pos * 90.0);
// Add a small “extra close” offset near fully closed
if (pos < 0.05) {
angle += 20.0; // extra 5 degrees beyond closed
}
id(servo_front_garden).write(angle / 180.0);
- delay: 1s
- servo.detach: servo_front_garden
- platform: template
name: "Back Lawn Valve"
id: back_lawn_valve
device_class: damper
has_position: true
optimistic: true
assumed_state: false
open_action:
- servo.write:
id: servo_back_lawn
level: 0.0
- cover.template.publish:
id: back_lawn_valve
position: 0.0
close_action:
- servo.write:
id: servo_back_lawn
level: 1.0
- cover.template.publish:
id: back_lawn_valve
position: 1.0
stop_action:
- servo.detach: servo_back_lawn
position_action:
- lambda: |-
float angle = 0.0 + (pos * 90.0);
// Add a small “extra close” offset near fully closed
if (pos < 0.05) {
angle += 5.0; // extra 5 degrees beyond closed
}
id(servo_back_lawn).write(angle / 180.0);
- delay: 1s
- servo.detach: servo_back_lawn
I created two covers for the servos that I can control from my HA Dashboard.
Now for the fun part. I was inspired by ericinventor for this. I asked a friend to print some 3D parts to get the servos placed correctly on the water valves.
However, the plastic did not last long
So I modified the design to use the servo metal arms
Once this is working, I got a 4 way water manifold that will connect the pump water supply to the servo valves.
I have installed this where my current water tap is so it is easy to connect to the existing watering systems.
And here is the final working product. I installed an electric junction box to house the ESP32 board and the PCA9685.
I also added an automation to water the Front Garden and the Back Lawn every second day.
alias: Water Front Garden Every Second Day
description: Water front garden every 2 days at 5 AM for 10 minutes
triggers:
- at: "05:00:00"
trigger: time
conditions:
- condition: template
value_template: "{{ (now().timetuple().tm_yday | int) % 2 == 0 }}"
actions:
- target:
entity_id: cover.esphome_web_54dc14_front_garden_valve
action: cover.open_cover
- delay:
hours: 0
minutes: 10
seconds: 0
milliseconds: 0
- target:
entity_id: cover.esphome_web_54dc14_front_garden_valve
action: cover.close_cover
- action: notify.mobile_app_abdul_iphone
data:
message: The front garden has been watered.
title: Front Garden Watered
mode: single
I would like to create better automation that will take the weather forecast and seasons into account. For example if the rain probability is > 50% then do not water the lawn. Or water only twice a week during winter but every second day during summer.
I would love to hear from other people on how they automate their gardens.
Other preparations:
I had 3 rainwater tanks (a total of 13,000L) in my property that were not being used for years and there were not connected to a water pump. I had to do major work to re-install the tanks first as they have slid down the hill in my back yard over the years. I built a platform for them using recycled retaining wall bricks and crusher dust. This took me weeks to do by hand ![]()
Then I installed a new pump and connected the outlet to the manifold with the servo valves.
Credit and links:
https://www.ebay.com.au/itm/226315087078
https://www.ebay.com.au/itm/356380928523
https://www.ebay.com.au/itm/286748676049
https://www.ebay.com.au/itm/371778903333










