An Arduino plant monitor with a soil moisture sensor
Intermediate
Or see every lesson.
- 261parts on the bench
- 31boards running now
- 1.00xreal time, on every board
A soil moisture sensor is the start of almost every plant project: a lamp that says "water me", a log of how fast a pot dries out, or a pump that waters on its own. The one in the circuit above is the black capacitive kind, marked "v1.2". It has no bare metal in the soil, so it does not rust away like the older two-prong sensors do.
The circuit is an Arduino Uno reading the soil sensor, a rain sensor and a water level sensor, once a second. A green lamp lights when the soil is dry and it is not raining. Drag the slider on the soil sensor to water the soil and watch the numbers move. It all runs in your browser on the sketch below.
What you need
- An Arduino Uno
- A capacitive soil moisture sensor (v1.2)
- A rain sensor plate with its comparator board (optional)
- A water level sensor (optional)
- A green LED and a 220 ohm resistor
- A half-size breadboard and jumper wires
Wiring
| Part and pin | Goes to | Note |
|---|---|---|
| Soil sensor VCC | 5 V | Works from 3.3 to 5.5 volts |
| Soil sensor GND | GND | Shared ground |
| Soil sensor AOUT | A0 | An analog pin, not a digital one |
| Rain sensor AO | A1 | Reads lower when wet |
| Rain sensor DO | Pin 7 | Goes LOW when the plate is wet enough |
| Water level S | A2 | Reads higher as the water rises |
| Green LED | Pin 8 | Through a 220 ohm resistor to GND |
Wetter reads lower
This catches almost everyone. A capacitive soil sensor gives a lower number when the soil is wetter. Held in the air, the one above reads 522 on the Uno. With its tip in water, it reads 260. Real soil lands somewhere in between. The slider starts at 30 percent, which reads 443.
So to get a percent, you map the numbers the other way around: map(soil, 520, 260, 0, 100). The dry number goes first and the wet number second. Then constrain() keeps the answer between 0 and 100, in case a reading lands a little past either end.
const int SOIL = A0;
// This sensor's two ends, in counts on a 5 V board.
const int SOIL_AIR = 520;
const int SOIL_WATER = 260;
void loop() {
int soil = analogRead(SOIL);
int percent = constrain(map(soil, SOIL_AIR, SOIL_WATER, 0, 100), 0, 100);
Serial.print("soil ");
Serial.print(percent);
Serial.println("%");
delay(1000);
}Calibrate your own sensor
The numbers 520 and 260 belong to this sensor. Yours will be a little different, and two sensors from the same bag can differ by more than a whole watering. So every real project starts with a two-minute test.
Upload a sketch that just prints analogRead(A0) once a second. Hold the sensor in the air and write down the number. Then put it in a glass of water, up to the line on the board, and write that number down too. Those are your dry and wet ends. For even better numbers, use a cup of dry soil and a cup of soaked soil from the same pot.
Three sensors that disagree about which way is up
The rain sensor also reads lower when it is wet. Dry, A1 reads the full 1023. Its board has a comparator with a small knob, too. When the plate is wet enough, the DO pin goes LOW, so pin 7 is a plain yes or no for rain with no math at all.
The water level sensor reads higher when it is wetter. It jumps up as soon as the tip gets wet, then creeps higher as the water rises. That makes it a good "is there water" sensor, but not a ruler.
The lamp on pin 8 puts two of these together. It lights when the soil is under 30 percent and it is not raining. The plant needs water, and the sky is not going to give it any.
Try it in the editor
Change 30 to 40 and the lamp comes on sooner. Add a buzzer that beeps once a minute while the soil is dry.
To water on a timer, add a relay module on a spare pin and turn it on for a few seconds when the soil is dry. Our relay module guide shows the active LOW trap that catches most people.
Common mistakes
Using a digital pin. digitalRead() can only say 0 or 1. The soil sensor needs analogRead() on A0 to A5.
Expecting a bigger number for wetter soil. Map it the other way around, dry first.
Leaving a two-prong resistive sensor powered all the time. The bare metal corrodes in wet soil, and the readings drift as it does. Power it from a pin only when you read it, or use a capacitive sensor like this one.
Pushing the sensor in past the line. The parts at the top of the board are not waterproof.
Questions
Why does my soil moisture sensor read lower when the soil is wet?
That is how the capacitive sensor works. Water raises the capacitance around the stake, and the board turns that into a lower voltage. Map the reading with the dry number first: map(reading, dry, wet, 0, 100).
Capacitive or resistive soil sensor: which should I buy?
Capacitive, for anything that stays in the soil. The resistive kind has bare metal prongs with current through them, and they corrode in a few weeks of wet soil.
Does Mokxi model real soil?
No. The slider is a straight line between the sensor’s dry and wet voltages. A real sensor’s reading is a curve that changes from soil to soil, which is why you calibrate your own.
Keep going
Build this for real
Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.