Capacitive soil moisture probe in a potted plant wired to a small enclosure on a windowsill

Beginner

Build a Smart Plant Monitor

SensorsIoTAutomation

Learn how a capacitive soil sensor tells a controller exactly when a plant actually needs water, instead of guessing.

6 real parts included

Total for this kit: 1,474.00 ฿

Doesn't include any order discount you may get at checkout.

What you'll need

Project Goal

This project teaches a controller to make a simple threshold decision based on live analog sensor data: read the soil's moisture level and use it to know when a plant actually needs water, rather than watering on a fixed schedule and guessing. It's a natural first automation project because it introduces analog sensing and threshold logic without any moving parts or wireless complexity.

What the Controller Does

The controller repeatedly reads the soil sensor's analog output, compares that value against a dry/wet threshold you define in code, and acts on or reports the result -- for example, printing a moisture reading or lighting an indicator. The threshold, not the raw voltage, is the meaningful number here: what counts as "dry" varies somewhat by soil type and probe placement, so it's worth calibrating in your own pot rather than trusting a single fixed number copied from an example sketch.

What the Capacitive Soil Moisture Sensor Does

Capacitive sensing measures moisture without a bare metal probe carrying current through the soil, which is what causes resistive soil sensors to corrode after weeks of continuous contact with wet dirt. The capacitive sensor's PCB is coated and instead senses changes in capacitance near its surface, reporting that as an analog voltage that the controller reads on one of its analog-capable pins -- higher or lower depending on how much moisture is near the sensing pads.

Reading an Analog Sensor and Setting a Threshold

Because the sensor communicates as a raw analog voltage rather than a pre-converted digital value, the controller's own analog-to-digital converter is doing the interpretation. In practice this means: read the raw value, note what it reads in genuinely dry soil and again in freshly watered soil, and set your threshold somewhere between those two extremes rather than guessing at a number from a different sensor batch or a different pot's soil composition.

Why This Project Needs an Enclosure

The moisture probe itself is designed to be pushed into soil and get wet -- that's normal and expected. What isn't fine is splash, condensation, or a watering-can drip reaching the controller board, the breadboard connections, or the USB power wiring nearby. An enclosure for this build exists specifically to keep the electronics dry and physically separated from the wet soil environment the probe has to sit in, even though the probe cable itself is the one part that's allowed to get dirty.

Software and Library Concepts

The sensor will have working example code available for common controller platforms -- start from that, confirm you're getting sane raw readings on their own, and only then add your threshold logic and any output (serial print, LED, or later a relay). Keep your dry/wet threshold as a named constant near the top of your code rather than a bare number buried in an if-statement, so recalibrating it later is a one-line change.

Testing and Troubleshooting

  • No reading at all -- check that the sensor is wired to power and ground correctly and confirm your code is reading the correct analog pin.
  • Reading never changes no matter what you do -- confirm the probe is actually inserted into the soil rather than sitting in open air, and double-check you selected the right analog pin in code, not just any GPIO.
  • Reading is maxed out and stays there constantly -- this usually means the probe is sitting in standing water rather than soil; it's worth adding a simple sanity check in code that flags an implausibly saturated reading instead of reporting it as normal.
  • Reading looks reasonable but never crosses into "wet" after watering -- recheck your calibrated thresholds; soil composition differs enough between pots that a hardcoded threshold copied from someone else's project may not match yours.

Optional Future Upgrade: Automated Watering

Once the threshold logic is proven reliable, that same on/off decision can drive a small water pump through a relay or MOSFET module instead of just reporting the moisture level -- see the Digital Thermostat Demo project for an example of that identical on/off threshold control concept applied to a completely different measurement.

Wiring

  • Soil moisture sensor module VCC → ESP32-C3 3V3
  • Soil moisture sensor module GND → ESP32-C3 GND
  • Soil moisture sensor module AOUT → ESP32-C3 GPIO0 — ADC-capable analog input pin, read with `analogRead()`
  • ESP32-C3 onboard LED pin → used directly in code (no wiring needed) — see note below
  • ESP32-C3 SuperMini → USB-C cable → computer/power bank (power + programming)
  • Enclosure: mount the sensor probe so the capacitive pad sits in the soil while the ESP32-C3 board and connector stay above soil level, protected from moisture

The onboard LED pin varies between SuperMini board revisions/vendors — the code below defaults to GPIO8 (a commonly reported location on these boards) behind a `#define`; confirm against your specific board's silkscreen/schematic and change it if the LED doesn't respond. Capacitive soil sensors read LOWER analog values when the soil is WETTER and higher when dry, so the dry-alert threshold logic is inverted from what feels intuitive — this is called out explicitly in the code. Let the sensor calibrate for a minute after first power-up and take a baseline reading in both fully dry and freshly watered soil to tune `DRY_THRESHOLD` for your specific plant/pot.

Wiring Diagram

VCC → 3V3 GND AOUT → GPIO0 ESP32-C3 Soil moisture sensor modu… used directly in code USB-C cable

Starter Code

// Smart Plant Monitor — ESP32-C3 SuperMini + capacitive soil moisture sensor
// No display in this build: readings go to Serial, with an onboard-LED low-moisture warning.

// --- Pins — adjust to match your board's silkscreen if different ---
#define SOIL_PIN 0          // ADC-capable GPIO
#define ONBOARD_LED_PIN 8   // many ESP32-C3 SuperMini boards use GPIO8 for the onboard LED —
                             // verify against your board; if it's wrong, the LED simply won't light

// Capacitive soil sensors read LOWER when WET, HIGHER when DRY (inverse relationship).
// Calibrate these two values for your specific sensor/soil before trusting the percentage.
const int WET_RAW = 1200;   // raw analogRead() value in fully wet soil (example — recalibrate)
const int DRY_RAW = 2800;   // raw analogRead() value in fully dry soil (example — recalibrate)
const int DRY_ALERT_RAW = 2400; // above this raw value, warn that soil is too dry

void setup() {
  Serial.begin(115200);
  pinMode(ONBOARD_LED_PIN, OUTPUT);
  digitalWrite(ONBOARD_LED_PIN, LOW);
}

void loop() {
  int raw = analogRead(SOIL_PIN);

  // Convert to an intuitive 0-100% moisture value (higher = wetter)
  int moisturePercent = map(raw, DRY_RAW, WET_RAW, 0, 100);
  moisturePercent = constrain(moisturePercent, 0, 100);

  bool tooDry = (raw >= DRY_ALERT_RAW);
  digitalWrite(ONBOARD_LED_PIN, tooDry ? HIGH : LOW);

  Serial.print("Raw: ");
  Serial.print(raw);
  Serial.print("  Moisture: ");
  Serial.print(moisturePercent);
  Serial.print("%  ");
  Serial.println(tooDry ? "-> LOW MOISTURE, WATER ME" : "-> OK");

  delay(2000);
}

Not sure about a step? Ask us