Pedro52
Published © GPL3+

Arduino Capacitive Soil Moisture Sensor (DIY) with ESP32

Many publications exist about moisture sensors for applications, e.g. plant watering systems. Making a DIY Sensor is fun and cost-saving.

IntermediateFull instructions provided37,191
Arduino Capacitive Soil Moisture Sensor (DIY) with ESP32

Things used in this project

Hardware components

capacitive Soil Moisture Sensor
DIY, for details see project description
×1
Moisture Level Indicator
DIY, for details see project description and link above
×1
Geekworm NodeMCU-32S ESP32S Lua
×1
Resistor 10k ohm
Resistor 10k ohm
×1
Resistor 1M ohm
Resistor 1M ohm
×1
Resistor 221 ohm
Resistor 221 ohm
220 Ohm
×1
1N4007 – High Voltage, High Current Rated Diode
1N4007 – High Voltage, High Current Rated Diode
×1
Capacitor 100 nF
Capacitor 100 nF
1000 nF / 1 uF
×1
Arduino Mega 2560
Arduino Mega 2560
only if it is possible to control the PWM frequency
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

common workshop tools
Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

Fritzing diagram Soil Moisture Sensor

Breadboard set up for measuring soil moisture with a DIY capacitive sensor

Code

Soil_Moisture_Sensor.ino

Arduino
/*
  This code for a Soil Moisture sensor and a Moist Level Indicator has been developed and produced by Pierre Pennings (December 2018)
  This application can be used e.g. in automatic plant watering systems  
  The DIY Moisture Sensor uses 2 pieces of fondue forks
  The DIY Moist Level Indicator is made with 5 (Neopixel) SMD5050 LEDs with WS2812B controller chips powered with 5 V
  The Moist Level is measured once every second (during 5 seconds) and determines the average of 5 consecutive measurements in 5 different levels
  The Moist Level Indicator is set to the measured soil moisture level
  This sketch is written for using 1 Moisture sensor, but in the final Plantwatering project 3 different sensors will be used
  
  For this Project, an ESP 32 (NodeMCU) is used with 12 Bits ADCs
  The ESP 32 device works at 3.3 Volt levels, while the Moist Level Indicator runs on 5 V
  The 5 Level LEDs have been built in a separate indicator Display (indicating 1%, 25%, 50%, 75% and 100% levels)
  The ESP 32 is fed with 5 V power (from a 5V adaptor or 5v powerbank), it has an on-board 3.3V voltage regulator
  The 5 indicator LEDs get the 5V supply directly from the 5 volt pin of the ESP 32 
    
  This code is licensed under GPL3+ license.
*/

#include <Adafruit_NeoPixel.h>
#define NUM_LEDS  5


///////////////////////////////////////////////// initialise the GPIO pins
const int IndicatorPin = 16;                    // pin 16 sends the control data to the LED Moist Level Indicator
const int ToneOutput1 = 25;                     // pin 25 is used for sending a 600 kHz PWM tone to the MoistSensor1 measurement circuit
const int freq = 600000;
const int Channel1 = 1;
const int resolution = 8;
const int MoistSensor1Pin = 4;                  // 12 bits ADC pin 4 senses the voltage level of the MoistSensor1 (values 0 - 4095)

int level = 0;                                  // Variable of the Moist Level: 1%, 25%, 50%, 75%, 100%
int Moistlevel1 = 0;                            // Variable to store the Moist level for sensor 1 

byte color_scheme[] = {
  0, 0, 0,                  // no color/ off
  0, 200, 0,                // green
  100, 200, 0,              // yellow
  250, 150, 0,              // orange
  0, 0, 200,                // blue
  200, 0, 0                 // red
};

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, IndicatorPin, NEO_RGB + NEO_KHZ800);

