Skip to content

An AI sprinkler brain that fails back to dumb

irrigation sidecarv0.1 build packagedesigned, not built

Turfy is the design for a weather-informed, camera-and-sensor irrigation controller, but the clever part isn’t the AI. It’s that it only touches the lawn when it’s provably healthy. It rides alongside a 1990s Rain Bird as a fail-safe sidecar: take authority while the watchdog is fed, and hand control straight back the instant anything goes wrong. In hardware. Because a stuck valve is a flooded yard and a very large water bill.

Rain Bird ESP-6Si faceplate with its analog scheduling dialThe brief
Rain Bird ESP-6Si: an analog dial, six stations, an ‘Adjust Water %’ knob. About as simple as irrigation controllers get. Reused, not replaced: Turfy borrows its transformer, its valves, and its job as the always-there fallback brain.

Where it stands

I have a simple sprinkler system at home, and I wanted an AI-driven, weather-informed one without ever making the yard depend on a Raspberry Pi. This page is the design for that. The controller has been opened and mapped, and the first build package is drawn. The board has not been built, and nothing here has ever switched a valve.

PieceWhat it isState
The Rain Bird, opened and mappedFive photographs, three boards, the tap point found.done
v0.1 build packageFour schematic sheets, channel map, pin map, parts list, acceptance test.drawn
The sidecar boardTwo relay boards, the watchdog, the sense bank.not built
The turfy daemonHeartbeat, zone driver, scheduler.not written
Acceptance testFive steps, before a valve is connected.not run
Phases 0 to 3Passive logging through weather and vision.not started

docs/turfy, the v0.1 build package and the teardown notes, 9 July 2026. No hardware exists to measure.

Safe by construction

Rain Bird keeps authority

The 1990s controller stays wired exactly as it is. Turfy is a sidecar on the station outputs. It never replaces the brain; it borrows it.

A hardware dead-man

A 555 missing-pulse watchdog must be fed by the daemon’s own main loop, one pulse every 10 seconds or less. Go quiet for about 24 seconds and the transfer relays physically drop.

Fail back to dumb

Power loss, kernel panic, a crashed or hung daemon: each one reverts to the Rain Bird with zero software involved. A stuck valve floods a yard, so this can’t stick.

The invariant the whole design hangs on

A de-energized transfer bank leaves the Rain Bird wired exactly as it is today. It’s the first line of the acceptance test, proven with a continuity meter before anything is ever powered on. Pull Turfy’s power in the middle of a watering cycle and the system is stock.

The transfer-switch architecture

It’s the classic automatic-transfer-switch pattern applied to sprinklers. An SPDT relay per zone: Rain Bird output on NC, Turfy output on NO, valve wire on the common pole. One authority line pulls the whole bank. Unpowered, crashed, or watchdog-tripped, the relays drop and the Rain Bird is back in control.

fallback, on NCRain Bird ESP-6Sistation outputs, as wired today
smart path, on NOPi → MCP23017 → zone bankits relays switch the same 24VAC leg
transfer bank8× SPDT relayone authority line picks NC or NO
field wires, on the relay COM polesValves 1 to 6 + MVthe valve return stays on the Rain Bird’s COM terminal
authority picks the bank, active low555 watchdog∧Pi GPIO17fed by the heartbeat, from the daemon’s main loop

The valve common stays on the Rain Bird’s COM terminal and is never moved or switched. Turfy’s valve supply is tapped from the Rain Bird’s own 24VAC terminals, behind a 1 A fuse and a 39 V MOV. With one transformer, paralleled outputs are harmless even during relay bounce.

The one rule that must survive every revision: never run a second 24VAC transformer while the NC path to the Rain Bird exists. Out-of-phase secondaries through the transfer relay = circulating current and dead triacs. Turfy steals 24VAC from the Rain Bird’s own terminals so both controllers switch the same hot leg.

The safety core

“The heartbeat must prove application liveness, not kernel liveness.”

So it’s toggled from the daemon’s own main loop, not a background timer. A timer would keep ticking after a crash and defeat the entire point. Never a cron job, never hardware PWM.

Authority = liveness ∧ intent

Two 2N2222s in series pull the transfer bank low. It engages only when the 555 says the daemon is alive and the Pi explicitly asserts yes. Either transistor off → the line floats high → the bank drops → Rain Bird.

authority ⇔ (heartbeat alive) ∧ (Pi says yes)

The watchdog, in numbers

Circuit
NE555 missing-pulse detector
R1
220 kΩ
C1
100 µF, low leakage
Timeout, 1.1 × R × C
about 24 s
Heartbeat, GPIO27
50 ms low pulse, every 10 s or less
Authority, GPIO17
pull-down default, active high
Authority gate, Q1 and Q2
two 2N2222 in series

