HydroView is a water level indicator that uses an HC-SR04 ultrasonic sensor to measure the distance between the water surface and the sensor, then displays the water level on a MAX7219 4-in-1 8×8 LED matrix in a dynamic bar format.The design is perfect for home water tanks, aquaponics setups, or industrial fluid containers.
Instead of relying on blinking LEDs or numeric displays, HydroView provides a real-time, graphical representation of the water level that’s instantly understandable at a glance.
FeaturesNon-contact measurement — Ultrasonic sensing means no physical contact with water.
- Non-contact measurement — Ultrasonic sensing means no physical contact with water.
Real-time visual display — LED matrix bar fills from right to left as the tank fills.
- Real-time visual display — LED matrix bar fills from right to left as the tank fills.
Customizable tank height — Easily set your tank’s depth in centimeters.
- Customizable tank height — Easily set your tank’s depth in centimeters.
Serial debugging — Built-in logging of distance, depth, and display columns.
- Serial debugging — Built-in logging of distance, depth, and display columns.
Scalable — Works with different MAX7219 configurations and display lengths.
- Scalable — Works with different MAX7219 configurations and display lengths.
Component
Quantity
Notes
HC-SR04 Ultrasonic Sensor
1
Measures distance to water surface
MAX7219 4-in-1 LED Matrix (32×8)
1
For graphical display
ESP32-S3 (e.g., Seeed Studio XIAO ESP32-S3)
1
Main microcontroller
Jumper Wires
As needed
Female–female or female–male depending on modules
Breadboard or PCB
Optional
For neat wiring
USB Cable
1
For programming and power
Pin ConnectionsESP32-S3 ↔ MAX7219 (Software SPI)MAX7219 Pin
ESP32-S3 Pin
Code Name
DIN
D10
DATA_PIN
CLK
D8
CLK_PIN
CS
D9
CS_PIN
VCC
5V
—
GND
GND
—
ESP32-S3 ↔ HC-SR04HC-SR04 Pin
ESP32-S3 Pin
Code Name
VCC
5V
—
GND
GND
—
TRIG
D2
TRIG_PIN
ECHO
D3
ECHO_PIN
Working PrincipleThe ESP32-S3 sends a 10µs HIGH pulse to the ultrasonic sensor’s TRIG pin.
- The ESP32-S3 sends a 10µs HIGH pulse to the ultrasonic sensor’s TRIG pin.
The HC-SR04 emits an ultrasonic pulse and waits for it to bounce back.
- The HC-SR04 emits an ultrasonic pulse and waits for it to bounce back.
The ECHO pin outputs the time taken for the echo to return.
- The ECHO pin outputs the time taken for the echo to return.
The ESP32-S3 calculates distance using the speed of sound.
- The ESP32-S3 calculates distance using the speed of sound.
Water depth is calculated as:
waterDepth = tankHeight - measuredDistance
- Water depth is calculated as:
waterDepth = tankHeight - measuredDistance
The water depth is mapped to 0–32 columns of the LED display.
- The water depth is mapped to 0–32 columns of the LED display.
The LED matrix is updated to show the water level, filling right-to-left.
- The LED matrix is updated to show the water level, filling right-to-left.
#include <MD_MAX72xx.h>
#include <SPI.h>
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4 // 4 modules of 8x8 = 32 columns
#define DATA_PIN D10
#define CLK_PIN D8
#define CS_PIN D9
#define TRIG_PIN D2
#define ECHO_PIN D3
// Tank dimensions
#define TANK_HEIGHT_CM 12 // distance from sensor to bottom of tank
// Software SPI constructor (lets you use any pins)
MD_MAX72XX mx = MD_MAX72XX(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);
void setup() {
Serial.begin(115200);
Serial.println("Water Level Indicator Starting...");
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
mx.begin();
mx.clear();
}
long getDistance() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH, 30000); // Timeout 30ms
return duration * 0.034 / 2; // cm
}
void displayLevel(int filledColumns) {
mx.clear();
for (int col = 0; col < filledColumns; col++) {
int actualCol = 31 - col; // Reverse fill
for (int row = 0; row < 8; row++) {
mx.setPoint(row, actualCol, true);
}
}
}
void loop() {
long distance = getDistance();
Serial.print("Raw Distance: ");
Serial.print(distance);
Serial.println(" cm");
if (distance > 0 && distance <= TANK_HEIGHT_CM) {
int waterDepth = TANK_HEIGHT_CM - distance; // water height from bottom
int levelCols = map(waterDepth, 0, TANK_HEIGHT_CM, 0, 32);
Serial.print("Water Depth: ");
Serial.print(waterDepth);
Serial.print(" cm, Columns: ");
Serial.println(levelCols);
displayLevel(levelCols);
} else {
Serial.println("Out of range or no water detected.");
displayLevel(0); // No water or out of range
}
delay(500);
}
CustomizationChange TANK_HEIGHT_CM
to match your tank’s depth.
- Change
TANK_HEIGHT_CM
to match your tank’s depth.
Adjust the delay(500)
in loop()
to update faster or slower.
- Adjust the
delay(500)
inloop()
to update faster or slower.
Change the actualCol
calculation if you want left-to-right fill instead.
- Change the
actualCol
calculation if you want left-to-right fill instead.
Add a buzzer alarm when the water level is too low or too high.
- Add a buzzer alarm when the water level is too low or too high.
Display numeric percentage on an additional OLED screen.
- Display numeric percentage on an additional OLED screen.
Use WiFi or Bluetooth to send water level data to a smartphone.
- Use WiFi or Bluetooth to send water level data to a smartphone.
Add low-power mode for battery operation.
- Add low-power mode for battery operation.
Comments