In short: A resistive or capacitive soil moisture probe outputs an analog voltage that Arduino's 10-bit ADC reads as a 0–1023 number; you calibrate the dry and wet extremes, map the reading to a percentage, and trigger a relay-driven pump once moisture crosses your threshold.
Automatic plant watering is the "hello world" of practical embedded sensing, yet a surprising number of builds fail in the field within weeks. The reason is almost never the code — it is a misunderstanding of what the sensor actually measures and how its signal degrades over time. This guide walks through the full signal chain, from the physics of soil conductivity to a production-minded Arduino sketch, with the real numbers you need to calibrate correctly.
How a soil moisture sensor actually works
Two sensor families dominate hobby and light-industrial use. Resistive probes pass a small current between two exposed electrodes; wetter soil has more free ions, so resistance drops and the measured voltage rises. They are cheap (under a dollar) but the electrodes corrode through electrolysis — continuously biased, a resistive probe can lose usable accuracy in 2–4 weeks of damp operation. Capacitive probes measure the dielectric constant of soil between two PCB traces coated in solder mask; water has a dielectric of roughly 80 versus about 4 for dry soil, so capacitance tracks moisture without any exposed metal. Capacitive sensors cost a few dollars more but survive months to years, which is why they are the correct default for any deployment you will not babysit.
Key fact: Both sensor types output an analog voltage, not a moisture figure. The on-board 555-timer or comparator on a typical module converts an oscillation or divider into a steady DC level that you read on an analog pin.
Reading the analog value on Arduino
An Arduino Uno (ATmega328P) has a 10-bit successive-approximation ADC: it quantizes the input between 0 V and the reference (5 V by default) into 1024 steps. That gives a resolution of 5 V / 1024 ≈ 4.88 mV per count. A dry capacitive probe might read around 620 counts (~3.0 V) and a fully saturated one around 310 counts (~1.5 V) — note that on many capacitive modules the relationship is inverted: wetter soil yields a lower count. Never assume direction; measure it.
const int SENSOR_PIN = A0;
int dryValue = 620; // calibrate in dry air/soil
int wetValue = 310; // calibrate in water
void setup() { Serial.begin(9600); }
void loop() {
long sum = 0;
for (int i = 0; i < 16; i++) { sum += analogRead(SENSOR_PIN); delay(5); }
int raw = sum / 16; // average 16 samples
int pct = map(raw, dryValue, wetValue, 0, 100);
pct = constrain(pct, 0, 100);
Serial.print("Moisture: "); Serial.print(pct); Serial.println("%");
delay(2000);
}
The 16-sample average matters. A single analogRead() near a switching pump or a long sensor lead can jitter by ±10 counts from mains hum and ADC noise. Averaging in software is the cheapest low-pass filter you own.
Calibration: the step everyone skips
Factory "0–1023" ranges are meaningless for your specific soil, probe, and supply voltage. Calibrate with two anchors: hold the probe in dry air (or oven-dried soil) and record the count; submerge it to the marked line in water and record again. Those become dryValue and wetValue in the sketch. Repeat after any supply-voltage change, because the ADC reference tracks VCC unless you switch to the internal 1.1 V reference with analogReference(INTERNAL).
| Condition | Typical raw count (capacitive) | Approx. voltage |
|---|---|---|
| Dry air | 610–640 | ~3.0 V |
| Dry soil | 560–600 | ~2.8 V |
| Moist soil | 400–480 | ~2.2 V |
| Saturated / water | 290–330 | ~1.5 V |
Key fact: To kill resistive-probe corrosion, power the sensor from a GPIO pin instead of 5 V rail — digitalWrite(PWR,HIGH), wait 10 ms to settle, read, then digitalWrite(PWR,LOW). Duty-cycling the excitation extends electrode life from weeks to months.
Driving the pump safely
A small 5 V submersible pump can draw 200–500 mA at stall — well beyond the 40 mA an Arduino pin can source. Switch it through a relay module or a logic-level MOSFET, and always place a flyback diode across an inductive load. Add hysteresis: start watering below 30% and stop above 55%, rather than toggling at a single threshold, or the pump will chatter every loop as the reading dithers around the setpoint.
Scaling beyond the Uno
The same signal chain scales to serious hardware. The ESP32's 12-bit ADC gives 4096 steps but is notoriously non-linear near the rails, so engineers characterize it with a lookup table — the identical discipline a chip team applies when verifying an on-die ADC macro in Cadence Virtuoso or running mixed-signal regressions in Siemens Questa. If you are curious how analog front-ends are designed and validated at the silicon level, our sister brand Avecas VLSI design services works on exactly these mixed-signal flows. For a structurally similar analog-read walkthrough, see our companion piece on the temperature sensor with Arduino, and for closing the loop cleanly, the guide to driving relays and loads from Arduino.
Want to go from blinking an LED to building instrumented, field-ready embedded systems? Explore the hands-on Embedded Systems track in the CourseTron course catalog and build this exact project with mentor feedback.
Frequently asked questions
Why does my moisture percentage jump around even when the soil is undisturbed?
ADC noise and sensor-lead pickup. Average 8–16 samples per reading, keep the sensor cable short and away from the pump wiring, and add a 100 nF capacitor across the analog pin to ground.
Resistive or capacitive — which should I buy?
Capacitive, for anything left running. Resistive probes corrode because current flows through exposed metal; capacitive probes seal the conductors under solder mask and last far longer.
Can I power the pump directly from the Arduino 5 V pin?
No. Pumps draw hundreds of milliamps and will brown-out or destroy the board. Use a relay or MOSFET with a separate supply and a flyback diode.
Do I need to recalibrate for different soil types?
Yes. Sandy, loamy, and clay soils hold water differently and have different baseline dielectrics, so re-run the two-point dry/wet calibration whenever you change pots or media.