Sheet 2 and the pin map, build package v0.1. Nominal part values.

Boot sequence: safe at every step

  1. 1Pi boots. AUTHORITY GPIO defaults pull-down → Rain Bird stays in control regardless of any GPIO chatter.
  2. 2MCP23017 powers up all-inputs (POR default) → zone relays held off. Defined state, no init race.
  3. 3turfy.service self-checks (I²C ack, config sane, time synced), starts the heartbeat, then raises AUTHORITY.
  4. 4Watchdog charges within one timeout; the transfer bank engages and Turfy is driving.

Every way it can fail

Seven failure modes. Four end at the Rain Bird with no software in the path. One is harmless by construction. One depends on the daemon noticing. And one the watchdog cannot see at all, which the build package says in so many words.

The bench is the design run as a state machine: the logic on the four sheets, not telemetry. Boot it, then break it.

Fault benchmodel, not hardwareTurfy unpowered

Valves answer toRain Bird

turfy daemon
Pi unpowered
HEARTBEAT, GPIO27
silent
C1, the watchdog’s capacitor
0.00 V, trips at 3.33 V
555 OUT, into Q1
LOW: Q1 open
AUTHORITY, GPIO17, into Q2
LOW on its pull-down: Q2 open
Relay boards, 5 V
off
Authority bus
floats HIGH
Transfer bank
DROPPED, valve wires on NC
Power
Break one thing, while Turfy drives
  1. restTurfy is unpowered. Every transfer relay rests on NC: the Rain Bird is wired exactly as it was.

Model, computed in your browser from the v0.1 build package: sheet 2 and the failure table. Its clock runs at 4× so the 24 s timeout plays in 6. No hardware is attached, because none is built.

FailureResultClosed by
Pi power loss / kernel panicHeartbeat stops → watchdog drops → Rain Bird.the watchdog
Daemon crash or hangSame: the heartbeat is owned by the daemon loop.the watchdog
Pi reboot GPIO chatterAUTHORITY pull-down + MCP23017 power-on reset = no valve action.boot defaults
Relay 5 V supply diesTransfer coils drop → Rain Bird.the relay coil
Both controllers fire one zoneHarmless: shared transformer, same phase.one transformer
I²C bus wedgeZones frozen. The daemon detects the NAK → drops AUTHORITY.the daemon
Healthy daemon, latched zoneNot caught by the watchdog → hard-capped by a per-zone max-runtime in the driver layer, plus a flow-meter alarm in v0.2.software invariant
7 failure modesbuild package v0.1, section 9

The one hole, a latched zone with a healthy daemon, is a software invariant: hard-cap every zone activation at a maximum runtime in the driver layer itself, not the scheduler. The same layer holds a second interlock: never more than one zone at a time, for the transformer’s VA budget and for water pressure.

The four build sheets

Four sheets carry the build from the 24VAC tap all the way to the Pi’s I²C bus: the valve path, the watchdog and authority gate, the sense front-end, and the zone drive. They are drawn from a parametric source, so when a board photograph changes a fact it is a one-line edit and a re-render rather than a redraw.

Turfy schematic, sheet 1: Power + valve path
Sheet 1Power + valve path. 24VAC tap → fuse + MOV → zone-bank relay → transfer-bank relay → valve solenoid. One channel of seven. Open full size
Turfy schematic, sheet 2: Watchdog + authority
Sheet 2Watchdog + authority. The 555 missing-pulse detector (t ≈ 1.1·R·C ≈ 24 s) feeding the Q1/Q2 series-AND that sinks the transfer bank’s authority bus. Open full size
Turfy schematic, sheet 3: Sense front-end
Sheet 3Sense front-end. One H11AA1 AC-input opto per Rain Bird station output: the passive-logging phase. Typical of seven. Open full size
Turfy schematic, sheet 4: Zone drive
Sheet 4Zone drive. Pi I²C → MCP23017 (0x20) → zone-bank inputs. Power-on leaves every pin hi-Z, so relays stay off. Open full size

Reverse-engineering the box

Before you can sidecar a sealed 1990s controller, you have to map it. Board by board: what’s the tap point, where does 24VAC come from, and is the fallback actually trustworthy?

The opened controller: green logic board over an orange power board, with a soldered-in lithium batteryFully mapped
Inside: a 24VAC transformer, a COB micro, one triac per station, and a hobbyist coin-cell hack that holds the schedule through outages, which is what makes the fallback trustworthy.

What the photographs settled

The tap point. Field wires land on a screw terminal block on the power board, so the sidecar never touches these boards. The Rain Bird already fuses and clamps its own side; Turfy’s fuse and MOV protect the tap independently. The green wire is earth to the chassis: it stays, and Turfy’s logic ground stays unbonded from it.

