#include <WiFi.h>
#include <WebServer.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Ultrasonic sensor pins
#define TRIG_PIN 5
#define ECHO_PIN 18
// LED pins
#define RED_LED 23
#define YELLOW_LED 22
#define GREEN_LED 21
// Tank dimensions (adjust)
const int TANK_HEIGHT = 30; // cm
// Wi-Fi credentials
const char* ssid = "Wokwi-GUEST"; // Wokwi simulation WiFi
const char* password = "";
// Web server on port 80
WebServer server(80);
// LCD setup (I2C address 0x27 is most common, change to 0x3F if needed)
LiquidCrystal_I2C lcd(0x27, 16, 2);
long readUltrasonicDistance() {
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
long duration = pulseIn(ECHO_PIN, HIGH);
long distance = duration * 0.034 / 2; // cm
return distance;
}
void handleRoot() {
long distance = readUltrasonicDistance();
int waterLevel = TANK_HEIGHT - distance;
if (waterLevel < 0) waterLevel = 0;
int percent = (waterLevel * 100) / TANK_HEIGHT;
String html = "<!DOCTYPE html><html><head><meta name='viewport' content='width=device-width, initial-scale=1'>";
html += "<style>body{font-family:Arial;text-align:center;} .level{font-size:24px;}</style></head><body>";
html += "<h1>ESP32 Water Level Indicator</h1>";
html += "<p class='level'>Water Level: " + String(waterLevel) + " cm</p>";
html += "<p>Tank Capacity: " + String(percent) + "%</p>";
html += "</body></html>";
server.send(200, "text/html", html);
}
void updateLEDs(int percent) {
if (percent <= 20) { // Low level
digitalWrite(RED_LED, HIGH);
digitalWrite(YELLOW_LED, LOW);
digitalWrite(GREEN_LED, LOW);
} else if (percent > 20 && percent < 80) { // Medium level
digitalWrite(RED_LED, LOW);
digitalWrite(YELLOW_LED, HIGH);
digitalWrite(GREEN_LED, LOW);
} else { // Full level
digitalWrite(RED_LED, LOW);
digitalWrite(YELLOW_LED, LOW);
digitalWrite(GREEN_LED, HIGH);
}
}
void setup() {
Serial.begin(115200);
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(RED_LED, OUTPUT);
pinMode(YELLOW_LED, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
// LCD setup
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Connecting WiFi");
// Wi-Fi setup
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected to WiFi");
Serial.println(WiFi.localIP());
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("WiFi Connected");
lcd.setCursor(0, 1);
lcd.print(WiFi.localIP());
// Start server
server.on("/", handleRoot);
server.begin();
}
void loop() {
server.handleClient();
// Measure water level
long distance = readUltrasonicDistance();
int waterLevel = TANK_HEIGHT - distance;
if (waterLevel < 0) waterLevel = 0;
int percent = (waterLevel * 100) / TANK_HEIGHT;
// Update LEDs
updateLEDs(percent);
// Update LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Level:");
lcd.print(waterLevel);
lcd.print("cm");
lcd.setCursor(0, 1);
lcd.print("Tank:");
lcd.print(percent);
lcd.print("%");
// Debug output
Serial.print("Water Level: ");
Serial.print(waterLevel);
Serial.print(" cm (");
Serial.print(percent);
Serial.println("%)");
delay(2000);
}