Tutorial – Using Capacitive Soil Moisture Sensors on the Raspberry Pi

Tutorial – Using Capacitive Soil Moisture Sensors on the Raspberry Pi

This is a tutorial showing how to use capacitive soil moisture sensors on the Raspberry Pi.


Corrosion on Resistive Soil Moisture Sensor

When we designed our first Raspberry Pi Gardening System (Smart Plant Pi), we used resistive moisture sensors.   During development we found that if you leave the resistive sensors with current applied in wet soil, we would see electroplating activity which would strip one electrode in the matter of a month.   Pretty short life.   We knew we had to solve this problem.


Grove Power Save Switch
Grove Power Save Switch

So, we knew if we powered off the sensor during the time we were not reading this, we could improve the reliability.  We did this by adding a Grove Power Save switch between the moisture sensor and the Raspberry Pi.   A Grove Power Save Switch works by using an additional Digital Grove (GPIO line) to switch the power on and off.  We use these in our solar powered designs to reduce power.   By putting a 1 into the control plug, you actually turn off the power (VDD) to whatever device is connected to the output of the Grove Power Save switch.

By switching the Grove Power Save switch on for just 100msec before using the Analog to Digital

High Reliability Resistive Moisture Sensor

Converter to read the voltage (which is proportional to the amount of water in the soil) and then turning it off 100msec after the sample, we reduced the amount of time power was applied to the resistive sensor to 1/300th of the time.   This dramatically (and we mean dramatically) improved the long term reliability of the resistive sensors.  This led to the development of our High Reliability Grove Plant Moisture Sensor which we then successfully shipped with the product, Smart Plant Pi.

Enter The Capacitive Moisture Sensor

The Smart Garden System (or SGS for short) is an introductory, easy to build Raspberry Pi based environmental monitoring and plant watering system using advanced sensors to monitor the soil moisture, monitor the sunlight, watch the air quality and monitor temperature and humidity.

As we started to design this new Raspberry Pi Gardening Kit, one thing struck us quickly.   Since SGS will support up to 9 plants (with the SGS Extender Kit), we knew we had to look for a less expensive solution to the moisture sensor problem.   While the high reliability moisture sensors would work, it used a whole bunch of GPIO (General Purpose Input Output) pins which are in short supply on the Raspberry Pi.    We then investigated other inexpensive ways of doing moisture sensing and found a capacitive moisture sensor.  It wasn’t as accurate as the resistive sensor, but it was significantly less expensive than the high reliability sensor and doesn’t use any GPIO ports.   Since you are not exposing the electrodes to the soil moisture, corrosion is not a problem.  We had found our new part.

How Does a Capacitive Moisture Sensor Work?

Simply stated, a capacitor stores electrical charge.

The electrical component known as a capacitor consist of three pieces.  A positive plate, a negative plate and the space in-between the plates, known as the dielectric.  The physical form and construction of practical capacitors vary widely and many capacitor types are in common use. Most capacitors contain at least two electrical conductors often in the form of metallic plates or surfaces separated by a dielectric medium.

A capacitive moisture sensor works by measuring the changes in capacitance caused by the changes in the dielectric. It does  not measure moisture directly (pure water does not conduct electricity well),  instead it measures the ions that are dissolved in the moisture  These ions and their concentration can be affected by a number of factors, for example adding fertilizer for instance will decrease the resistance of the soil.  Capacitive measuring basically measures the dielectric that is formed by the soil and the water is the most important factor that affects the dielectric.

Capacitive measuring has some advantages, It not only avoids corrosion of the probe but also gives a better reading of the moisture content of the soil as opposed to using a resistive soil moisture sensor.   Since the contacts (the plus plate and the minus plate of the capacitor) are not exposed to the soil, there is no corrosion of the sensor itself.

The capacitance of the sensor is measured by means of a 555 based circuit that produces a voltage proportional to the capacitor inserted in the soil.   We then measure this voltage by use of an Analog to Digital Converter which produces a number that we can then interpret as soil moisture.

Using the Capacitor Moisture Sensor with an Arduino

Using the capacitor sensor with an Arduino is simple as the Arduino has a built in 10 bit ADC.  Not very accurate, but sufficient for this sensor.


 This example reads Capacitive Soil Moisture Sensor.
 Created 2015-10-21
 By berinie Chen <[email protected]>
 GNU Lesser General Public License.
 See <http://www.gnu.org/licenses/> for details.
 All above must be included in any redistribution

