Free tech learning for everyone, from basics to pro

IoT ProjectsIoT SecurityIntermediate

Project: a smart plant watering system

In short: This project reads soil moisture with a capacitive probe and runs a small pump when the soil is dry. Decisions are made locally on the ESP32, with strict limits on pump run time so a fault cannot flood the room. It teaches calibration, actuator control and why safety limits belong in the device itself.

What you will build and what you need

You will build a controller that waters one or two pots. It measures soil moisture every ten minutes, runs a pump for a few seconds if the soil is too dry, and publishes the moisture level and pump activity over MQTT. It keeps working even if Wi-Fi is down, because the decision happens on the device.

PartNotes
ESP32 boardUse an ADC1 pin (such as GPIO 34), as ADC2 pins clash with Wi-Fi
Capacitive soil moisture sensorAvoid resistive probes, which corrode quickly
Small 5 V submersible pump and tubingSits in a water reservoir
Logic-level N-channel MOSFET moduleOr a relay module; switches the pump from a GPIO
Flyback diodeAcross the pump motor to absorb voltage spikes
Separate 5 V supplyShares ground with the ESP32; the pump draws more than a GPIO can
Optional float switchDetects an empty reservoir

Design

Watering control loopSoil sensorcapacitiveprobeESP32 ADCaverage,convert %Decidebelowthreshold?MOSFETswitch 5 VpumpReportMQTT status
Figure 1. The controller reads soil moisture, decides locally, runs the pump briefly and reports what it did.

Keep all electronics above and away from the water, and mount the board in a box with cable entry from below so drips cannot run into it. Use only low-voltage parts; never build this with a mains-powered pump unless you are qualified. The GPIO drives the MOSFET gate, the MOSFET switches the pump's negative lead, and the diode sits across the pump terminals.

Build and calibrate

  1. Connect the moisture sensor to 3.3 V, ground and GPIO 34. Print raw readings in dry air and in a glass of water.
  2. Push the probe into dry soil and note the value (DRY), then water thoroughly and note it again (WET). Capacitive probes read higher when drier.
  3. Wire the pump through the MOSFET and test it for one second from the REPL.
  4. Upload the code, choose a threshold suitable for your plant, and watch it for a few days before trusting it.
import time
from machine import ADC, Pin

soil = ADC(Pin(34)); soil.atten(ADC.ATTN_11DB)
pump = Pin(26, Pin.OUT, value=0)       # pump off at boot
DRY, WET = 2600, 1450                  # from your calibration
THRESHOLD = 35                         # percent
RUN_S = 5                              # seconds per watering
MAX_PER_DAY = 6                        # hard safety limit
MIN_GAP_S = 3600                       # wait for water to soak in

runs_today, last_run, day_start = 0, 0, time.time()

def moisture_pct():
    raw = sum(soil.read() for _ in range(16)) // 16
    pct = (DRY - raw) * 100 // (DRY - WET)
    return max(0, min(100, pct))

def water():
    pump.value(1)
    try:
        time.sleep(RUN_S)
    finally:
        pump.value(0)                  # always switch off, even on error

while True:
    now = time.time()
    if now - day_start > 86400:
        runs_today, day_start = 0, now
    m = moisture_pct()
    if m < THRESHOLD and runs_today < MAX_PER_DAY and now - last_run > MIN_GAP_S:
        water()
        runs_today, last_run = runs_today + 1, now
    # publish m and runs_today over MQTT here (see the temperature monitor project)
    time.sleep(600)

Safety and security checklist

  • Fail safe: pump off at boot, off in a finally block, and a hard daily limit in firmware.
  • Remote commands are requests: if you add an MQTT "water now" command, the device must still apply its own limits.
  • Authenticate commands: only your controller account may publish to the command topic; sensors and dashboards are read-only.
  • Detect faults: alert if moisture does not rise after watering (empty reservoir, blocked tube) or if readings jump to 0 or 100 per cent (sensor fault).
  • Electrical safety: low voltage only, drip loops on cables and a fuse on the pump supply.
  • Usual device hygiene: TLS, unique credentials, IoT VLAN, no debug services left on.

Tip: this project shows an important IoT principle in miniature. Any actuator that can cause physical harm must enforce its safety limits locally, so that a network attacker, a software bug or a stuck message cannot drive it beyond safe bounds.

Practice

Why use an ADC1 pin on the ESP32 for the moisture sensor?
ADC2 pins are shared with the Wi-Fi driver and cannot be read reliably while Wi-Fi is active, so ADC1 pins such as GPIO 34 are used.
Why is the pump switched through a MOSFET or relay rather than directly from a GPIO pin?
A GPIO can supply only a few milliamps at 3.3 V, far less than the pump needs. The MOSFET switches the pump's own supply under GPIO control.
What stops an attacker who gains MQTT access from flooding the room?
The device enforces its own run time, minimum gap and daily maximum in firmware, and command topics are restricted to an authorised account.

Key takeaways

  • Capacitive probes last longer than resistive ones; calibrate dry and wet values.
  • Drive the pump through a MOSFET or relay with a flyback diode and separate supply.
  • Make watering decisions locally so the system works without Wi-Fi.
  • Enforce run-time and daily limits in firmware, whatever commands arrive.
  • Keep electronics above the water and use low voltage only.
Tracks your learning on this device only. See your progress on the learning paths.

About the author

Mohamed Fayas

Founder of FM TecHub. CCNA certified, with a BTEC HND in Network Engineering, and BEng (Hons) in Computer Networking and Cloud Security. He writes practical, plain-English guides on networking, security and cloud.

More about the author

Original content written by Mohamed Fayas for FM TecHub. © 2026 FM TecHub. You're welcome to share a link to this page; please don't copy the text elsewhere without permission.

Stay up to date by email

New notes, tools and security news from FM TecHub, explained simply. Free.

We only use your email to send these updates. See our privacy policy.