/////////////////////////////////////////////////// the setup code that follows, will run once after "Power On" or after a RESET
void setup() {
  Serial.begin(115200);
  ledcSetup(Channel1, freq, resolution);         // configure the PWM functionalitites
  ledcAttachPin(ToneOutput1, Channel1);           // attach the channel 1 to the GPIO pin 25 for generating a PWM signal of 600kHz
  
  pinMode(IndicatorPin, OUTPUT);                // Initializes the output pin for the Moist Level Indicator
  pinMode(MoistSensor1Pin, INPUT);               // Initializes the sensor pin (4) for measuring the MoistureLevelValue1
  
  strip.begin();                                 // Initialize all LEDs to "off"
  
  for (int t = 0; t < 5 ; t++)
    {
    strip.setPixelColor(t, 100, 100, 100);       // After Power On the Moist Level Indicator LEDs are tested once
    strip.show();                                // note that the order of colors of the WS2812 LED strip is R,G,B 
    delay (200);
    strip.setPixelColor(t, 0, 0, 0);             // and back to off
    }
  for (int k = 4; k > -1 ; k--)
    {
    strip.setPixelColor(k, 100, 100, 100);       // blink for 0,2 seconds going top down and then off
    strip.show();
    delay (200);
    strip.setPixelColor(k, 0, 0, 0);             // and back to off
    }
}


/////////////////////////////////////////////////// the loop code that follows, will run repeatedly until "Power Off" or a RESET
void loop(){

   MEASUREMOISTURE1 ();                     // measure moisture level1
   INDICATELEVEL ();
   delay(1000);                            // wait 1 sec to Check for new values;
                                            //this value is just for demonstration purposes and will in a practical application be far less frequent
}
//////////////////END of LOOP////////////////////////////////////////////////////////////  

/////////////////////////////////////////////////// Hereafter follows the Function for measuring the Moisture level with MoistSensor1 (capacitive measurement)

void MEASUREMOISTURE1 ()  {
  Moistlevel1 = 0;
  ledcWrite(Channel1, 128);                             // send a PWM signal of 600 kHz to pin 25 with a dutycycle of 50%
  delay(200);                                           // allow the circuit to stabilize  
  for (int m = 1; m < 6 ; m++)                          // take 5 consecutive measurements in 5 seconds
    {
      Moistlevel1 = Moistlevel1 + analogRead(MoistSensor1Pin) ;    // Read data from analog pin 4 and add it to MoistLevel1 variable
      delay (1000);
    }
    Moistlevel1 = Moistlevel1 / 5;                       // Determine the average of 5 measurements 
    
    if (Moistlevel1 > 150 && Moistlevel1 < 375){
      level = 5;                                         // means moistlevel is 100%
      Serial.print(" Moistlevel is 100% "); Serial.print(" Moistlevel1 = "); Serial.println (Moistlevel1);
    }
    if (Moistlevel1 > 375 && Moistlevel1 < 725){
      level = 4;                                         // means moistlevel is 75%
      Serial.print(" Moistlevel is 75% "); Serial.print(" Moistlevel1 = "); Serial.println (Moistlevel1);
    }
    if (Moistlevel1 > 725 && Moistlevel1 < 1075){
      level = 3;                                         // means moistlevel is 50%
      Serial.print(" Moistlevel is 50% "); Serial.print(" Moistlevel1 = "); Serial.println (Moistlevel1);
    }
    if (Moistlevel1 > 1075 && Moistlevel1 < 1425){
      level = 2;                                         // means moistlevel is 25%
      Serial.print(" Moistlevel is 25% "); Serial.print(" Moistlevel1 = "); Serial.println (Moistlevel1);
    }
    if (Moistlevel1 > 1425 && Moistlevel1 < 1775){
      level = 1;                                         // means moistlevel is 1%
      Serial.print(" Moistlevel is 1% "); Serial.print(" Moistlevel1 = "); Serial.println (Moistlevel1);
    }
  ledcWrite(Channel1, 0);                                // stop generating PWM tones at pin 25
  }


/////////////////////////////////////////////////// Hereafter follows the Function for Indicating the MoistureLevel (called from within the loop)

void INDICATELEVEL ()  {

for (int t = 0; t < 6 ; t++)
    {
    strip.setPixelColor(t, 0, 0, 0);                     // turn off all LEDs on the Moist Level Indicator
    strip.show();                                  
    }
    
int redVal, greenVal, blueVal;                          // Set the Moist Level Indicator LED with a color defined in the Array color_scheme
    redVal = color_scheme[level*3];
    greenVal = color_scheme[level*3 + 1];
    blueVal = color_scheme[level*3 + 2];
    
    strip.setPixelColor(level-1, strip.Color(redVal, greenVal, blueVal) ); 
    strip.show();
    }

Credits

Pedro52

Pedro52

6 projects • 46 followers

Comments