#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#define TRIGGER_PIN 12
#define ECHO_PIN 14
#define RELAY_PIN 13
#define BUZZER_PIN 27
#define LCD_ADDRESS 0x27
#define LCD_COLUMNS 16
#define LCD_ROWS 2
#define OK_BUTTON_PIN 4
#define OK_BUTTON_LONG_PRESS_DURATION 2000 // 2 seconds in milliseconds
#define UP_BUTTON_PIN 2
#define DOWN_BUTTON_PIN 0
#define EEPROM_MODE_ADDRESS 0
#define EEPROM_TANK_HEIGHT_ADDRESS 1
#define EEPROM_HIGH_VALUE_ADDRESS 2
#define EEPROM_LOW_VALUE_ADDRESS 3
LiquidCrystal_I2C lcd(LCD_ADDRESS, LCD_COLUMNS, LCD_ROWS);
int mode; // 0 for auto, 1 for manual
int tankHeight = 0; // Default tank height
int highValue = 80; // Default high value
int lowValue = 5; // Default low value
enum MenuItem {
MODE,
TANK_HEIGHT,
HIGH_VALUE,
LOW_VALUE
};
int selectedMenuItem = MODE;
bool inMenu = false;
unsigned long okButtonPressedTime = 0;
void setup() {
pinMode(TRIGGER_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(RELAY_PIN, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(OK_BUTTON_PIN, INPUT_PULLUP); // Assuming the button is active low
pinMode(UP_BUTTON_PIN, INPUT_PULLUP); // Assuming the button is active low
pinMode(DOWN_BUTTON_PIN, INPUT_PULLUP); // Assuming the button is active low
lcd.init();
lcd.backlight();
lcd.clear();
// Load settings from EEPROM
mode = EEPROM.read(EEPROM_MODE_ADDRESS);
tankHeight = EEPROM.read(EEPROM_TANK_HEIGHT_ADDRESS);
highValue = EEPROM.read(EEPROM_HIGH_VALUE_ADDRESS);
lowValue = EEPROM.read(EEPROM_LOW_VALUE_ADDRESS);
// Display initial water level
displayWaterLevel(50); // Example water level, replace with actual measurement
}
void loop() {
// Measure water level and display if not in menu
if (!inMenu) {
float distance = measureDistance();
int waterLevel = map(distance, 5, 80, 0, 100); // Assuming water levels are between 5 and 80 cm
waterLevel = constrain(waterLevel, 0, 100); // Ensure water level stays within range
displayWaterLevel(waterLevel);
}
// Check for long press on OK button to enter menu
if (!inMenu && digitalRead(OK_BUTTON_PIN) == LOW) {
unsigned long currentTime = millis();
if (currentTime - okButtonPressedTime >= OK_BUTTON_LONG_PRESS_DURATION) {
okButtonPressedTime = currentTime;
enterMenu();
}
}
// Check for navigation buttons press
if (inMenu) {
if (digitalRead(UP_BUTTON_PIN) == LOW) {
selectedMenuItem = (selectedMenuItem + 1) % 4;
updateMenuSelection(selectedMenuItem);
delay(200); // Debounce delay
} else if (digitalRead(DOWN_BUTTON_PIN) == LOW) {
selectedMenuItem = (selectedMenuItem - 1 + 4) % 4;
updateMenuSelection(selectedMenuItem);
delay(200); // Debounce delay
}
}
// Check for exit from menu
if (inMenu && digitalRead(OK_BUTTON_PIN) == LOW) {
exitMenu();
}
}
void enterMenu() {
inMenu = true;
okButtonPressedTime = millis();
displayMainMenu();
}
void exitMenu() {
inMenu = false;
lcd.clear();
}
void updateMenuSelection(int menuItem) {
lcd.setCursor(0, 0);
switch (menuItem) {
case MODE:
lcd.print("1. Mode");
break;
case TANK_HEIGHT:
lcd.print("2. Tank Height");
break;
case HIGH_VALUE:
lcd.print("3. High Value");
break;
case LOW_VALUE:
lcd.print("4. Low Value");
break;
}
lcd.setCursor(0, menuItem);
lcd.print(">");
}
void displayMainMenu() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("1. Mode");
lcd.setCursor(0, 1);
lcd.print(">"); // Initially highlight the first menu item
}
float measureDistance() {
digitalWrite(TRIGGER_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIGGER_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIGGER_PIN, LOW);
unsigned long duration = pulseIn(ECHO_PIN, HIGH);
float distance = duration / 29.1 / 2; // Convert pulse duration to distance in cm
return distance;
}
void displayWaterLevel(int level) {
// Set cursor to the position where "Water Level: " starts
lcd.setCursor(0, 0);
// Print "Water Level: "
lcd.print("Water Level: ");
// Set cursor to the position where the water level value starts
lcd.setCursor(13, 0); // Assuming "Water Level: " takes up 13 characters
// Clear the current water level content
lcd.print(" "); // Clear 4 characters to ensure the old content is overwritten
// Set cursor back to the water level position
lcd.setCursor(13, 0);
// Print the new water level value
lcd.print(level);
// Print the "%" symbol
lcd.print("%");
}