#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
// Use the correct I2C address found by the I2C scanner
LiquidCrystal_I2C lcd(0x27, 16, 2);
Servo myServo;
// Declare variables for the ultrasonic sensor readings and calculations
long duration, inches;
int set_val, percentage;
bool state, pump, buttonPressed;
bool servoOpen = false; // Track the state of the servo (open or closed)
const int servoPin = 14; // Pin for the servo motor
const int buttonPin = 15; // Pin for the button
void setup() {
Serial.begin(9600);
Serial.println("Initializing...");
// Initialize the LCD and display initial messages
lcd.begin(16, 2); // Correctly initialize the LCD with columns and rows
lcd.backlight();
lcd.print("WATER LEVEL:");
lcd.setCursor(0, 1);
lcd.print("PUMP:OFF MANUAL");
// Set pin modes for the ultrasonic sensor, button, and pump control
pinMode(8, OUTPUT); // Trigger pin for ultrasonic sensor
pinMode(9, INPUT); // Echo pin for ultrasonic sensor
pinMode(10, INPUT_PULLUP); // Button to set the water level (pull-up resistor)
pinMode(11, INPUT_PULLUP); // Button to switch between manual and automatic mode (pull-up resistor)
pinMode(12, OUTPUT); // Pump control pin
pinMode(buttonPin, INPUT_PULLUP); // Button input with pull-up resistor
// Attach the servo motor to the specified pin
myServo.attach(servoPin);
// Read the previously saved water level set value from EEPROM
set_val = EEPROM.read(0);
if (set_val > 150) set_val = 150; // Cap the set value at 150
Serial.println("Setup complete");
}
void loop() {
// Trigger the ultrasonic sensor to take a reading
digitalWrite(8, LOW); // Ensure the trigger pin is low
delayMicroseconds(2);
digitalWrite(8, HIGH); // Send a 10 microsecond pulse to the trigger pin
delayMicroseconds(10);
digitalWrite(8, LOW);
// Measure the duration of the pulse
duration = pulseIn(9, HIGH);
// Convert the duration to distance in inches
inches = microsecondsToInches(duration);
// Calculate the water level percentage
percentage = (set_val - inches) * 100 / set_val;
// Display the water level percentage on the LCD
lcd.setCursor(12, 0);
if (percentage < 0) percentage = 0;
lcd.print(percentage);
lcd.print("% ");
// Control the pump based on the water level percentage and mode
if (percentage < 30 && digitalRead(11)) pump = 1;
if (percentage > 99) pump = 0;
digitalWrite(12, !pump); // Invert the pump control signal
// Display the pump state (ON/OFF) on the LCD
lcd.setCursor(5, 1);
if (pump == 1) lcd.print("ON ");
else if (pump == 0) lcd.print("OFF");
// Display the control mode (MANUAL/AUTO) on the LCD
lcd.setCursor(9, 1);
if (!digitalRead(11)) lcd.print("MANUAL");
else lcd.print("AUTO ");
// Set the water level if the set button is pressed and in automatic mode
if (!digitalRead(10) && !state && digitalRead(11)) {
state = 1;
set_val = inches;
EEPROM.write(0, set_val);
}
// Toggle the pump if the set button is pressed and in manual mode
if (!digitalRead(10) && !state && !digitalRead(11)) {
state = 1;
pump = !pump;
}
// Reset the state if the set button is released
if (digitalRead(10)) state = 0;
// Toggle the servo state when the button is pressed
if (digitalRead(buttonPin) == LOW && !buttonPressed) {
buttonPressed = true; // Set button pressed state
if (servoOpen) {
myServo.write(0); // Close the servo
servoOpen = false; // Update the servo state
} else {
myServo.write(90); // Open the servo
servoOpen = true; // Update the servo state
}
}
// Reset button state if released
if (digitalRead(buttonPin) == HIGH) {
buttonPressed = false;
}
}
// Convert microseconds to distance in inches for the ultrasonic sensor
long microsecondsToInches(long microseconds) {
return microseconds / 74 / 2;
}