Table of contents
Abstract
EchoFill is an intelligent, cloud-connected water tank system that utilizes ultrasonic sensing for water-level monitoring and pumping control to avoid overflow, save water, and electricity, and ensure reliable and maintenance-free operation.
Project
Introduction
In most buildings across Bangladesh, there is at least one rooftop water tank that stores daily household water. The tank is filled from a ground reservoir by an electric pump. While the system is simple, filling the tank with water is still handled manually in most homes and apartments, leading to a range of problems, from unnecessary water waste to damaged pumps and wasted electricity. To solve these issues, I developed EchoFill, a fully automated smart water tank management system using ultrasonic sensing and cloud-based control.
The Problem
Traditional water management relies solely on the observation of human beings. Someone needs to check if the rooftop tank is empty before manually switching on the ground pump. When the tank is full, the pump has to be switched off again manually. But in fact, it is an inefficient process on several counts because:
- Often, overflow and wastage occur since people often forget to turn the pump off.
- Continuous overflow may damage walls, ceilings, or the surrounding building structure.
- Dry running of pumps or when the ground tank is empty may cause overheating and damage to the motor.
- Manual management is time-wasting and increases the electricity bill.
These problems are very common in both residential and commercial buildings in Bangladesh.
Why I Made It?
Water is a valuable resource in Bangladesh, a nation with a high population density. I have seen firsthand how much water is wasted due to ordinary human forgetfulness. Every day, water spills over the roofs of many buildings. However, because they are used without adequate supervision, pumps frequently sustain damage early on. These problems stem from a lack of automation.
I wanted to create a solution for the problem for many days, suddenly the challenge came, and I decided to make the system that is:
-
Affordable
-
Easy to install
-
Reliable in Bangladeshi building conditions
-
Independent and cloud-connected
The problem and the contest both motivated me to design a system that can automatically measure water level, send the data to the cloud, and intelligently control the pump.
Benefits of using the system, like EchoFill:
- No more overflowing tanks: The pump automatically turns off when the tank is full.
- Prevents damage to the pump by preventing it from operating when the ground reservoir is empty.
- Conserves water: Significant water waste is decreased.
- Saves electricity by only running the pump when needed.
- Real-time monitoring: Check the water level in the tank from any location.
- Dependable operation: It functions even when the tank and pump units are located far apart.
- Low maintenance: cloud-based logic and basic hardware.
- Perfect for Bangladesh: Designed for standard water systems and building structures.
Components Used in this Project
1. TDK Ultrasonic Sensor, 45° Beam Angle, 74.5 kHz
3. DC 5V 9V 12V UPS Power Supply Module with Lithium Battery Charging & Boost - 18650
6. DFRobot Monocrystalline Solar Panel (5V, 1A)
| {gallery}Components List |
|---|
|
IMAGE TITLE: TDK Ultrasonic Sensor |
|
IMAGE TITLE: Wemos D1 Mini |
|
IMAGE TITLE: 18650 UPS Module |
|
IMAGE TITLE: MT3608 Boost Module |
|
IMAGE TITLE: 18650 Li-ion Battery
DFRobot Solar Panel |
Hardware Design
The hardware system for EchoFill is built around an ESP8266-based Wemos D1 Mini powered by a single 18650 Li-ion battery for continuous operation in rooftop environments. A mini-UPS charging module is utilized to not only raise this from the 3.7 V of the battery to a stable 5 V for the Wemos board, but simultaneously charge the battery from a regulated 5 V solar panel (DFRobot 5 V, 1 A). Two TDK ultrasonic sensors are used to measure the water level of the tank, requiring each 12 V supplied with an MT3608 boost converter stepping up the output 5 V of the UPS module to 12 V. The Wemos D1 Mini reads the ultrasonic sensors for water level, calculates the water level in the tank, and publishes data to the cloud. A separate pump-controller unit gets this cloud data and automatically controls the water pump. All electronics (except the solar panel) are contained inside a small 3D-printed enclosure designed for outdoor mounting on the rooftop.
The following image shows the block diagram of the system.

Hardware Connection Diagram

To protect the hardware components, a 3D-printed enclosure was designed, as shown in the following images.


Hardware Connection & Assembly
After printing the 3D case, I first add the sensor units in the case using the washers and gaskets that came with the sensors.




Then, I soldered the MT3608 boost converter module with the UPS module as shown in the following image:

Then I connected the boost converter output to the power supply pin of the sensors.