const int AirValue = 520;   
const int WaterValue = 260;  
int intervals = (AirValue - WaterValue)/3;   
int soilMoistureValue = 0;
void setup() {
  Serial.begin(9600); // open serial port, set the baud rate to 9600 bps
void loop() {
soilMoistureValue = analogRead(A0);  //put Sensor insert into soil
if(soilMoistureValue > WaterValue && soilMoistureValue < (WaterValue + intervals)) { Serial.println("Very Wet"); } else if(soilMoistureValue > (WaterValue + intervals) && soilMoistureValue < (AirValue - intervals))
else if(soilMoistureValue < AirValue && soilMoistureValue > (AirValue - intervals))

The final output value is affected by probe insertion depth and how tight the soil packed around it is. Value_1 is the value for dry soil and Value_2 is the value for saturated soil.
For example: Value_1 = 520; Value_2 = 260.
The range will be divided into three sections: dry, wet, water. Their related values are:

  • Dry: (520 430]
  • Wet: (430 350]
  • Water: (350 260]

Assuming linearity, you can convert these values to a “percent” of water.  Just remember, in reality, Dry is not 0% moisture and “Water” may not be 100% moisture, at least at the lower values.  Still, it is a useful measurement.

Using the Capacitor Moisture Sensor with a Raspberry Pi

For this test we are using the following components:

Raspberry Pi 3B+

Pi2Grover Pi Hat (converts Pi to Grove Connectors)

Grove 4 Channel 16 bit ADC

Grove Capacitor Soil Moisture Sensor

We are using the https://github.com/switchdoclabs/SDL_Pi_Grove4Ch16BitADC library.   The test program included in the library is sufficient.

If you want a pre-programmed SD Card with all of this software installed and tested, you can find it here.

Hook up

  1. Plug the Pi2Grover board on the GPIO pins on the Raspberry Pi (Be careful not to bend or miss some pins!)
  2. Connect the Grove cable between the I2C port on the 4 Channel ADC to one of the I2C ports on the Pi2Grover board.
  3. Connect the Grove cable from the Capacitive Soil Moisture Sensor to the Grove Connector marked “A0” on the 4 Channel ADC

That’s it for hardware setup.

Capacitive Soil Moisture Sensor


Make sure you have installed I2C support on your Pi.   Type “i2cdetect -y 1” and you should see this

Now install the ADC software.

git clone https://github.com/switchdoclabs/SDL_Pi_Grove4Ch16BitADC.git

Next, cd SDL_Pi_Grove4Ch16BitADC

Now start the program with your sensor in free air:

[email protected]:~/SDL_Pi_Grove4Ch16BitADC $ sudo python TestGrove4Ch16BitADC.py
Channel 0 =2.849625V raw=0x590B dec=22795
Channel 1 =0.567000V raw=0x11E8 dec=4584
Channel 2 =0.561500V raw=0x11D0 dec=4560
Channel 3 =0.561500V raw=0x11C0 dec=4544
Channel 0 =2.849625V raw=0x590B dec=22795
Channel 1 =0.566500V raw=0x11F0 dec=4592
Channel 2 =0.561000V raw=0x11CD dec=4557
Channel 3 =0.560625V raw=0x11BB dec=4539

The value of interest right now is Channel 0 (the decimal value) 22795.    This represents “Dry”.

Capacitive Soil Moisture SensorPutting the sensor in a glass of water (keep the electronics out of the water!!!!!) yields the following:

[email protected]:~/SDL_Pi_Grove4Ch16BitADC $ sudo python TestGrove4Ch16BitADC.py
Channel 0 =1.694875V raw=0x34EE dec=13550
Channel 1 =0.564750V raw=0x11E9 dec=4585
Channel 2 =0.560375V raw=0x11C7 dec=4551
Channel 3 =0.561250V raw=0x11BB dec=4539
Channel 0 =1.600250V raw=0x31FB dec=12795
Channel 1 =0.564875V raw=0x11E8 dec=4584
Channel 2 =0.560250V raw=0x11CC dec=4556
Channel 3 =0.560750V raw=0x11BA dec=4538
Channel 0 =1.542625V raw=0x3031 dec=12337
Channel 1 =0.563875V raw=0x11E2 dec=4578
Channel 2 =0.559500V raw=0x11C1 dec=4545
Channel 3 =0.559500V raw=0x11AD dec=4525

Now we have the dry and the wet values.   Next, we put it in a moist pot.


[email protected]:~/SDL_Pi_Grove4Ch16BitADC $ sudo python TestGrove4Ch16BitADC.py
Channel 0 =1.855625V raw=0x39FC dec=14844
Channel 1 =0.564875V raw=0x11E7 dec=4583
Channel 2 =0.560625V raw=0x11CA dec=4554
Channel 3 =0.561375V raw=0x11BA dec=4538
Channel 0 =1.857000V raw=0x3A08 dec=14856
Channel 1 =0.564625V raw=0x11E5 dec=4581
Channel 2 =0.560625V raw=0x11CC dec=4556
Channel 3 =0.560125V raw=0x11B5 dec=4533
Channel 0 =1.858375V raw=0x3A12 dec=14866
Channel 1 =0.564250V raw=0x11E3 dec=4579
Channel 2 =0.560000V raw=0x11C4 dec=4548
Channel 3 =0.559500V raw=0x11B2 dec=4530

We can see now that the “moist” value is about 14866.   Our Capacitive soil sensor works!

What do the Values really mean?

As mentioned before, a simple conversion to a “percent” moisture assumes linearity, so the following software is not a valid, calibrated scientific measurement.   It’s hard to do in general as we need to have a calibrated moisture source to compare it agains and then take multiple samples to curve fit the data to in order to produce a valid equation.   But it gets worse as the moisture measurement will also be affected by the density of the soil, the amount of fertilizer in the soil, temperature and other factors.   Keep this in mind!  But we still get some useful data out the linear equation.

Following is the Python code we use for generating % moisture from the value from the Capacitive Soil Moisture Sensor measurement in the Smart Garden System.

First we read the value from the Capacitance sensor (Note:  We scale 16 bits down to 10 bits to maintain compatibility with Resistive Sensors – The Smart Garden System also supports Resistive Sensors).

       		Moisture_Raw   = ads1115.readRaw(config.moistureADPin, gain, sps) # Scale to 10 bits
                if (Moisture_Raw > 0x7FFF):
                    Moisture_Raw = 0 # Zero out negative Values
                Moisture_Raw = Moisture_Raw / 64 # scale to 10 bits


# scale for capacitance sensor 1
def scaleMoistureCapacitance1(Moisture_Raw, PlantNumber):
    # do the varying scale of the moisture for Capacitance readers 
    # do the varying scale of the moisture
    # based on 10 bit values
    # > #0 100%
    #  = #1 0%
    # scale to 0% from there
    if (Moisture_Raw < config.Capacitor1SensorCalibration[PlantNumber][1]):
          Moisture_Humidity = 100
          Moisture_Humidity = ((config.Capacitor1SensorCalibration[PlantNumber][0] - Moisture_Raw)*100.0)/(config.Capacitor1SensorCalibration[PlantNu
mber][0] - config.Capacitor1SensorCalibration[PlantNumber][1])

    if (Moisture_Humidity < 0):
        Moisture_Humidity = 0.0

    return Moisture_Humidity

In the Smart Garden System, we are using the coefficients 363 for Dry and 150 for Wet.  Note that the voltage goes down for wetter environments using the capacitive sensor while the resistive sensor gives a higher voltage for wet than dry.


Final Comment about Resistive versus Capacitive Soil Moisture Sensors

During the development of the Smart Garden System we spent a lot of time working with the sensors and developing decent (but nowhere near perfect or calibrated) values to determine when to water plants.   We used up to 9 sensors at a time and to test things we would plug all of them into a single pot to measure the moisture.   When doing this with our resistive sensors, we found all sorts of weird and bad data.  Things weren’t working any way we thought they would.  Then we realized what was going on.  When you plug more than one resistive sensor in the same pot, there are multiple ways for the current to go from one sensor ground and another.  So the values change when you plug more resistive sensors in the same pot.  A lesson to be learned.

Plugging multiple Capacitor sensors, as long as they weren’t too close, produced the expected values.

What is a Grove Connector?

The way we have been wiring I2C connections before just didn’t work for building fast and quick IOT projects.  Then we found Grove.

There are hundreds of Grove Devices from multiple manufacturers around the world.     Just  a quick look finds over 100 boards.

You can’t plug it in backwards.   If you put the connector in the wrong plug it just doesn’t work.  No smoke.  No fire. This makes us happy as we look over into our Box Of Death, filled with boards we have ruined.

We quickly found the Grove connectors and their respective cables very useful. With the large selection of Grove I2C devices available, we decided to include a Grove connector on all our future boards and products.

For more information, check out our full Grove Tutorial here.