What Sensor Is Best For Water Level Measurement : R/arduino

Aug 05, 2026

Leave a message

 

The Short Answer

Float Switch - Simple On/Off Detection

What it does

Wiring diagram:

Arduino 5V -------+------- Float Switch ------ Arduino Pin 7

| |

[10k pull-down] [INPUT_PULLUP]

| |

GND ------------------------------ GND

Arduino code

const int FLOAT_PIN = 7;

void setup() {

Serial.begin(9600);

pinMode(FLOAT_PIN, INPUT_PULLUP); // use internal pull-up, no external resistor needed

}

void loop() {

bool waterHigh = digitalRead(FLOAT_PIN) == LOW; // LOW = water above setpoint

Serial.print("Water: ");

Serial.println(waterHigh ? "HIGH" : "LOW");

delay(500);

}

Pros and Cons

Pros

Cons

Dirt cheap ($1-3)

On/off only - no continuous level data

Dead simple wiring

Moving parts - can stick or jam in dirty water

Works with any Arduino pin

Must physically place it at the exact switch point

No calibration needed

Usually single setpoint - add multiple for multiple levels

Handles AC/DC pump switching directly

Contact wear over time in frequently switching applications

HC-SR04 Ultrasonic Sensor - Continuous Non-Contact Level

What it does

Wiring diagram:

HC-SR04 Arduino Uno

-------- -----------

VCC --------> 5V

GND --------> GND

TRIG --------> Pin 9

ECHO --------> Pin 10 (via 1k ohm resistor if needed)

Arduino code (NewPing library)

#include <NewPing.h>

const int TRIG_PIN = 9;

const int ECHO_PIN = 10;

const int MAX_DISTANCE = 200; // cm - max range of HC-SR04

const float TANK_HEIGHT_CM = 30.0; // measure your actual tank height

NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE);

void setup() {

Serial.begin(9600);

}

void loop() {

int distance_cm = sonar.ping_cm();

if (distance_cm == 0) {

Serial.println("Out of range");

} else {

float water_level_cm = TANK_HEIGHT_CM - distance_cm;

float fill_pct = (water_level_cm / TANK_HEIGHT_CM) * 100.0;

Serial.print("Distance: "); Serial.print(distance_cm); Serial.print(" cm | ");

Serial.print("Water level: "); Serial.print(water_level_cm); Serial.print(" cm | ");

Serial.print("Fill: "); Serial.print(fill_pct); Serial.println(" %");

}

delay(500);

}

Pros and Cons

Pros

Cons

Non-contact - nothing in the water

Accuracy degrades in steam, condensation, or heavy foam

Continuous level - not just on/off

HC-SR04 is 5V - use a voltage divider on ECHO for 3.3V boards

Cheap (~$3)

Temperature affects speed of sound - add DS18B20 for temperature compensation

Easy to install

Beam angle means it needs clearance above water surface

Works for tanks, sumps, reservoirs

Not ideal for very small containers due to minimum detection distance

The condensation problem

Pressure Sensor (MPX5010 / Submersible) - Depth Measurement

What it does

MPX5010 wiring (analog, 5V Arduino):

MPX5010 VOUT -----> Arduino A0

MPX5010 GND -----> Arduino GND

MPX5010 VCC -----> Arduino 5V

(also connect a tube from the MPX5010 pressure port to the tank)

Arduino code (MPX5010)

const int PRESSURE_PIN = A0;

const float SENSOR_MAX_KPA = 10.0; // MPX5010 = 0-10 kPa

const float ADC_MAX = 1023.0;

const float GRAVITY = 0.9806; // kPa per cm of water

void setup() { Serial.begin(9600); }

void loop() {

int raw = analogRead(PRESSURE_PIN);

float voltage = (raw / ADC_MAX) * 5.0;

float pressure_kPa = (raw / ADC_MAX) * SENSOR_MAX_KPA;

float depth_cm = pressure_kPa / GRAVITY;

Serial.print("Raw: "); Serial.print(raw);

Serial.print(" | Pressure: "); Serial.print(pressure_kPa, 2); Serial.print(" kPa");

Serial.print(" | Depth: "); Serial.print(depth_cm, 1); Serial.println(" cm");

delay(500);

}

Pros and Cons

Pros

Cons

Direct depth measurement in cm

MPX5010 is not submersible - requires a tube to the tank

Very accurate - 0.5% typical error

Submersible modules cost more ($15-30)

Works through condensation, foam, steam

Tube-based systems can get moisture inside the tube

Analog output - works with any Arduino

Needs calibration - zero at empty tank, span at full tank

Capacitive Sensor - Non-Metallic Tank Water Detection

What it does

DIY capacitive sensor wiring:

DIY capacitive plate ----+---> Arduino Pin 2 (send)

|

[1M-10M resistor]

|

+---> Arduino Pin 3 (receive)

|

GND

Arduino code (CapacitiveSensor library)

#include <CapacitiveSensor.h>

// 1M resistor between pins 2 and 3; sensor wire on pin 3

CapacitiveSensor cs = CapacitiveSensor(2, 3);

const long THRESHOLD = 500; // calibrate this value for your setup

void setup() {

Serial.begin(9600);

cs.set_CS_AutocaL_Millis(0xFFFFFFFF); // auto-calibrate

}

