#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h>
#include <WebServer.h>
#include <Ultrasonic.h>
#include <Servo.h> // Use ServoESP32 (not the default Servo library)
// WiFi credentials
const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";
// Pin assignments
const int relayPin = 23; // Relay control pin
const int trigPin = 19; // Ultrasonic trig pin
const int echoPin = 18; // Ultrasonic echo pin
const int servoPin = 17; // Servo control pin
// Initialize objects
LiquidCrystal_I2C lcd(0x3F, 16, 2); // I2C LCD
Ultrasonic ultrasonic(trigPin, echoPin); // Ultrasonic sensor
Servo valveServo; // Servo motor for valve control
WebServer server(80); // Web server for ESP32
void setup() {
// Initialize the relay and servo
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, LOW); // Initially close the water tap (valve)
valveServo.attach(servoPin); // Attach servo to the specified pin
valveServo.write(0); // Initialize servo to 0 degrees (closed)
// Initialize LCD
lcd.begin(16, 2);
lcd.print("Water Flow Control");
delay(1000);
lcd.clear();
// Connect to Wi-Fi
lcd.print("Connecting to WiFi...");
WiFi.begin(ssid, password);
// Wait until connected
int wifiAttempts = 0;
while (WiFi.status() != WL_CONNECTED && wifiAttempts < 20) {
delay(500);
lcd.print("Connecting...");
wifiAttempts++;
}
if (WiFi.status() == WL_CONNECTED) {
lcd.clear();
lcd.print("Connected to WiFi");
lcd.setCursor(0, 1);
lcd.print(WiFi.localIP());
} else {
lcd.clear();
lcd.print("WiFi Failed");
return;
}
// Setup the web server routes
server.on("/", HTTP_GET, handleHome);
server.on("/open", HTTP_GET, openTap);
server.on("/close", HTTP_GET, closeTap);
server.on("/control", HTTP_GET, handleControl);
// Start the web server
server.begin();
}
void loop() {
server.handleClient(); // Handle HTTP requests
// Measure distance (water level) and display it on LCD
long distance = ultrasonic.read(); // Measure distance (water level)
if (distance > 0) { // Only update if the distance is valid
lcd.setCursor(0, 1);
lcd.print("Level: ");
lcd.print(distance);
lcd.print(" cm");
// Automatic tap control based on water level (distance)
if (distance > 100) { // If distance > 100 cm (low level), open the tap
openTap();
} else { // If distance <= 100 cm (high level), close the tap
closeTap();
}
} else {
lcd.setCursor(0, 1);
lcd.print("Sensor Error");
}
delay(1000); // Delay for a second before taking the next measurement
}
void handleHome() {
String html = "<html><body><h1>Water Flow Control</h1>";
html += "<p><a href='/open'><button>Open Tap</button></a></p>";
html += "<p><a href='/close'><button>Close Tap</button></a></p>";
html += "<p><a href='/control'><button>Automatic Control</button></a></p>";
html += "</body></html>";
server.send(200, "text/html", html);
}
void openTap() {
digitalWrite(relayPin, HIGH); // Open the solenoid valve
valveServo.write(90); // Open the valve using the servo motor (90 degrees)
lcd.clear();
lcd.print("Water Tap: Opened");
server.send(200, "text/html", "<html><body><h1>Tap Opened!</h1><a href='/'>Go Back</a></body></html>");
}
void closeTap() {
digitalWrite(relayPin, LOW); // Close the solenoid valve
valveServo.write(0); // Close the valve using the servo motor (0 degrees)
lcd.clear();
lcd.print("Water Tap: Closed");
server.send(200, "text/html", "<html><body><h1>Tap Closed!</h1><a href='/'>Go Back</a></body></html>");
}
void handleControl() {
// Measure distance for control page
long distance = ultrasonic.read(); // Measure distance (water level)
if (distance > 0) {
String html = "<html><body><h1>Water Flow Control</h1>";
html += "<p>Current Water Level: ";
html += distance;
html += " cm</p>";
html += "<p><a href='/open'><button>Open Tap</button></a></p>";
html += "<p><a href='/close'><button>Close Tap</button></a></p>";
html += "</body></html>";
server.send(200, "text/html", html);
} else {
String html = "<html><body><h1>Sensor Error</h1><p>Unable to read water level.</p><a href='/'>Go Back</a></body></html>";
server.send(500, "text/html", html);
}
}