Soil Moisture Sensor

written by hek

Have you ever wanted to be notified when your plants need to be watered? Then this is the place for you.

There are several water sensors available and we've tried the soil, rain and water level sensors.

The soil sensors both have digital and analog outputs. The digital trigger level can adjusted by setting the trimpot on the sensor module. We're only going to use the digital output of the sensors in the following example.

Wiring Things Up

Start by connecting the radio module.

Sensor Arduino Comment
GND GND Marked black
VCC VCC (3.3 - 5V) Marked red
DO (digital out) Digital pin 3 Marked green


Last updated by tekka007, 24 Jul 2022, "Upate CI and HW defs (#1530)"
 * The MySensors Arduino library handles the wireless radio link and protocol
 * between your home built sensors/actuators and HA controller of choice.
 * The sensors forms a self healing radio network with optional repeaters. Each
 * repeater and gateway builds a routing tables in EEPROM which keeps track of the
 * network topology allowing messages to be routed to nodes.
 * Created by Henrik Ekblad <[email protected]>
 * Copyright (C) 2013-2019 Sensnology AB
 * Full contributor list:
 * Documentation:
 * Support Forum:
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 * Arduino soil moisture based on gypsum sensor/resistive sensor to avoid electric catalyse in soil
 *  Required to interface the sensor: 2 * 4.7kOhm + 2 * 1N4148
 * Gypsum sensor and calibration:
 *    DIY: See
 *    Built: Davis / Watermark 200SS
 *        cb (centibar)
 *            0-10 Saturated Soil. Occurs for a day or two after irrigation
 *            10-20 Soil is adequately wet (except coarse sands which are drying out at this range)
 *            30-60 Usual range to irrigate or water (except heavy clay soils).
 *            60-100 Usual range to irrigate heavy clay soils
 *            100-200 Soil is becoming dangerously dry for maximum production. Proceed with caution.
 * Connection:
 * D6, D7: alternative powering to avoid sensor degradation
 * A0, A1: alternative resistance measuring
 *  Based on:
 *  "Vinduino" portable soil moisture sensor code V3.00
 *   Date December 31, 2012
 *   Reinier van der Lee and Theodore Kaskalis
 * Contributor: epierre

// Copyright (C) 2015, Reinier van der Lee

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// GNU General Public License for more details.

// Enable debug prints to serial monitor
#define MY_DEBUG

// Enable and select radio type attached
#define MY_RADIO_RF24
//#define MY_RADIO_NRF5_ESB
//#define MY_RADIO_RFM69
//#define MY_RADIO_RFM95

#include <math.h>       // Conversion equation from resistance to %
#include <MySensors.h>

// Setting up format for reading 3 soil sensors
#define NUM_READS (int)10    // Number of sensor reads for filtering
#define CHILD_ID 0

MyMessage msg(CHILD_ID, V_LEVEL);
uint32_t SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)

long buffer[NUM_READS];
int idx;

/// @brief Structure to be used in percentage and resistance values matrix to be filtered (have to be in pairs)
typedef struct {
    int moisture; //!< Moisture
    long resistance; //!< Resistance
} values;

const long knownResistor = 4700;  // Constant value of known resistor in Ohms

int supplyVoltage;                // Measured supply voltage
int sensorVoltage;                // Measured sensor voltage

values valueOf[NUM_READS];        // Calculated moisture percentages and resistances to be sorted and filtered

int i;                            // Simple index variable

void setup()
    // initialize the digital pins as an output.
    // Pin 6,7 is for sensor 1
    // initialize the digital pin as an output.
    // Pin 6 is sense resistor voltage supply 1
    pinMode(6, OUTPUT);

    // initialize the digital pin as an output.
    // Pin 7 is sense resistor voltage supply 2
    pinMode(7, OUTPUT);

void presentation()
    sendSketchInfo("Soil Moisture Sensor Reverse Polarity", "1.0");
    present(CHILD_ID, S_MOISTURE);

void loop()

    Serial.print ("\t");
    Serial.println (average());
    long read1 = average();

    Serial.print ("\t");
    Serial.println (average());
    long read2= average();

    long sensor1 = (read1 + read2)/2;

    Serial.print ("resistance bias =" );
    Serial.println (read1-read2);
    Serial.print ("sensor bias compensated value = ");
    Serial.println (sensor1);
    Serial.println ();

    //send back the values
    // delay until next measurement (msec)

void measure (int phase_b, int phase_a, int analog_input)
    // read sensor, filter, and calculate resistance value
    // Noise filter: median filter

    for (i=0; i<NUM_READS; i++) {

        // Read 1 pair of voltage values
        digitalWrite(phase_a, HIGH);                 // set the voltage supply on
        supplyVoltage = analogRead(analog_input);   // read the supply voltage
        digitalWrite(phase_a, LOW);                  // set the voltage supply off

        digitalWrite(phase_b, HIGH);                 // set the voltage supply on
        sensorVoltage = analogRead(analog_input);   // read the sensor voltage
        digitalWrite(phase_b, LOW);                  // set the voltage supply off

        // Calculate resistance
        // the 0.5 add-term is used to round to the nearest integer
        // Tip: no need to transform 0-1023 voltage value to 0-5 range, due to following fraction
        long resistance = (knownResistor * (supplyVoltage - sensorVoltage ) / sensorVoltage) ;

        Serial.print (resistance);
        Serial.print ("\t");

// Averaging algorithm
void addReading(long resistance)
    buffer[idx] = resistance;
    if (idx >= NUM_READS) {
        idx = 0;

long average()
    long sum = 0;
    for (int cnt = 0; cnt < NUM_READS; cnt++) {
        sum += buffer[cnt];
    return (long)(sum / NUM_READS);

Shopping Guide

Rain Detection Sensor
Detect rain! Yeah!
Unavailable   Buy
undefined   Buy
Soil Moisture Sensor
Stick these into your plant pots to be notified when they need to be watered.
Unavailable   Buy
undefined   Buy
Water Level Sensor
Use it to detect presence of water or the water level.
Unavailable   Buy
undefined   Buy


Sensors & Actuators

Related Content