Soil Moisture Measurement
Measuring soil moisture is a common and useful practical exercise for learning how sensors interface with microcontrollers and how analog signals are converted into meaningful physical measurements. Two widely used approaches are the capacitive method and the resistive (resistance-based) method. Both types of sensors produce an electrical signal that can be read by a microcontroller ADC (analog-to-digital converter), but they rely on different physical principles and have different practical trade-offs.
Capacitive Soil Moisture Sensor — Principle of Operation
A capacitive soil moisture sensor is essentially a printed circuit-board (PCB) capacitor whose effective capacitance changes with the dielectric properties of the surrounding soil. The "electrodes" are interleaved copper traces on the PCB (an interdigitated layout) that form two capacitor plates separated by the board material and the surrounding medium.
As soil moisture increases, the dielectric constant of the material between (and around) the PCB traces increases (water has a much higher dielectric constant than dry soil or air). That change in dielectric constant increases the effective capacitance. The sensor module contains simple electronics (an oscillator, RC timing circuit or capacitance-to-voltage converter) that translate the small change in capacitance into a measurable analog voltage (AOUT) which you read with the ADC.
Key practical points: capacitive sensors are non-conductive (the traces are usually coated), so they do not pass DC current through the soil and do not corrode quickly. They are generally more stable and longer lasting, and they work well with microcontrollers running at 3.3 V or 5 V.
Resistive (Resistance-based) Soil Moisture Sensor — Principle of Operation
A resistive soil moisture sensor measures the electrical resistance (or conductance) between two exposed metal electrodes that are inserted into the soil. When the soil contains more water and dissolved ions, it conducts electricity better and the resistance between the electrodes decreases; when the soil is dry the resistance increases.
The typical way to use a resistive probe is to build a voltage divider: the probe forms one leg of the divider and a known resistor forms the other. The voltage at the divider midpoint changes with the probe resistance and is read by the microcontroller analog input. Many commercial resistive sensor kits include a small driver board with an op-amp or comparator that provides both an analog output (A0) and a configurable digital threshold output (D0).
Key practical points: resistive probes are simple and cheap, and the onboard digital output is useful for simple threshold-based control (e.g. switching a pump). However, because DC current flows through the electrodes, they are prone to electrochemical corrosion and degradation over time; they also may give less stable readings in the long term compared to capacitive sensors.
In the following lab exercise we will demonstrate how to interface both sensor types with an Arduino (or ESP32), how to read and interpret the analog signal, and how to calibrate the readings for your local soil. The exercise will include wiring diagrams, example code and visualization of the measured values.
Resistive Soil Moisture Sensor
This section continues the lesson on soil moisture sensing and focuses on the resistive (resistance-based) probe. The resistive probe is a simple, low-cost sensor that measures how well the soil conducts electricity — a practical way to estimate moisture content. Below we explain what the probe measures, what it is typically used for, and how to wire it in both the simplified Tinkercad setup and a real-world circuit using the small driver board (LM393 module).
How the Resistive Probe Measures Moisture
The probe consists of two exposed metal electrodes that are inserted into the soil. The soil between the electrodes acts as a resistor: when the soil contains more water and dissolved ions, its electrical resistance decreases; when the soil is dry, resistance increases. The probe by itself is not an active device — it must be used as part of a simple circuit (usually a voltage divider) so a microcontroller can read a voltage proportional to the soil resistance.
Typical uses include:
- Simple moisture monitoring for plant irrigation.
- Threshold detection (is soil dry / wet) for automatic watering systems.
- Educational projects and prototypes where low cost is important.
Wiring and Connections — Conceptual
The usual electrical arrangement is a voltage divider.
One leg of the divider is the probe (variable resistance Rsoil)
and the other leg is a known resistor R1.
The midpoint voltage is read by the microcontroller ADC:
VCC --- R1 ---+--- A0 (ADC input)
|
Rsoil (probe)
|
GND
As Rsoil changes, the midpoint voltage changes and analogRead()
returns a different value. To get reliable results:
- Choose
R1so the midpoint voltage moves across a useful ADC range (commonly 10 kΩ). - Only power the probe briefly during a measurement to reduce electrochemical wear.
- Use common ground between sensor module and microcontroller.
The soil moisture sensor measures the amount of water in the soil by detecting changes in its electrical resistance. When the soil is dry, its resistance is high, while in moist soil the resistance decreases. The sensor converts this resistance into a voltage signal that can be read by the Arduino board.
Figure 2 shows the basic wiring diagram for connecting the soil moisture sensor directly to the Arduino UNO. The diagram, created in Tinkercad, illustrates a simple connection of the sensor pins VCC, GND, and Signal to the corresponding pins on the Arduino.
In this exercise, the analog pin A0 is used to read the output voltage from the sensor. This voltage depends on the resistance of the soil between the two probe electrodes. The Arduino converts the analog voltage into a digital value between 0 and 1023, which represents the relative moisture level.
Using the LM393 Comparator Module
Figure 3 shows the practical connection of the sensor through an LM393 comparator module. This module allows the sensor to work in both analog and digital modes.
- Analog output (A0) — provides a continuous voltage signal proportional to the soil’s moisture level.
- Digital output (D0) — provides a binary signal (0 or 1) depending on the set threshold level.
The comparator board includes a small potentiometer that lets you adjust the voltage threshold. When the measured voltage from the sensor drops below this threshold, the digital output (D0) becomes LOW (0); otherwise, it stays HIGH (1). This makes it possible to trigger simple actions, such as turning on a water pump or LED indicator.
Pin Configuration
The LM393 module has 4 + 2 pins:
- On the two-pin side: the sensor’s metal probes are connected.
- On the four-pin side (module output):
- VCC → connect to 5V on the Arduino
- GND → connect to GND on the Arduino
- A0 → connect to the analog input A0
- D0 → optional digital output for threshold-based detection
(Insert Figure 2: Basic wiring in Tinkercad here)
(Insert Figure 3: Connection using LM393 module here)
This setup allows easy measurement of soil moisture and helps demonstrate the principle of resistance-based sensing using Arduino.
Measuring Soil Moisture with a Capacitive Sensor
The capacitive soil moisture sensor represents a more advanced version of the soil humidity sensor. Unlike the resistive type, which measures changes in electrical resistance between two electrodes, the capacitive sensor measures variations in capacitance caused by the dielectric properties of the soil. When the soil becomes wetter, its dielectric constant increases, which raises the capacitance value and changes the analog signal output of the sensor.
The main advantage of a capacitive sensor compared to a resistive one is that it does not cause electrolysis, since no direct current passes through the soil. This significantly extends the sensor’s lifespan and provides more stable and repeatable measurements over time.
Overview
Figure 1 shows a real connection of the capacitive soil moisture sensor with an Arduino board inserted into a flower pot,
while Figure 2 illustrates the wiring diagram of the sensor connection — including the power pins
(Vcc and GND) and the analog output pin (A0) connected to the Arduino analog input.
Sensor Operation
The capacitive sensor has an analog output labeled AO that provides a voltage proportional
to the soil moisture level.
This voltage is read by the Arduino through the analogRead(A0) function.
The value typically ranges from 0 to 1023 and can be linearly mapped to a moisture percentage for easier interpretation.
// Example: Reading from a capacitive soil moisture sensor
int sensorPin = A0; // analog input connected to the sensor AO pin
float moistureValue = 0; // current moisture level
void setup() {
Serial.begin(115200); // communication with Processing
}
void loop() {
int rawValue = analogRead(sensorPin); // read raw sensor value
moistureValue = map(rawValue, 1023, 300, 0, 100); // map to percentage (adjust if needed)
Serial.println(moistureValue); // send moisture value to Processing
delay(3000); // wait 3 seconds between readings
}
Serial Communication and Processing Visualization
The way data is sent to Processing is exactly the same as with the resistive sensor version. In both cases, the Arduino sends a single numeric value — the soil moisture percentage — via the serial port at a baud rate of 115200.
Therefore, the same Processing sketch shown in the previous section can be used for this sensor as well.
It automatically receives the moisture values through the serialEvent() function,
displays them on screen, and visualizes changes in real time using a text label and a color bar.
The only difference between the two sensors lies in the measurement principle — resistive sensors measure conductivity, while capacitive sensors detect changes in dielectric constant. The wiring, communication, and visualization methods remain identical.
Arduino Code – Measuring Soil Moisture
The following Arduino program reads data from the resistive soil moisture sensor using the analog input pin A0.
The measured value is converted into a percentage of soil moisture and sent through the serial port every 3 seconds.
The data can be viewed directly in the Serial Monitor (from the Arduino IDE) or read in other applications
such as Processing for visualization and further analysis.
Arduino Program
// Define the analog pin connected to the soil moisture sensor
const int pin_A0 = A0;
// Threshold value to define when the soil is considered dry
const int dryThreshold = 200;
void setup() {
// Initialize serial communication at 115200 bits per second
Serial.begin(115200);
}
void loop() {
// Read the raw analog value from the sensor (0 to 1023)
int sensorValue = analogRead(pin_A0);
// Convert the raw value to a percentage:
// High sensor value (e.g., 1023) → dry soil → low moisture percent
// Low sensor value (e.g., 300) → wet soil → high moisture percent
float moisturePercent = 100.0 * (1023 - sensorValue) / 1023;
// Send the calculated moisture percentage to the serial port
Serial.println(moisturePercent);
// Wait 3 seconds before the next reading
delay(3000);
}
Explanation
analogRead(A0)reads the voltage from the sensor and converts it to a digital value between 0 and 1023.- Higher values correspond to drier soil (higher resistance), while lower values indicate more moisture.
- The percentage value is computed linearly to make it easier to interpret.
Serial.println()sends the measured humidity percentage to the serial interface — it can be monitored in Serial Monitor or other software such as Processing, MATLAB, or Python scripts that read serial data.
This simple program can serve as the basis for more advanced applications, such as automatic irrigation systems or data logging for environmental monitoring.
Processing Code – Visualization of Soil Moisture Data
The following Processing program receives soil moisture data from the Arduino via the serial port
and displays it on the screen in both text and graphical form.
Each value sent by the Arduino represents the current soil moisture percentage and is transmitted
every 3 seconds using the Serial.println() command.
Processing Program
import processing.serial.*;
Serial myPort;
String val = "";
float moisture = 0; // Stores the latest moisture value (0–100%)
void setup() {
size(400, 200); // Window size
myPort = new Serial(this, Serial.list()[0], 115200); // Open the first available serial port
}
void draw() {
background(255); // White background
fill(0); // Black text color
textSize(20);
text("Soil Moisture: " + nf(moisture, 0, 2) + "%", 50, 60); // Display with 2 decimal places
// Visual moisture bar
fill(0, 100, 255);
rect(50, 100, map(moisture, 0, 100.0, 0, 300), 30); // Draws a blue bar proportional to moisture
}
void serialEvent(Serial p) {
val = p.readStringUntil('\n'); // Reads the entire line sent from Arduino
if (val != null) {
val = trim(val); // Removes extra whitespace and newline characters
try {
moisture = float(val); // Converts the received string to a float value
} catch (Exception e) {
println("Failed to parse value: " + val); // Error message if conversion fails
}
}
}
Explanation
- Serial communication: The program uses the
processing.seriallibrary to communicate with the Arduino board via USB. Serial.list()returns a list of available ports. The first one ([0]) is usually the Arduino — if not, try a different index.- Function
serialEvent()automatically triggers whenever new serial data arrives. It reads a complete line (terminated by'\n') sent by Arduino. - The string value is then converted to a
floatso it can be used for calculations and graphical display. - Inside the
draw()loop, the latest value is shown as text and as a blue bar proportional to soil moisture percentage.
This visual feedback allows real-time monitoring of how soil moisture changes. By connecting a resistive or capacitive sensor to the Arduino, you can observe how the measured value responds to different soil conditions (dry, damp, or wet). Processing provides an intuitive and interactive way to visualize sensor data from Arduino projects.
|< Introduction to Servo Motors

