When you hear the term “smart garden,” one of the first things that comes to mind is a system that monitors the moisture level of the soil and automatically supplies the necessary amount of water to the plants.
With this system, plants can be watered only when required, avoiding over- or under-watering.
If you want to build such a system, you will undoubtedly require a Soil Moisture Sensor.
How Does a Soil Moisture Sensor Work?
The soil moisture sensor operates in a straightforward manner.
The fork-shaped probe with two exposed conductors acts as a variable resistor (similar to a potentiometer) whose resistance varies with the soil’s moisture content.
This resistance varies inversely with soil moisture:
- The more water in the soil, the better the conductivity and the lower the resistance.
- The less water in the soil, the lower the conductivity and thus the higher the resistance.
The sensor produces an output voltage according to the resistance, which by measuring we can determine the soil moisture level.
Hardware Overview
A typical soil moisture sensor consists of two parts.
The Probe
The sensor includes a fork-shaped probe with two exposed conductors that is inserted into the soil or wherever the moisture content is to be measured.
As previously stated, it acts as a variable resistor, with resistance varying according to soil moisture.
The Module
In addition, the sensor includes an electronic module that connects the probe to the Arduino.
The module generates an output voltage based on the resistance of the probe, which is available at an Analog Output (AO) pin.
The same signal is fed to an LM393 High Precision Comparator, which digitizes it and makes it available at a Digital Output (DO) pin.
The module includes a potentiometer for adjusting the sensitivity of the digital output (DO).
You can use it to set a threshold, so that when the soil moisture level exceeds the threshold, the module outputs LOW otherwise HIGH.
This setup is very useful for triggering an action when a certain threshold is reached. For example, if the moisture level in the soil exceeds a certain threshold, you can activate a relay to start watering the plant.
Rotate the knob clockwise to increase sensitivity and counterclockwise to decrease it.
The module also includes two LEDs. The Power LED illuminates when the module is turned on, and the Status LED illuminates when the soil moisture level exceeds the threshold value.
Soil Moisture Sensor Pinout
The soil moisture sensor is extremely simple to use and only requires four pins to connect.
AO (Analog Output) generates analog output voltage proportional to the soil moisture level, so a higher level results in a higher voltage and a lower level results in a lower voltage.
DO (Digital Output) indicates whether the soil moisture level is within the limit. D0 becomes LOW when the moisture level exceeds the threshold value (as set by the potentiometer), and HIGH otherwise.
VCC supplies power to the sensor. It is recommended that the sensor be powered from 3.3V to 5V. Please keep in mind that the analog output will vary depending on the voltage supplied to the sensor.
GND is the ground pin.
Experiment 1 – Measuring Soil Moisture using Analog Output (A0)
In our first experiment, we will read the analog output to estimate the level of soil moisture.
Wiring
Let’s hook up the soil moisture sensor to the Arduino.
Let’s begin by powering up the sensor. For this, you can connect the VCC pin of the module to Arduino’s 5V pin.
However, one well-known issue with these sensors is that they have a shorter lifespan because they are constantly exposed to moisture. Moreover, constantly applying power to the sensor while buried in soil significantly accelerates the rate of corrosion.
To avoid this, it is recommended that the sensor be turned on only when taking readings.
One easy way to do this is to connect the sensor’s power pin to a digital pin on an Arduino and set it to HIGH or LOW as needed. Also, the total power drawn by the module (with both LEDs lit) is about 8 mA, so powering the module from a digital pin is fine. So, we’ll connect the VCC pin to the Arduino’s digital pin #7.
Finally, connect the A0 pin to the Arduino’s A0 ADC pin.
The wiring is shown in the image below.
Finding the threshold values
To estimate the soil moisture level, record the values of your sensor output when the soil is as dry as possible and when it is completely saturated.
Keep in mind that your sensor may be more or less sensitive depending on the type of soil you use. Also, minerals dissolved in water from fertilizers and other sources can affect the sensor output.
Simply run the sketch below and take your readings.
// Sensor pins
#define sensorPower 7
#define sensorPin A0
void setup() {
pinMode(sensorPower, OUTPUT);
// Initially keep the sensor OFF
digitalWrite(sensorPower, LOW);
Serial.begin(9600);
}
void loop() {
//get the reading from the function below and print it
Serial.print("Analog output: ");
Serial.println(readSensor());
delay(1000);
}
// This function returns the analog soil moisture measurement
int readSensor() {
digitalWrite(sensorPower, HIGH); // Turn the sensor ON
delay(10); // Allow power to settle
int val = analogRead(sensorPin); // Read the analog value form sensor
digitalWrite(sensorPower, LOW); // Turn the sensor OFF
return val; // Return analog moisture value
}
When you run the sketch, you should see readings similar to the ones below:
- When the soil is dry (around 850)
- When the soil is completely saturated (around 400)
This test may require some trial and error. Once you have the readings, you can use them as a threshold to trigger an action.
Arduino Code
The sketch below estimates the level of soil moisture using the following threshold values:
- < 500 is too wet
- 500-750 is the target range
- > 750 is dry enough to be watered
/* Change these values based on your calibration values */
#define soilWet 500 // Define max value we consider soil 'wet'
#define soilDry 750 // Define min value we consider soil 'dry'
// Sensor pins
#define sensorPower 7
#define sensorPin A0
void setup() {
pinMode(sensorPower, OUTPUT);
// Initially keep the sensor OFF
digitalWrite(sensorPower, LOW);
Serial.begin(9600);
}
void loop() {
//get the reading from the function below and print it
int moisture = readSensor();
Serial.print("Analog Output: ");
Serial.println(moisture);
// Determine status of our soil
if (moisture < soilWet) {
Serial.println("Status: Soil is too wet");
} else if (moisture >= soilWet && moisture < soilDry) {
Serial.println("Status: Soil moisture is perfect");
} else {
Serial.println("Status: Soil is too dry - time to water!");
}
delay(1000); // Take a reading every second for testing
// Normally you should take reading perhaps once or twice a day
Serial.println();
}
// This function returns the analog soil moisture measurement
int readSensor() {
digitalWrite(sensorPower, HIGH); // Turn the sensor ON
delay(10); // Allow power to settle
int val = analogRead(sensorPin); // Read the analog value form sensor
digitalWrite(sensorPower, LOW); // Turn the sensor OFF
return val; // Return analog moisture value
}
If everything is fine, you should see something similar on the serial monitor.
Experiment 2 – Measuring Soil Moisture using Digital Output (D0)
In our second experiment, we will use digital output to determine whether the soil moisture level is within acceptable limits.
Wiring
We’ll reuse the previous experiment’s circuit. Simply disconnect the connection to the ADC pin and connect the D0 pin on the module to the Arduino’s digital pin #8.
The following image shows the wiring.
Setting the threshold
The module has a built-in potentiometer for setting the moisture level threshold above which the module outputs LOW and the status LED lights up.
Now, to set the threshold, stick the probe into the soil when your plant needs watering and turn the pot clockwise until the Status LED is on. Then, turn the pot back counterclockwise just until the LED goes off.
That’s all there is to it; your module is now ready to use.
Arduino Code
Now, upload the sketch below to your Arduino.
// Sensor pins
#define sensorPower 7
#define sensorPin 8
void setup() {
pinMode(sensorPower, OUTPUT);
// Initially keep the sensor OFF
digitalWrite(sensorPower, LOW);
Serial.begin(9600);
}
void loop() {
//get the reading from the function below and print it
int val = readSensor();
Serial.print("Digital Output: ");
Serial.println(val);
// Determine status of our soil moisture situation
if (val) {
Serial.println("Status: Soil is too dry - time to water!");
} else {
Serial.println("Status: Soil moisture is perfect");
}
delay(1000); // Take a reading every second for testing
// Normally you shoul take reading perhaps every 12 hours
Serial.println();
}
// This function returns the analog soil moisture measurement
int readSensor() {
digitalWrite(sensorPower, HIGH); // Turn the sensor ON
delay(10); // Allow power to settle
int val = digitalRead(sensorPin); // Read the analog value form sensor
digitalWrite(sensorPower, LOW); // Turn the sensor OFF
return val; // Return analog moisture value
}
You should see similar output on the serial monitor.