Waterfall

Greg Abbas

Engineers are known for spending a lot of time to make a complex solution to automate some task that's tedious, but not really that onerous. Just look at xkcd 1025 "Is It Worth The Time", or Wallace (of Wallace & Gromit fame). I'm no exception to this phenomenon, and here's the latest example. The "tedious task" being the job of keeping the waterfall in my backyard full of water:

It has a mechanical autofill that's supposed to do the job, but it doesn't work. I took to filling it with a garden hose, and even in the summer I only had to do it about once a week, but c'mon... wouldn't it be better if I had to do it no times a week because I had a robot to do it for me? Yeah. Of course that would be better.

The Plan

I've gotten the hang of using ESP32 boards as little IoT brains, so I decided to use that approach here. It just needs to control a sprinkler valve, and have enough sensors to know when to turn it on and off. I already have an electrical outlet and a water supply (a 3/4" PVC sprinkler line) near the waterfall, so with a sufficiently weatherproof enclosure, the controller could sit nearby.

A standard sprinkler valve needs 24VAC to open, so I needed a 120VAC-to-24VAC sprinkler transformer. The ESP32 needs a 5V DC supply, so I needed to something that could take 24VAC and provide that, too. A relay could switch the 24VAC for the sprinkler valve.

I decided I needed two sensors. The crucial one is of course something to tell whether the water level in the waterfall is low enough that it needs to be filled. There are several ways to this, as I learned when I made the Christmas Tree water sensor. But I was concerned that the liquid level sensor I used for that project wouldn't be hardy enough to survive outdoors in the waterfall. There are expensive commercial solutions too, but I didn't want to spend a lot of money on this. In the end, I settled on this Stainless Steel Switch Tank Water Level Sensor that uses floats and reed switches.

It doesn't provide an analog measurement of how much water there is, but it does provide two digital measurements: one higher, one lower. That's enough for this application, and hopefully it'll survive the elements for a while. The white bracket on top is the thing that I 3D-printed to hold it in place in the waterfall reservoir tank.

Besides the level sensor, I also wanted a flow sensor so that the controller can check if water is actually coming out when it opens the valve. If the water doesn't flow, something is wrong and it can signal a fault. Here's the flow sensor (on the left), connected to the sprinkler valve (middle) and a pressure regulator on the right.

Here's what they look like installed in the back yard, between the manual shutoff valve (right, red handle) and the 1/4" adapter (left, white & brass).

Electronics

To make things easy on myself, I got a relay breakout board that comes with the necessary components to be driven directly from a GPIO pin, without worrying about the inductive behavior of the relay coil.

I prototyped everything with a lot of wago connectors.

For the ESP32, I used a SparkFun Thing Plus (USB-C) board I had lying around.

Firmware

Now that everything is hooked up (albeit in a tangled mess on my workbench) I needed some firmware on the ESP32 to drive it. As with previous recent projets, I used VS Code + Claude Code to make this part really easy. It connects to my LAN via WiFi, and opens a connection to my local MQTT server (running Mosquitto). It also publishes a web interface on port 80, with lots of useful stuff:

I also implemented over-the-air (OTA) update support, which has been really handy because once the controller is installed in my backyard, unhooking it to bring it back within a cable-distance of my Mac is not convenient. Much better to push bug fixes and enhancements wirelessly.

The control logic is as follows: if "auto" is off, then wait until the user turns the valve on, and then turn it off again after a set period of time. If "auto" is on, then wait until the pump is off, and then wait another "settling" interval of time. If at that point the lower level sensor ever reports "dry", then open the valve. Leave the valve open until the higher level sensor reports "wet", and then close the valve again. The controller knows whether the pump is running by listening for an MQTT message on a particular topic.

There are several faults that can occur, and if one of them does then the controller won't open the valve until the fault is cleared. They are:

I wish I could distribute the source code publicly. But I work for Apple and they're super-uptight about that. But feel free to reach out if you have questions.

Assembly

Once I tested that everything is working as expected, it was time to put it together in a more robust form. I found a 8.7" x 6.7" x 4.3" weather-proof outdoor enclosure that has a clear door, perfect for showing off my creation. I'm a little concerned that it won't be as good at shielding the components from solar UV radiation as an opaque door would be, but the clear door is pretty so I couldn't resist.

The case is made of a plastic that's easy to drill holes in with a step bit, and I put cable glands in the holes so that even where the cables enter the box it's going to be very hard for water to enter. I hope. Time will tell.

Attaching dupont connectors to the header pins on the ESP32 board is not a durable solution, so I decided to use this breadboard.

I put female headers on it to hold the ESP32 board (red rectangle on top), and some 2-pin and 3-pin screw terminals (blue rectangles on bottom). It's very convenient that a lot of the holes are connected by traces, allowing one to solder wires that connect the rows together, like this:

I 3D-printed a little chassis that uses heat-set inserts to screw all the main components to (protoboard, relay, power supply, transformer). The chassis is attached to the plastic "floor" with zip-ties, and the floor is then held to the box with two screws. Here's what the protoboard looks like, installed:

The relay board is in the middle, the power supply is in the upper-left, and the transformer is in the lower-left.

Another view, with the transparent door shut. Notice the white cable glands installed at the bottom — a 1/2" one for the power cable, and three 3/4" ones for the 3-conductor outdoor signal cables. I stuck with the wago connectors to connect everything together.

Here it is installed on the fence behind the waterfall.

Parts List

Questions or comments? Email me at .

2026 Aug 8