void loop() {

long sensorValue = cs.capacitiveSensor(30);

bool waterPresent = sensorValue > THRESHOLD;

Serial.print("Capacitance: "); Serial.print(sensorValue);

Serial.print(" | Water: "); Serial.println(waterPresent ? "YES" : "NO");

delay(200);

}

Pros and Cons

Pros

Cons

Works through non-conductive tank walls - no holes needed

Requires calibration in the actual tank and liquid

No moving parts, no contact with liquid

Does not work through metal tanks

Very sensitive to thin water films

Conductivity of the liquid affects the reading - saltwater reads differently from pure water

DIY-friendly and cheap ($2-5 for DIY)

Long sensor wires pick up electrical noise - keep wires short or use shielded cable

Multiple sensors can be arranged for multiple setpoints

Temperature changes the baseline - re-calibrate seasonally

Optical TIR Sensor (TCRT5000 / Generic) - Point-Level With No Moving Parts

What it does

Wiring:

VCC (3.3-5V) -----> Arduino 3.3V or 5V

GND -----> Arduino GND

DO (digital out) -----> Arduino Pin 8

AO (analog out) -----> Arduino A1 (optional)

Arduino code

const int SENSOR_DIGITAL = 8;

const int SENSOR_ANALOG = A1;

void setup() {

Serial.begin(9600);

pinMode(SENSOR_DIGITAL, INPUT);

}

void loop() {

int digitalVal = digitalRead(SENSOR_DIGITAL); // HIGH = air, LOW = water

int analogVal = analogRead(SENSOR_ANALOG);

Serial.print("Digital: "); Serial.print(digitalVal ? "DRY" : "WET");

Serial.print(" | Analog: "); Serial.println(analogVal);

delay(200);

}

Pros and Cons

Pros

Cons

No moving parts - reliable in dirty water

Point-level only - one setpoint per sensor

Fast response (1-5 ms)

Sensor tip must be in contact with or very close to the liquid

Compact - fits in small spaces

Prism tip sensitive to fouling - algae or scale changes the TIR condition

Works with Arduino at 3.3V or 5V

Not suitable for opaque or highly coloured liquids

Both digital (ON/OFF) and analog output

Requires IR LED current-limiting resistor (typically 100-330 ohm)

Side-by-Side Comparison

Sensor

Type

Cost

Arduino Voltage

Best For

Key Gotcha

Float Switch

Point-level

$1-3

5V

Simple pump control, sump pits

Moving parts jam in debris

HC-SR04 Ultrasonic

Continuous

$3-5

5V (3.3V with resistor)

Water tanks, non-contact, DIY

Condensation causes false echoes

MPX5010 Pressure

Continuous

$10-15

5V analog

Accurate depth in cm

Tube-based, not submersible

Submersible Pressure Module

Continuous

$15-30

5V analog or 3.3V

Deep tanks, wells

Needs waterproof cable

DIY Capacitive Sensor

Point or multi-level

$2-5

5V or 3.3V

Non-metallic tanks, no holes needed

Requires calibration in your tank

Optical TIR Sensor

Point-level

$3-8

3.3V or 5V

Compact detection, clean liquids

Prism tip fouls in dirty water

Which Sensor Should You Use?

Use a float switch if...

You only need to know when the water reaches one point - like turning a pump on or off

You want the absolute cheapest, simplest solution

Your tank has debris or fibrous material that would jam a float

Use an HC-SR04 if...

You want continuous fill percentage and your tank has an open top with headroom above the water

You want to monitor a large tank or sump pit without touching the liquid

You are okay doing some math in code to convert distance to fill percentage

Use a pressure sensor if...

You need depth in centimetres and your tank is sealed or underground

You want accuracy better than 1 cm and are willing to calibrate

You are monitoring a sump pit or reservoir and can route a small tube to the sensor

Use a capacitive sensor if...

You cannot put anything inside your tank (food-safe, sealed, pressurized)

You are using a plastic, glass, or ceramic container

You want multiple detection points and can arrange several DIY plates

Use an optical TIR sensor if...

You want point-level detection with no moving parts

Your application is clean water or you can keep the prism tip clean

You need a fast response time (under 10 ms)

Calibration Tips That Forum Posts Skip

Ultrasonic: Temperature Compensation

speed_of_sound = 331.3 + (0.606 * temperature_C); // m/s

distance = (speed_of_sound * travel_time_us / 2) / 10000; // cm

Pressure: Two-Point Calibration

offset = reading_at_empty

span_reading = reading_at_full - reading_at_empty

span_depth = actual_full_height_cm

depth_cm = (current_reading - offset) / span_reading * span_depth

Capacitive: Find Your Threshold

void calibrate() {

Serial.println("Empty tank - leave sensor exposed to air..."); delay(2000);

long dryReading = cs.capacitiveSensor(30);

Serial.println("Now fill tank above sensor, then press a key..."); delay(2000);

long wetReading = cs.capacitiveSensor(30);

long threshold = (dryReading + wetReading) / 2;

Serial.print("Threshold set to: "); Serial.println(threshold);

}

Frequently Asked Questions

Can I use multiple sensors in one tank?

Will this work with Raspberry Pi?

How do I power the sensor and Arduino from the same supply?

The sensor gives wrong readings in direct sunlight / outdoors.

What's the most reliable long-term Arduino water level project?

Send Inquiry