After connecting the sensors, I attached the pre-prepared UPS module (Forum Post #5) inside the case using M3 screws.


Then I plugged the sensor connection cables into the attached sensor.

I placed the ESP8266 board and the boost converter module inside the case.


The final unit, after placing the top cover, looks as follows.


Attaching The Solar Panel
After making the sensor unit ready, the next step is to connect it to the power source (solar panel) and check that everything is working perfectly. I attached the panel with the sensor unit using a micro USB cable as shown in the image below.

The LED lights up when I face the solar panel toward the sun.

The final assembly of my project is as follows:

The next step is to install the system in the water tank. I am still waiting for permission from the building authority to install it on the rooftop water tank for practical testing and data.
Developing and Uploading Code
The ESP8266 reads the water-tank distance using two TDK ultrasonic sensors and processes the data for a stable water-level percentage. In each cycle, the readings from the two sensors are averaged, and the output is fed to a 5-sample rolling average to remove the noise. The resulting output is scaled to a water level reading where 200 cm corresponds to 0% and 20 cm to 100%. To further smooth out sudden fluctuations, the level is passed through an exponential smoothing filter.
After the computation of the final percentage, it connects to WiFi and sends this value to a Firebase Realtime Database. To minimize power consumption, the ESP8266 enters deep-sleep mode; the system wakes up automatically every 60 seconds, makes a measurement, uploads data, and goes back to sleep. This approach provides for accurate readings and long battery life, thus making the system suitable for continuous outdoor or remote operation.
#include <TDK_USSM.h>
#include <ESP8266WiFi.h>
#include <Firebase_ESP_Client.h>
// ----------------------------------------------
// Ultrasonic Sensor Configuration
// ----------------------------------------------
#define N_SENSORS 2
const int IoPins[N_SENSORS] = {4, 5}; // D2 & D1 on Wemos D1 Mini
TDK_USSM TdkUssm(IoPins, N_SENSORS);
// ----------------------------------------------
// Firebase Realtime Database Configuration
// ----------------------------------------------
#define FIREBASE_HOST "YOUR_PROJECT.firebaseio.com" // e.g. mytank.firebaseio.com
#define FIREBASE_AUTH "YOUR_DATABASE_SECRET" // legacy token
FirebaseConfig config;
FirebaseAuth auth;
FirebaseData fbData;
// ----------------------------------------------
// WiFi Credentials
// ----------------------------------------------
const char* ssid = "YOUR_WIFI_NAME";
const char* password = "YOUR_WIFI_PASSWORD";
// ----------------------------------------------
// Smoothing Variables
// ----------------------------------------------
float smoothingFactor = 0.3; // 0.1 = very smooth, 0.3 = good balance
float smoothedLevel = 0;
// ----------------------------------------------
// Convert distance to water level percentage
// 200 cm → 0%
// 20 cm → 100%
// ----------------------------------------------
float distanceToLevel(float dist) {
float level = (200.0 - dist) * (100.0 / (200.0 - 20.0));
return constrain(level, 0, 100);
}
// ----------------------------------------------
// Read and average both ultrasonic sensors
// ----------------------------------------------
float avgTwoSensors() {
float s1 = TdkUssm.GetDistanceCm(0);
float s2 = TdkUssm.GetDistanceCm(1);
return (s1 + s2) / 2.0;
}
// ----------------------------------------------
// Setup (Runs Once After Deep Sleep Wake)
// ----------------------------------------------
void setup() {
Serial.begin(115200);
delay(200);
// ----------------------------------------------
// Connect WiFi (fast timeout for power saving)
// ----------------------------------------------
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
unsigned long wifiStart = millis();
while (WiFi.status() != WL_CONNECTED && millis() - wifiStart < 8000) {
delay(100);
}
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi failed → going to sleep");
ESP.deepSleep(60e6); // Sleep for 60 seconds
return;
}
Serial.println("WiFi connected!");
// ----------------------------------------------
// Initialize Firebase
// ----------------------------------------------
config.host = FIREBASE_HOST;
config.signer.tokens.legacy_token = FIREBASE_AUTH;
Firebase.begin(&config, &auth);
Firebase.reconnectWiFi(true);
// ----------------------------------------------
// Read Sensors
// ----------------------------------------------
float avgDist = avgTwoSensors();
// Convert to water level %
float level = distanceToLevel(avgDist);
// First-run initialization
if (smoothedLevel == 0) smoothedLevel = level;
// Exponential smoothing
smoothedLevel = (smoothingFactor * level) +
((1 - smoothingFactor) * smoothedLevel);
// Debug print
Serial.print("Distance Avg = ");
Serial.print(avgDist);
Serial.print(" cm Water Level Smoothed = ");
Serial.print(smoothedLevel);
Serial.println("%");
// ----------------------------------------------
// Upload to Firebase
// ----------------------------------------------
if (Firebase.RTDB.setFloat(&fbData, "/tank/water_level", smoothedLevel)) {
Serial.println("Firebase upload OK");
} else {
Serial.println(fbData.errorReason());
}
// ----------------------------------------------
// Deep Sleep
// ----------------------------------------------
Serial.println("Going to deep sleep for 60 seconds...");
ESP.deepSleep(60e6); // 60 seconds
}
void loop() {
// Will never run. ESP resets after wake.
}
Firebase Configuration
I created a new project named "EchoFill" from https://console.firebase.google.com/ and created a real-time database from the Build tab.

After a successful connection data will be uploaded to the Firebase every minute.

The next step
The next step is to design a pump unit that will receive the update from the Firebase and control the pump. Due to time limitations, I could not make that unit.
Attachments
top_cover.stlcase.stl
References
1. Unboxing TDK Ultrasonic Sensor Kit (EcoFill #1)
2. Testing the Range & Accuracy of TDK USSM Sensor (EchoFill #2)
3. Measuring Water Level (EchoFill #3)
4. Interfacing TDK Ultrasonic Sensor with ESP8266 Board (EchoFill #4)
5. Power Management (EchoFill #5)
6. TDK Ultrasonic Sensor Module
7. TDK Ultrasonic Sensor Demo Kit





