An Arduino water level sensor, from dry to full
Beginner
Or see every lesson.
- 455parts on the bench
- 43boards running now
- 1.00xreal time, on every board
The water level sensor in most kits is a red board with ten bare copper traces up its length and three pins marked S, + and -. Dip it in water and the reading on S rises with the depth. It is the cheapest way to tell an empty cup from a full one, a dry plant tray from a flooded one, or a sump from an overflow.
The circuit above is an Uno with the sensor on A0. Drag the slider to raise the water up the traces and the serial monitor says dry, low, half or full, with the raw reading beside it. It runs in your browser on the sketch below, so you can see the real shape of the readings before you put one in water.
What you need
- An Arduino Uno
- A water level sensor (the red three-pin board)
- A half-size breadboard and jumper wires
- A cup of water, on the real desk
Wiring
| Part and pin | Goes to | Note |
|---|---|---|
| Sensor S | A0 | The analog reading |
| Sensor + | 5 V | Better: a digital pin, switched on only to read |
| Sensor - | GND |
How the traces turn water into a voltage
Half the traces are joined to the supply. The other half sit between them and go to a small transistor on the board. Dry, nothing connects the two sets and S sits at 0. Water joins them, a little current flows into the transistor, and S rises. The deeper the water, the more trace it joins and the higher S goes.
The reading does not rise in a straight line. It jumps as soon as the tip touches the water and then creeps up. In the circuit above, A0 reads 127 at 1 mm, about 506 at 10 mm, 608 at 20 mm and about 675 at the full 40 mm. Half the range is used up in the first few millimeters.
The sketch, step by step
The sketch reads A0 every 200 milliseconds and sorts the number into four words: under 100 is dry, under 400 is low, under 600 is half, and anything above is full. It only prints when the word changes, so the serial monitor stays readable.
Raise the slider in steps and the lines read "reading 0: dry", then "reading 127: low" at 1 mm, "reading 506: half" at 10 mm and "reading 608: full" at 20 mm.
const int SENSOR = A0;
const char *levelOf(int reading) {
if (reading < 100) return "dry";
if (reading < 400) return "low";
if (reading < 600) return "half";
return "full";
}
const char *lastLevel = "";
void setup() {
Serial.begin(9600);
Serial.println("Mokxi Uno: water level sensor");
}
void loop() {
int reading = analogRead(SENSOR);
const char *level = levelOf(reading);
if (level != lastLevel) {
lastLevel = level;
Serial.print("reading ");
Serial.print(reading);
Serial.print(": ");
Serial.println(level);
}
delay(200);
}Keep it from corroding
Bare copper in water with current flowing through it corrodes. A sensor powered all day can be eaten away in weeks. The fix is to power it from a digital pin instead of 5 V: set the pin HIGH, wait about 10 milliseconds, read A0, then set the pin LOW again. Read once every few seconds or minutes, and the traces last far longer.
The circuit here keeps + on 5 V to stay simple, and Mokxi does not model corrosion, so it will not warn you. Make the change before you leave a real one in water.
Try it in the editor
Add a buzzer on pin 8 that sounds when the level reaches full, for an overflow alarm. Add a green, a yellow and a red LED for low, half and full.
Then move + from 5 V to pin 7 and add the power-on, read, power-off steps from the corrosion section. The readings come out the same, and your real sensor will thank you.
Common mistakes
Reading the number as millimeters. The curve is steep at the bottom and flat at the top, and it changes with how much salt or soap is in the water. Calibrate against a ruler in your own water.
Leaving it powered all the time. See the corrosion section above.
Dipping the pins. Only the traces go in the water. Keep the top of the board, with the pins and the transistor, dry.
Expecting it to work in pure water. Distilled water barely conducts, so the reading stays low however deep it is.
Questions
How do I connect a water level sensor to an Arduino?
S to A0, + to 5 V (or to a digital pin you switch on to read) and - to GND. Read it with analogRead(A0): 0 is dry, and the number rises with the water.
What reading means full?
In the circuit above, about 675 with the traces fully under water. A real one depends on the water, so read yours dry and full and use those two numbers as your limits.
Can I measure the water level in a tank with it?
Only the bottom 4 cm or so, and only roughly. For a deep tank, an ultrasonic sensor looking down at the surface measures the distance instead. The ultrasonic tutorial shows how to read one.
Why does my water sensor read high after I take it out?
A film of water stays on the traces and keeps them connected until it dries. The simulated sensor does not model that film, so it drops to 0 the moment the slider does.
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.