← SHEET 02 · ASSEMBLIES EL-006

Deep-Sleep Plant Waterer

ELEMBEDDED
LIVE DRAWING — HOVER OR DRAG TO CRANK · BUILT FROM THE REAL PLANT PARAMETERS
PART NOEL-006
MATL / SYSTEMESP32 · CAPACITIVE PROBE · 5V PUMP
TOOLSArduino IDE · Wokwi · C++

A battery-operated plant waterer built around an ESP32’s deep-sleep timer wake rather than a continuously-running loop: every 30 minutes the chip wakes, averages 16 ADC samples from a capacitive soil probe, decides whether to water using a hysteresis band, and — if it does — enforces an 8-second hard-cap on pump runtime and checks on the next wake whether the moisture reading actually dropped, locking the pump out after three straight failures to water (empty reservoir, kinked tube, dead pump). The one number that makes or breaks a project like this is the battery budget, so it’s worked from the firmware’s own duty cycle rather than quoted from a spec sheet: the arithmetic below, with every current figure labeled either datasheet-typical or an explicit design assumption, projects roughly 5.6 years on a single 18650 before Li-ion self-discharge — not the circuit — becomes the limiting factor.

OVERVIEW & MOTIVATION

Most “smart” plant waterers either poll continuously (killing battery life) or water on a blind timer with no feedback (killing plants when the reservoir runs dry). This design treats watering as a closed decision with two independent safety nets — a hard runtime cap that doesn’t care what the sensor says, and a moisture-feedback check that catches the case the runtime cap can’t: the pump ran for its full allotted time and the soil still didn’t get wetter. Both live in RTC memory so they survive every deep-sleep cycle without touching flash. The design brief was explicit about not padding numbers from a datasheet, so the battery-life section works forward from the firmware’s actual measured-by-design timing (wake interval, awake-time budget, sampling count) rather than backward from a marketing “years of battery life” claim.

COMPONENTS & BOM

REFCOMPONENTSPECROLE
U1ESP32 DevKitC-V4ESP32-WROOM-32, deep-sleep ≈10 µA typcontroller — RTC timer wake, ADC read, pump logic
PR1Capacitive soil-moisture probev1.2-class board, analog out ~0–3 Vmoisture sensing; no exposed metal in soil, so no electrolytic corrosion
K1Relay module or logic-level MOSFETopto relay board, or e.g. IRLZ44N + gate resistorswitches the 5V pump from GPIO27
P15V DC mini pumpdiaphragm/submersible, ~400 mA typdelivers water to the plant
BT118650 Li-ion cell3.7 V nominal, ~2600 mAh typbattery power source
U2Low-Iq LDO/buck regulatore.g. MCP1700 / ME6211-class, ~1–3 µA Iq3V3 logic rail — must be low-quiescent, see power budget
U35V boost convertere.g. MT3608 modulepump supply rail stepped up from the single Li-ion cell

WIRING

CAPACITIVE PROBE SIM: POTENTIOMETER

ESP32 DEVKIT-C V4

5V PUMP SIM: LED INDICATOR

MOSFET / RELAY DRIVER SIM: RELAY MODULE

18650 Li-ion + REGULATOR 3V3 LDO · 5V BOOST

VCC SIG GPIO25 (PROBE PWR) GPIO34 (ADC1_CH6) GPIO27 (PUMP) IN PUMP+ (SW 5V) VCC+ 3V3 3V3 OUT 5V OUT 5V IN GND BUS GND GND GND GND
ESP32 PINNETPERIPHERAL PIN
GPIO34 (ADC1_CH6, input-only)MOISTURE_SIGProbe SIG — Wokwi: pot1:SIG
GPIO25PROBE_PWRProbe VCC, switched — Wokwi: pot1:VCC
GPIO27PUMP_CTRLDriver IN — Wokwi: relay1:IN
3V33V3Regulator 3V3 OUT
GNDGNDCommon ground bus

FIRMWARE & POWER BUDGET

State machine. Deep sleep restarts execution at setup() every wake — there is no persistent loop() — so the whole decision lives there, backed by RTC_DATA_ATTR variables that survive sleep (but not a power-on/EN reset): bootCount, pumpLockedOut, dryRunStrikes, wateringCheckPending, preWaterMoistureRaw. Each wake: read the probe (powered only for the ~100 ms sampling window via PROBE_PWR_PIN), resolve any pending watering check from the previous wake, decide whether to water this wake, then re-arm the timer and sleep.

uint16_t readMoistureAveraged() {
  digitalWrite(PROBE_PWR_PIN, HIGH);
  delay(PROBE_SETTLE_MS);
  uint32_t sum = 0;
  for (int i = 0; i < ADC_SAMPLES; i++) { sum += analogRead(MOISTURE_ADC_PIN); delay(5); }
  digitalWrite(PROBE_PWR_PIN, LOW);   // cut probe power right after sampling
  return (uint16_t)(sum / ADC_SAMPLES);
}

Hysteresis. A capacitive probe reads a higher raw ADC count as soil gets drier. MOISTURE_DRY_RAW = 2800 triggers watering; MIN_MOISTURE_DROP = 150 is the fall in raw counts the next wake’s reading must show for the watering event to count as successful — that comparison, not a fixed wet threshold, is what drives the lockout:

int32_t drop = (int32_t)preWaterMoistureRaw - (int32_t)raw;
if (drop >= MIN_MOISTURE_DROP) {
  dryRunStrikes = 0;
} else if (++dryRunStrikes >= MAX_DRY_RUN_STRIKES) {
  pumpLockedOut = true;   // reservoir/tubing/pump suspected empty or failed
}

