#include <EEPROM.h>
#include <LiquidCrystal.h>
// Initialize the LCD with the pins you specified
LiquidCrystal lcd_1(33, 25, 26, 27, 14, 12);
// Pin assignments
const int trigPin = 23;
const int echoPin = 22;
const int relayPin = 19;
const int modeButtonPin = 5; // Use this button to toggle between manual/auto modes
const int pumpButtonPin = 17; // Use this button to turn the pump on/off in manual mode
const int buzzerPin = 21; // GPIO 21 for Buzzer
long duration;
int distance;
int setLevel;
bool pumpState = false; // False = OFF, True = ON
bool manualMode = false;
bool pumpButtonPressed = false;
bool modeButtonPressed = false;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50; // Debounce delay to avoid false triggers
void setup()
{
// Set up the LCD's number of columns and rows:
lcd_1.begin(16, 2);
// Print initial messages to the LCD.
lcd_1.print("WATER LEVEL: ");
lcd_1.setCursor(0, 1);
lcd_1.print("PUMP: OFF");
// Initialize pin modes
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(relayPin, OUTPUT);
pinMode(modeButtonPin, INPUT_PULLUP); // Button for mode toggle (Manual/Auto)
pinMode(pumpButtonPin, INPUT_PULLUP); // Button for pump control in manual mode
pinMode(buzzerPin, OUTPUT); // Buzzer output
// Load the stored set level from EEPROM (maximum distance when tank is empty)
setLevel = EEPROM.read(0);
if (setLevel > 400 || setLevel < 15) setLevel = 400; // Ensure valid range (15 cm as empty)
}
void loop()
{
// Check the mode toggle button with debouncing
if (digitalRead(modeButtonPin) == LOW && (millis() - lastDebounceTime) > debounceDelay)
{
lastDebounceTime = millis(); // Reset the debounce timer
modeButtonPressed = !modeButtonPressed; // Toggle the button press state
manualMode = !manualMode; // Toggle the mode between Manual and Auto
}
// Read the pump control button in manual mode
if (digitalRead(pumpButtonPin) == LOW && !pumpButtonPressed)
{
pumpButtonPressed = true;
if (manualMode)
{
pumpState = !pumpState; // Toggle the pump state only in manual mode
}
}
if (digitalRead(pumpButtonPin) == HIGH)
{
pumpButtonPressed = false; // Reset button press flag when released
}
// Measure the current distance
int currentDistance = measureDistance();
// Calculate the percentage of water level based on distance
int percentage = map(currentDistance, setLevel, 2, 0, 100); // Empty tank is at setLevel distance
if (percentage < 0) percentage = 0;
if (percentage > 100) percentage = 100;
// Update the LCD with the current water level percentage
lcd_1.setCursor(13, 0);
lcd_1.print(percentage);
lcd_1.print("% ");
// Automatic control based on water level percentage (only in auto mode)
if (!manualMode)
{
if (percentage < 30) pumpState = true; // Turn pump ON if water is below 30%
if (percentage >= 95) pumpState = false; // Turn pump OFF if water is above 95%
}
// Control the relay (pump) based on the pump state
// If relay is active-low, reverse the logic
digitalWrite(relayPin, pumpState ? HIGH : LOW); // LOW turns ON the pump, HIGH turns it OFF
// Control the buzzer for low water levels (below 30%)
if (percentage < 30)
{
digitalWrite(buzzerPin, HIGH); // Buzzer ON when water level is low
}
else
{
digitalWrite(buzzerPin, LOW); // Buzzer OFF
}
// Update the LCD with the current pump status
lcd_1.setCursor(6, 1);
if (pumpState) lcd_1.print("ON ");
else lcd_1.print("OFF");
// Display the current mode (Manual/Auto)
lcd_1.setCursor(10, 1);
if (manualMode) lcd_1.print("MANUAL ");
else lcd_1.print("AUTO ");
delay(500); // Small delay for stability
}
// Function to measure distance using the ultrasonic sensor
int measureDistance()
{
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
return duration * 0.034 / 2;
}