What they could not

  • The terminal block legend. Whether the master-valve terminal is broken out on the 6Si is not readable here. The eighth triac position suggests the board supports it.
  • The transformer’s VA rating, which sets how many coils the shared supply tolerates during a handover.
  • The battery. It holds the time and the program through an outage, so it is worth metering: if it is dead, the fallback boots into a default program.
  • Triac leakage. With the Rain Bird off, each triac leaks a little through its MOV network into the sense optos. With a 2.2 kΩ series resistor that should read as off. The teardown notes still want it proven, not assumed: scope a SENSE line with the station idle and see a solid high. That would be a sixth step; the acceptance test below has five.
Power board showing station triacs TH1 to TH8, red MOVs, a glass fuse and the field terminal blockThe tap point
Power board (949-26330): eight station triacs TH1 to TH8, per-output MOVs, and a fused 24VAC feed. Field wires land on this screw terminal, so zone wires lift straight off and nothing gets cut.
Logic board, component side: rows of small transistors, resistors, wire jumpers and red NP marks, with the COB daughtercard at one cornerThe drivers
Logic board (049-26062): discrete transistor gate drivers between the micro and the triacs, everything through one board-to-board header. The red NP marks are positions left unpopulated for sibling models.
COB daughtercard with epoxy-blob microcontroller and a station-count solder-jumper legendThe blob
COB daughtercard: the epoxy blob is the micro, and that S1/S2 jumper table is the 4/6/8-station config for the shared module. ‘OPEN:ACTIVE HIGH’ is the jumper-sense legend, not an I/O spec.

Validate each layer

None of the four phases has run. Phase 0 is first for a reason: a couple of weeks of passive logging puts the whole software stack on real signals while the old brain is still driving.

Phase 0 · instrumentation

Passive learn

An H11AA1 opto per station output logs when the Rain Bird actually waters. Validates zone mapping and collects a baseline schedule at zero risk, since Turfy never asserts.

Phase 1 · the sidecar

Take authority

Transfer relays + watchdog go live. Turfy replicates the dumb schedule first, proving the fail-safe handover with a meter before anything smart happens.

Phase 2 · closing the loop

Flow metering

An inline pulse flow meter learns each zone’s baseline GPM. That’s the killer feature: it detects stuck valves, broken heads (flow too high) and clogged lines (flow too low), per zone.

Phase 3 · the AI layer

Weather + vision

ET-based scheduling (Penman-Monteith / Hargreaves) scales runtime to replace the daily deficit, minus rainfall. A cheap camera adds an NDVI-ish turf-stress index on top.

The v0.1 build package

Two stock relay boards, an MCP23017 for a defined power-on state, a 555 watchdog, and an H11AA1 sense bank: everything a Turfy v0.1 board needs, laid out across the four sheets above.

PartRole
2× 8-channel 5 V opto relay board, SPDT, NO and NC exposedtransfer bank, zone bank
1× MCP23017zone drive, defined power-on state
1× NE555 + 2N3906 + 220 kΩ + 100 µF + decouplingwatchdog
2× 2N2222 + 10 kΩauthority AND
7× H11AA1 + 2.2 kΩ 1 W + 10 kΩ + 1 µFsense bank
1× 1 A fuse and holder, 39 V MOV24VAC tap protection
1× 5 V 2 A supplyrelay coils
1× Raspberry Pi, on its own 5 V supplythe daemon
partsplus terminal blocks and a DIN enclosure
SignalNotes
AUTHORITYGPIO 17out. Pull-down default; high requests control.
HEARTBEATGPIO 27out. Idle high; 50 ms low pulse every 10 s or less, from the daemon main loop only.
I²C1GPIO 2, 3bus. MCP23017 at 0x20.
SENSE 1 to 6GPIO 5, 6, 13, 19, 26, 16in. H11AA1 outputs; low means a Rain Bird station is energized.
SENSE MVGPIO 20in. Same, for the master valve.
spareGPIO 21in. Reserved for flow-meter pulses.
pinsBCM numbering

Acceptance test, before a valve is connected

  1. 1Transfer bank unpowered: continuity from every Rain Bird station terminal to its valve terminal, all 8 channels. The Rain Bird path is intact.
  2. 2Power logic only, no 24VAC: boot the Pi and verify every relay stays silent through two full reboots. The GPIO chatter test.
  3. 3Start the daemon; confirm the transfer bank engages only after AUTHORITY is high and the heartbeat is running. Kill -9 the daemon: the bank must drop within about 24 s.
  4. 4Pull the heartbeat wire with the daemon running: same result.
  5. 5Apply 24VAC with a dummy load on channel 1, a 24 V lamp or a spare solenoid: a Rain Bird manual start drives it with authority off, and MCP23017 bit 0 drives it with authority on.

The rest of the hand-built pages are on the projects index.

Anti-cloud. Host local, think global.

Terminal
/terminal