Safety. runPumpWithSafetyCap() enforces MAX_PUMP_RUNTIME_MS = 8000 unconditionally — it is a millis() timeout with no feedback early-exit, deliberately, since a single-shot wake-sleep node can’t watch the ADC continuously while the pump runs without abandoning the low-power design. Three consecutive failed waterings (MAX_DRY_RUN_STRIKES = 3) latch pumpLockedOut, which only clears on a power-on/EN reset.

Power budget. Every current figure below is either labeled datasheet-typical or an explicit design assumption — none of it is a field measurement, since the unit hasn’t been deployed (see STATUS). The arithmetic is driven entirely by the firmware’s own numbers:

TERMVALUESOURCE
Wake interval T1800 s (30 min)design — WAKE_INTERVAL_SEC
Awake current I_awake80 mAdatasheet-typical, ESP32 active CPU, radio off
Awake time t_awake0.3 sdesign estimate: wake boot + 16-sample ADC average + logic
Sleep current I_sleep10 µAdatasheet-typical, ESP32 deep sleep, timer-only RTC wake
Avg standby current(I_awake·t_awake + I_sleep·(T−t_awake)) / T = 23.3 µAcomputed
Pump current @5V400 mAdatasheet-typical, small 5V diaphragm pump
Watering assumption1 event/day × 4 s (within the 8 s cap)design assumption, not measured
Boost efficiency85%design assumption, MT3608-class converter
Avg pump-duty current29.4 µAcomputed, battery-side via 3.7V→5V boost
Total avg current52.8 µAstandby + pump duty
Battery capacity2600 mAhdatasheet-typical, single 18650 cell
Modeled runtime≈2053 days ≈ 5.6 yr2600 mAh / 52.8 µA
Realistic runtime≈2–3 yrLi-ion self-discharge (~2%/month typical) and any regulator leakage aren’t modeled above and will cap the real figure well below the modeled one

The standby term alone (23.3 µA) already implies the design decision that matters most: an LDO with a few mA of quiescent current (a generic AMS1117, say) would outweigh the entire modeled budget by roughly three orders of magnitude and make the whole calculation moot — which is why the BOM calls out a low-Iq regulator specifically.

SIMULATION

Wokwi simulates deep sleep faithfully (the sim clock advances through esp_deep_sleep_start() and lets you fast-forward through the 30-minute intervals), so the whole state machine — including the multi-wake dry-run check — is exercisable without hardware:

  1. Load sketch.ino + diagram.json into a Wokwi ESP32 project, start the simulation, open the Serial Monitor at 115200 baud.
  2. Moisture probe substitution: a potentiometer (pot1) stands in for the capacitive probe — Wokwi has no capacitive soil-probe part. Its wiper feeds GPIO34 and its VCC is switched from GPIO25, exactly like the real probe. Twist it toward the “dry” end to push the raw ADC reading above MOISTURE_DRY_RAW and trigger a watering cycle on the next wake; twist it back to simulate the soil having absorbed water.
  3. Pump substitution: a wokwi-relay-module (relay1) stands in for the real MOSFET/relay driver, energized from GPIO27 exactly like the real build. A green LED + 220 Ω resistor across the relay’s switched contacts just gives a visible “pump on” indicator — the real load there is a 5V pump, not an LED.
  4. To rehearse the lockout: leave the potentiometer parked “dry” across three watering cycles in a row. The Serial Monitor prints PUMP LOCKED OUT on the third failure, and the relay stops firing until the simulation is reset.

STATUS

Design and Wokwi-simulated only — this has not been built or run on a real plant. The state machine, hysteresis, dry-run lockout, and max-runtime safety all execute correctly in simulation, and the power-budget arithmetic is internally consistent, but the moisture thresholds (MOISTURE_DRY_RAW, MOISTURE_WET_RAW, MIN_MOISTURE_DROP) are design values, not calibrated against a real probe in real soil, and the 80 mA/10 µA current figures are datasheet-typical, not bench-measured on this specific board/regulator combination. Next: bench-calibrate the probe in air/water, select and verify the low-Iq regulator, measure actual awake current on a scope/USB power meter, and re-run the battery-life arithmetic against measured numbers instead of datasheet ones.

USE CASES & APPLICATIONS

The pattern here — read a sensor, make a bounded actuation decision with hardware/firmware safety limits, sleep for the rest of the interval — generalizes past plant watering to any duty-cycled battery IoT node: greenhouse micro-irrigation zones (many nodes, each independent, where a single stuck-pump failure must stay local), remote environmental/soil sensing nodes that only need to report on a slow cadence, and livestock-trough or rain-barrel level control where a pump/valve needs the same max-runtime-plus-feedback safety structure. The specific lesson worth reusing elsewhere: computing the battery budget from the firmware’s actual duty cycle (not a spec-sheet “years of battery life” claim) is what turns a plausible-sounding low-power design into one whose numbers can be checked.

FILES

  • sketch.ino — full firmware: RTC-persisted state machine, averaged ADC read, hysteresis watering decision, hard max-runtime pump safety, dry-run lockout, timer-based deep sleep.
  • diagram.json — Wokwi circuit (ESP32 DevKitC-V4 + potentiometer probe stand-in + relay module pump-driver stand-in + LED pump indicator).
  • README.md — Wokwi simulation walkthrough and real-build notes (capacitive vs. resistive probes, switched probe power, low-Iq regulator choice, pump driver wiring).

Paths: sources/electronics/plant-waterer/sketch.ino, sources/electronics/plant-waterer/diagram.json, sources/electronics/plant-waterer/README.md.

← BACK TO ASSEMBLIES

NAME ODILBEK MARIMOV
DWG NO. PF-2026
SHEET 01 / 07
DISCIPLINE ROBOTICS / MECHATRONICS
SCALE 1:1
REV A
THIRD-ANGLE PROJECTION
DATE 2026-07-11
UNITS mm