// ============================================================
// SMART DRAINAGE SYSTEM - ESP32
// FEATURES: Self-Correction (Moving Average) + Adaptive Sampling
// ============================================================
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <HTTPClient.h>
// LCD Setup
LiquidCrystal_I2C lcd(0x27, 16, 2);
// WiFi Configuration
const char* ssid = "YOUR_WIFI_NAME";
const char* password = "YOUR_WIFI_PASSWORD";
// ThingSpeak Configuration
String thingspeakKey = "YOUR_WRITE_API_KEY";
String server = "http://api.thingspeak.com/update";
// Ultrasonic pins - Reverting to ESP32 GPIOs
#define TRIG_PIN 5 // GPIO 5
#define ECHO_PIN 18 // GPIO 18
// Thresholds [cite: 26]
#define SAFE_DISTANCE 150
#define WARNING_DISTANCE 50
// Location [cite: 28]
float manholeLat = 12.9716;
float manholeLon = 77.5946;
// Variables
float distance_cm;
float readings[3] = {150.0, 150.0, 150.0}; // Array for Self-Correction
int readIndex = 0;
bool alertSent = false;
unsigned long lastSend = 0;
int statusCode = 0;
int samplingInterval = 10000;
void setup() {
Serial.begin(115200);
// LCD Init
lcd.init();
lcd.backlight();
lcd.clear();
lcd.print("Smart Drainage");
lcd.setCursor(0, 1);
lcd.print("Booting...");
// WiFi Connection
int attempts = 0;
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED && attempts < 15) {
delay(500);
Serial.print(".");
attempts++;
}
lcd.clear();
if (WiFi.status() == WL_CONNECTED) {
lcd.print("WiFi OK!");
Serial.println("\nWiFi Connected!");
} else {
lcd.print("WiFi Failed!");
}
delay(2000);
// Ultrasonic Sensor Setup
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
lcd.clear();
lcd.print("System Ready");
delay(1000);
}
void loop() {
// ----- 1. READ SENSOR -----
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH, 30000);
float currentReading;
if (duration == 0) {
currentReading = 2.0; // Fail-safe for submerged sensor
} else {
currentReading = (duration * 0.0343) / 2;
}
// ----- 2. SELF-CORRECTION (Moving Average) -----
readings[readIndex] = currentReading;
readIndex = (readIndex + 1) % 3;
float total = 0;
for (int i = 0; i < 3; i++) {
total += readings[i];
}
distance_cm = total / 3;
// ----- 3. STATUS & ADAPTIVE SAMPLING -----
String status = "";
if (distance_cm > SAFE_DISTANCE) {
status = "SAFE";
statusCode = 0;
alertSent = false;
samplingInterval = 10000; // Normal Mode
}
else if (distance_cm >= WARNING_DISTANCE && distance_cm <= SAFE_DISTANCE) {
status = "WARNING";
statusCode = 1;
alertSent = false;
samplingInterval = 2000; // Burst Mode
}
else if (distance_cm < WARNING_DISTANCE) {
status = "CRITICAL!";
statusCode = 2;
samplingInterval = 2000; // Burst Mode
if (!alertSent) {
sendToThingSpeak(true);
alertSent = true;
}
}
// ----- 4. DISPLAY & LOG -----
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Dist: ");
lcd.print(distance_cm, 0);
lcd.print(" cm");
lcd.setCursor(0, 1);
lcd.print(status);
if (samplingInterval < 5000) {
lcd.setCursor(12, 1);
lcd.print("FAST");
}
Serial.print("Avg Dist: "); Serial.print(distance_cm);
Serial.print(" | Interval: "); Serial.println(samplingInterval);
// Periodic ThingSpeak Update
if (millis() - lastSend > 20000) {
sendToThingSpeak(false);
lastSend = millis();
}
delay(samplingInterval);
}
void sendToThingSpeak(bool isAlert) {
if (WiFi.status() != WL_CONNECTED) return;
String url = server + "?api_key=" + thingspeakKey +
"&field1=" + String(distance_cm, 0) +
"&field2=" + String(statusCode) +
"&field3=" + String(isAlert ? 1 : 0) +
"&field4=" + String(manholeLat, 4) +
"&field5=" + String(manholeLon, 4);
HTTPClient http;
http.begin(url);
int httpCode = http.GET();
http.end();
}