Monitor a water level over Wi-Fi

Measure how high the water is in a glass with the water level sensor and check it from your phone.
  • Level:Intermediate
  • Duration: 45 min
  • Ages 12+
  • Platform: ESP32

Tools for this lesson

Helpful for this build. Open a tool to see tips and more projects that use it.

Monitor a water level over Wi-Fi – EEMENTOR STEM™ lesson

Is the plant tray, the pet bowl or the fish tank running low? The water level sensor has long copper stripes: the more of them are under water, the more current flows. The ESP32 turns that into a percentage you can check from your phone.

What you'll learn

  • How a resistive water level sensor works
  • Why powering a sensor only when you measure makes it last longer
  • How to calibrate a sensor between "empty" and "full"

What you need

  • ESP32 board, expansion board and USB cable (ESP32 IoT Starter Kit)
  • Water level sensor (45-in-1 Sensor Kit)
  • A glass of water
  • A 2.4 GHz Wi-Fi network
  • Breadboard and jumper wires (ESP32 IoT Starter Kit)

Safety and care

Only the striped part of the sensor goes in the water, never above the line printed on it. Keep the ESP32, the breadboard and the wires dry and away from the glass.

Wiring

Breadboard wiring diagram: Monitor a water level over Wi-Fi
Breadboard view. Check each connection against the wiring table below.
From To
Sensor S ESP32 GPIO 35
Sensor + ESP32 GPIO 32 (powers the sensor only while measuring)
Sensor − GND

Sensor modules from different makers can label and order their pins differently. Always follow the labels printed on your module.

The sketch

Replace YOUR_WIFI_NAME and YOUR_WIFI_PASSWORD with your own network details (2.4 GHz only). Open the Serial Monitor at 115200 baud to see the address, then open it on a phone or computer on the same Wi-Fi.

#include <WiFi.h>
#include <WebServer.h>

const char* WIFI_NAME = "YOUR_WIFI_NAME";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";

const int SENSOR_PIN = 35;
const int POWER_PIN = 32;
int EMPTY = 0;        // reading with the sensor out of the water
int FULL = 1800;      // reading with the stripes fully under water

WebServer server(80);
int lastReading = 0;

int readSensor() {
  digitalWrite(POWER_PIN, HIGH);   // power on only while measuring
  delay(10);
  int value = analogRead(SENSOR_PIN);
  digitalWrite(POWER_PIN, LOW);
  return value;
}

String page() {
  int percent = constrain(map(lastReading, EMPTY, FULL, 0, 100), 0, 100);
  String html = "<!DOCTYPE html><html><head><meta charset='utf-8'>";
  html += "<meta name='viewport' content='width=device-width, initial-scale=1'>";
  html += "<meta http-equiv='refresh' content='3'><title>Water level</title></head>";
  html += "<body style='font-family:sans-serif;padding:16px;text-align:center'><h1>Water level</h1>";
  html += "<p style='font-size:56px;margin:8px'>" + String(percent) + " %</p>";
  html += "<p style='color:#888'>Reading: " + String(lastReading) + "</p></body></html>";
  return html;
}

void setup() {
  Serial.begin(115200);
  pinMode(POWER_PIN, OUTPUT);
  digitalWrite(POWER_PIN, LOW);

  WiFi.begin(WIFI_NAME, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  Serial.print("Open http://");
  Serial.println(WiFi.localIP());

  server.on("/", []() { server.send(200, "text/html", page()); });
  server.begin();
}

void loop() {
  server.handleClient();
  static unsigned long lastMeasure = 0;
  if (millis() - lastMeasure > 2000) {
    lastMeasure = millis();
    lastReading = readSensor();
    Serial.println(lastReading);
  }
}

Calibrate it: note the reading in the Serial Monitor with the sensor dry (EMPTY) and with the stripes fully under water (FULL), then put both numbers in the code and upload again.

How it works

Half of the stripes are connected to power and half to the signal pin. Water conducts electricity, so the deeper the sensor goes, the more current flows between them and the higher the voltage on S. Powering the sensor from GPIO 32 for just 10 ms every two seconds means current flows only briefly. That slows down the corrosion that happens when metal sits in water with electricity running through it.

Try this next

  • Light an LED or sound the buzzer below 20 %.
  • Show a picture of a glass on the page that fills up with the level.
  • Log the level every hour to see how fast the water evaporates.

Troubleshooting

  • The level jumps around: hold the sensor still and straight.
  • It shows 0 % in water: check that + goes to GPIO 32 and S to GPIO 35.
  • Readings drift over days: the stripes corrode; clean them gently, and remember this is a learning project.

Build it yourself

Everything used in this lesson comes in one kit, with parts tested by our engineers.

ESP32 IoT Starter Kit | Arduino IDE Compatible | Free Tutorials $57.00

Shop the kit