A rainwater harvesting monitor using an ultrasonic sensor tracks tank water levels in real time, enabling smart overflow management, automated pump control, and conservation analytics. India receives 1,170 mm of annual rainfall on average, yet water scarcity affects 600 million people — because most rainwater runs off uncollected. This guide covers building an automated rainwater tank monitoring system with HC-SR04 ultrasonic sensor, ESP32, and automated pump control.
Table of Contents
- Rainwater Harvesting in India
- Ultrasonic Level Measurement Principle
- Components Required
- Circuit and Wiring
- ESP32 Tank Monitor Code
- Tank Automation Logic
- Multi-Tank and Borewell Integration
- Frequently Asked Questions
Rainwater Harvesting in India
Rainwater harvesting (RWH) is mandatory under building bylaws in many Indian states including Tamil Nadu, Karnataka, Maharashtra, Rajasthan, and Delhi. Common systems include:
- Rooftop collection: 1 mm of rain on 100 sq m roof = 100 litres (minus losses)
- Check dams and farm ponds: Common in Rajasthan, Gujarat, Maharashtra
- Groundwater recharge pits: Percolation-focused, not direct use
- Underground sump tanks: Urban apartments commonly have 10,000-50,000 litre sumps
Without a level monitor, tanks overflow (wasting water) or run dry (pump damage). A Rs 500 ultrasonic sensor + ESP32 system prevents both problems and enables usage analytics.
Ultrasonic Level Measurement Principle
The HC-SR04 ultrasonic sensor emits 40kHz sound pulses. The time for the echo to return is measured and converted to distance:
Distance (cm) = Echo pulse duration (microseconds) / 58
Water level (%) = ((Tank height – Distance) / Tank height) x 100
For outdoor tanks, use the JSN-SR04T waterproof variant — it has the transducer on a separate waterproof probe suitable for submersion in wet environments. Standard HC-SR04 will corrode in tank humidity within weeks.
Components Required
Related Products from Zbotic
- 12V DC Mini Submersible Water Pump — for automated pump-out control
- 5V/12V Relay Control Module — pump automation relay
- Raindrops Detection Sensor Module — detect active rainfall for smart harvesting
Full parts list:
- ESP32 WROOM-32
- JSN-SR04T waterproof ultrasonic sensor
- Rain sensor module (to detect active rainfall)
- 2-channel relay module
- 12V 3A power supply
- Float switch (backup mechanical level sensor)
- LED indicator panel (red/yellow/green for low/medium/full)
- Buzzer (overflow/empty alarm)
- Waterproof project enclosure (IP65)
- Optional: SIM800L GSM module for SMS alerts
Circuit and Wiring
Connections:
- JSN-SR04T TRIG -> GPIO26, ECHO -> GPIO25
- Rain sensor DOUT -> GPIO14 (digital: rain detected)
- Relay IN1 -> GPIO27 (overflow pump / diverter valve)
- Relay IN2 -> GPIO32 (irrigation/supply pump)
- Float switch (NO type) -> GPIO34 (pulled HIGH, LOW = full tank)
- Red LED -> GPIO13, Yellow LED -> GPIO12, Green LED -> GPIO4
- Buzzer -> GPIO5
Mount the ultrasonic sensor inside the tank lid, pointing down at the water surface. Ensure the sensor is at least 20 cm from the tank walls to avoid false reflections (ultrasonic beam angle is 15-30 degrees).
ESP32 Tank Monitor Code
#include <WiFi.h>
#include <WebServer.h>
const char* ssid = "HomeNet";
const char* pass = "yourpassword";
WebServer server(80);
#define TRIG_PIN 26
#define ECHO_PIN 25
#define RAIN_PIN 14
#define PUMP_OVF 27 // Overflow pump
#define PUMP_SUP 32 // Supply pump
// Tank configuration
const float TANK_HEIGHT_CM = 200.0; // Tank depth in cm (sensor to bottom when full)
const float TANK_CAPACITY_L = 5000; // Tank capacity in litres
const float FULL_LEVEL_PCT = 95.0; // Activate overflow pump above this
const float LOW_LEVEL_PCT = 15.0; // Alert when below this
float tankLevel = 0; // Percentage
float tankVolume = 0; // Litres
bool raining = false;
bool overflowActive = false;
float readDistance() {
digitalWrite(TRIG_PIN, LOW); delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long dur = pulseIn(ECHO_PIN, HIGH, 30000);
if (dur == 0) return -1; // No echo
return dur / 58.0; // Distance in cm
}
float calculateLevel() {
float dist = 0;
int valid = 0;
// Average 5 readings for stability
for (int i = 0; i < 5; i++) {
float d = readDistance();
if (d > 0 && d < TANK_HEIGHT_CM + 30) {
dist += d;
valid++;
}
delay(60);
}
if (valid == 0) return -1;
dist /= valid;
// Calculate water level (sensor is at top, water surface below)
float waterDepth = TANK_HEIGHT_CM - dist;
if (waterDepth < 0) waterDepth = 0;
float pct = (waterDepth / TANK_HEIGHT_CM) * 100.0;
return constrain(pct, 0, 100);
}
String getStatusHTML() {
String color = (tankLevel > 70) ? "green" : (tankLevel > 30) ? "orange" : "red";
String html = "HTTP/1.1 200 OKrnContent-Type: text/htmlrnrn";
html = "<!DOCTYPE html><html><head><title>Tank Monitor</title>";
html += "<meta name='viewport' content='width=device-width,initial-scale=1'>";
html += "<meta http-equiv='refresh' content='30'></head><body style='font-family:sans-serif;text-align:center'>";
html += "<h1>Rainwater Tank Monitor</h1>";
html += "<div style='font-size:48px;color:" + color + "'>" + String(tankLevel, 0) + "%</div>";
html += "<p>" + String(tankVolume, 0) + " litres available</p>";
html += "<p>Rain: " + String(raining ? "Yes" : "No") + "</p>";
html += "<p>Overflow pump: " + String(overflowActive ? "ACTIVE" : "Off") + "</p>";
html += "</body></html>";
return html;
}
void setup() {
Serial.begin(115200);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(RAIN_PIN, INPUT_PULLUP);
pinMode(PUMP_OVF, OUTPUT); digitalWrite(PUMP_OVF, HIGH);
pinMode(PUMP_SUP, OUTPUT); digitalWrite(PUMP_SUP, HIGH);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("nIP: " + WiFi.localIP().toString());
server.on("/", []() { server.send(200, "text/html", getStatusHTML()); });
server.begin();
}
void loop() {
server.handleClient();
raining = !digitalRead(RAIN_PIN);
static unsigned long lastRead = 0;
if (millis() - lastRead > 60000) { // Read every minute
lastRead = millis();
tankLevel = calculateLevel();
if (tankLevel < 0) {
Serial.println("Sensor read error");
} else {
tankVolume = (tankLevel / 100.0) * TANK_CAPACITY_L;
// Overflow management
if (tankLevel >= FULL_LEVEL_PCT && !overflowActive) {
digitalWrite(PUMP_OVF, LOW); // Activate overflow pump/valve
overflowActive = true;
Serial.println("OVERFLOW PUMP ON - tank full");
} else if (tankLevel < FULL_LEVEL_PCT - 5 && overflowActive) {
digitalWrite(PUMP_OVF, HIGH);
overflowActive = false;
}
if (tankLevel < LOW_LEVEL_PCT) {
Serial.println("ALERT: Tank low! " + String(tankLevel, 0) + "%");
}
Serial.printf("Level: %.1f%% | Volume: %.0fL | Rain: %sn",
tankLevel, tankVolume, raining ? "Yes" : "No");
}
}
delay(100);
}
Tank Automation Logic
Advanced automation options:
- Rainfall-triggered diverter: For the first 5 minutes of rain (first-flush), divert to drain (roof contaminants). After 5 minutes, switch valve to tank inlet. Reset timer after 2-hour dry period.
- Multi-source management: When rain tank is empty, automatically switch supply pump to borewell. Return to rain tank preference when refilled.
- Time-of-use scheduling: Pump to overhead tank at night (low electricity tariff) using BESCOM/MSEDCL time-of-use rates.
- Daily usage report: Send WhatsApp/SMS with yesterday’s consumption and current level at 7am.
Multi-Tank and Borewell Integration
Typical urban Indian home water system has multiple sources:
- Municipal water connection (intermittent)
- Borewell (ground water)
- Rainwater harvesting tank
- Overhead tank (gravity feed to taps)
The ESP32 system can monitor all three storage tanks with one sensor per tank and automate switching between sources based on availability and priority — reducing borewell dependence by 40-70% in good monsoon years.
Frequently Asked Questions
What accuracy can I expect from an HC-SR04 ultrasonic sensor?
HC-SR04 accuracy is ±3mm in ideal conditions. For a 2-metre tank, this translates to ±0.15% level accuracy — more than sufficient for tank monitoring. Averaging multiple readings reduces noise. Temperature affects sound speed (0.17% per degree C), but for typical 20-40 degree C Indian temperatures, the error is under 2 cm.
How do I prevent the sensor from giving false readings on tank ripples?
Average 5-10 readings taken 100ms apart and discard outliers (readings more than 10 cm from the median). Install the sensor in a protective PVC pipe standpipe inside the tank to reduce ripples from inlet flow. Read sensor only when pump is off for 60 seconds.
Can I monitor tank level when there is no internet or WiFi?
Yes. The ESP32 can display level on an OLED/LCD and drive LED indicators locally without WiFi. For remote alerts without internet, add a SIM800L GSM module for SMS alerts to your phone when the tank is low or full.
What is the typical lifespan of ultrasonic sensors in an outdoor tank environment?
Standard HC-SR04 lasts 6-18 months in humid conditions before corrosion causes failure. JSN-SR04T (waterproof variant) with proper mounting lasts 3-5 years. Annual sensor replacement is a worthwhile investment for continuous monitoring.
Add comment