Embedded

Soil Moisture Sensor Arduino

By CourseTron Team ·  6 min read ·  Updated Oct 2026 💬 𝕏 in f
Table of Contents
    ? Print / Save as PDF

    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.

    Sense, decide, actuate Soil + probesenses waterAnalog V0–5 VADC + MCU0–1023Relay + Pumpon / off Dielectric or RSteady DC level4.88 mV per countSeparate supply CourseTron · coursetron.com
    The full sense-decide-actuate chain: analog voltage becomes a digital count, then a watering decision.

    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).

    ConditionTypical raw count (capacitive)Approx. voltage
    Dry air610–640~3.0 V
    Dry soil560–600~2.8 V
    Moist soil400–480~2.2 V
    Saturated / water290–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.

    Two-point calibration: raw count to percent dryValue = 620 wetValue = 310 0 % 100 % Dry soil ~580 ~13 % Moist soil ~440 ~58 % pct = map(raw, 620, 310, 0, 100); wetter soil gives a lower count CourseTron · coursetron.com
    Dry and wet anchor counts define the 0 to 100 percent scale; typical table readings fall between them.

    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.

    Pump runs until moisture reaches the high threshold stop above 55% start below 30% Soil moisture PUMP water flow Relay-switched, own supply CourseTron · coursetron.com
    When moisture drops below the low threshold the pump energizes; droplets flow until the high threshold is reached.

    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.

    Advertisement