#include <WiFi.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
const char* ssid = "Wokwi-GUEST"; // Replace with your Wi-Fi SSID
const char* password = ""; // Replace with your Wi-Fi password
const int triggerPin = 23; // Use GPIO 23 as the trigger pin
const int echoPin = 18; // Use GPIO 18 as the echo pin
const int buzzerPin = 13; // Use GPIO 13 for the buzzer
const int pushButtonIncrementPin = 12; // Use GPIO 12 for the push button (increment)
const int pushButtonDecrementPin = 14; // Use GPIO 14 for the push button (decrement)
#define PIN_LED_1 2 // Use GPIO 34 for the LED indicator
// Define sound speed in cm/uS
#define SOUND_SPEED 0.034
LiquidCrystal_I2C LCD = LiquidCrystal_I2C(0x27, 20, 4);
int thresholdValue = 10; // Initial threshold value set to 10 cm
int distanceInt = 0; // Declare the distanceInt variable at the beginning of the code
unsigned long lastIncrementTime = 0; // Last time increment button was pressed
unsigned long lastDecrementTime = 0; // Last time decrement button was pressed
unsigned long debounceDelay = 200; // Debounce delay in milliseconds
unsigned long measurementInterval = 500; // Measurement interval in milliseconds
unsigned long previousMeasurementTime = 0; // Last time distance was measured
bool ledState = LOW; // Store the current state of the LED
void setup() {
Serial.begin(115200);
LCD.init();
LCD.backlight();
LCD.begin(20, 4); // Initialize the LCD with 20x4 characters
LCD.setCursor(0, 0);
LCD.print("Water level");
LCD.setCursor(0, 1);
LCD.print("Detection System");
LCD.setCursor(0, 2);
LCD.print("by. aviano88");
LCD.setCursor(0, 3);
LCD.print("Initializing...");
delay(2000);
// Connect to Wi-Fi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
LCD.clear(); // Clear the LCD display
LCD.setCursor(1, 1);
LCD.print("Connected to WiFi");
delay(3000);
}
pinMode(triggerPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(buzzerPin, OUTPUT);
pinMode(PIN_LED_1, OUTPUT);
pinMode(pushButtonIncrementPin, INPUT_PULLUP); // Use internal pull-up resistor for the push button (increment)
pinMode(pushButtonDecrementPin, INPUT_PULLUP); // Use internal pull-up resistor for the push button (decrement)
LCD.clear(); // Clear the LCD display
LCD.setCursor(1, 0);
LCD.print("IP : ");
LCD.print(WiFi.localIP());
LCD.setCursor(1, 1);
LCD.print("Water Level: ");
LCD.setCursor(1, 2);
LCD.print("Threshold : ");
LCD.print(thresholdValue);
LCD.print(" cm");
}
void loop() {
unsigned long currentMillis = millis();
// Measure the distance and update the LCD
if (currentMillis - previousMeasurementTime >= measurementInterval) {
previousMeasurementTime = currentMillis;
detection();
}
// Check for button presses
checkIncrementButton();
checkDecrementButton();
// Control the LED based on the water level
controlLED();
}
void detection() {
// Clears the trigPin
digitalWrite(triggerPin, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 microseconds
digitalWrite(triggerPin, HIGH);
delayMicroseconds(10);
digitalWrite(triggerPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
long duration = pulseIn(echoPin, HIGH);
// Calculate the distance
float distanceCm = (duration * SOUND_SPEED / 2) + 0.15;
// Convert distanceCm to an integer for display
int newDistanceInt = static_cast<int>(distanceCm);
// Update the water level reading on the LCD if the distance has changed
if (newDistanceInt != distanceInt) {
distanceInt = newDistanceInt;
LCD.setCursor(14, 1);
LCD.print(" "); // Clear previous readings
LCD.setCursor(14, 1);
LCD.print(distanceInt); // Print the distance in centimeters as an integer
LCD.print(" cm");
}
// Check if the water level is above the threshold
if (distanceInt >= thresholdValue) {
LCD.setCursor(1, 3);
LCD.print("Status : Flooding");
alarm(); // Turn on the buzzer if the water level is above or equal to the threshold
} else {
LCD.setCursor(1, 3);
LCD.print("Status : Normal ");
noTone(buzzerPin); // Turn off the buzzer if the water level is below the threshold
}
// Print the water level to the Serial Monitor
Serial.print("Water Level: ");
Serial.print(distanceInt);
Serial.println(" cm");
}
void alarm() {
// Turn on the buzzer
tone(buzzerPin, 450, 500);
}
void checkIncrementButton() {
// Read the state of the increment push button
int incrementButtonState = digitalRead(pushButtonIncrementPin);
// If the increment push button is pressed and debounce time has passed
if (incrementButtonState == LOW && millis() - lastIncrementTime > debounceDelay) {
lastIncrementTime = millis(); // Update the last press time
thresholdValue += 5;
// Update the threshold value on the LCD
LCD.setCursor(13, 2);
LCD.print(" "); // Clear previous value
LCD.setCursor(13, 2);
LCD.print(thresholdValue);
LCD.print(" cm");
// Print the updated threshold to the Serial Monitor
Serial.print("Threshold increased to: ");
Serial.print(thresholdValue);
Serial.println(" cm");
}
}
void checkDecrementButton() {
// Read the state of the decrement push button
int decrementButtonState = digitalRead(pushButtonDecrementPin);
// If the decrement push button is pressed and debounce time has passed
if (decrementButtonState == LOW && millis() - lastDecrementTime > debounceDelay) {
lastDecrementTime = millis(); // Update the last press time
thresholdValue -= 5;
// Update the threshold value on the LCD
LCD.setCursor(13, 2);
LCD.print(" "); // Clear previous value
LCD.setCursor(13, 2);
LCD.print(thresholdValue);
LCD.print(" cm");
// Print the updated threshold to the Serial Monitor
Serial.print("Threshold decreased to: ");
Serial.print(thresholdValue);
Serial.println(" cm");
}
}
void controlLED() {
// Control the LED based on the water level
if (distanceInt >= 5) {
if (ledState != HIGH) {
digitalWrite(PIN_LED_1, HIGH); // Turn on the LED if the water level is above or equal to 5 cm
ledState = HIGH;
}
} else {
if (ledState != LOW) {
digitalWrite(PIN_LED_1, LOW); // Turn off the LED if the water level is below 5 cm
ledState = LOW;
}
}
}
void printWiFiIP() {
LCD.setCursor(12, 1);
LCD.print(" "); // Clear previous IP address
LCD.setCursor(12, 1);
LCD.print("IP: ");
LCD.print(WiFi.localIP());
}