#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <WiFi.h> // Include the Wi-Fi library
#include <EEPROM.h>
// Set the LCD address to 0x27 for a 20 chars and 4 line display
LiquidCrystal_I2C lcd(0x27, 20, 4);
// WiFi credentials
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const int wifiTimeout = 6; // Adjust the timeout as needed
// NTP Server
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 3600;
const int daylightOffset_sec = 3600;
// Define EEPROM addresses for storing last tank event times
#define EEPROM_ADDR_LAST_TANK_FULL 0
#define EEPROM_ADDR_LAST_TANK_EMPTY 4
// Global variables for last tank event times
long lastTankFullTime = 0;
long lastTankEmptyTime = 0;
bool updateTime = false; // Flag to update time
// Pin connected to the potentiometer and LEDs
const int potPin = 34;
const int ledPin1 = 2;
const int ledPin2 = 0;
bool ledState = false; // Variable to alternate LED states
void setup() {
// Initialize LCD
lcd.init();
lcd.backlight();
// Display initial information
lcd.setCursor(0, 0);
lcd.print("Water Level: --%");
// Initialize LED pins
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
// Initialize Serial
Serial.begin(9600);
// Set time using ESP8266WiFi library
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
// Attempt WiFi connection
Serial.print("Connecting to WiFi");
WiFi.begin(ssid, password, wifiTimeout);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println(" Connected!");
// Read last tank event times from EEPROM
readLastTankEventTimesFromEEPROM();
}
void loop() {
// Get current time
time_t now = time(nullptr);
// Read potentiometer value and update water level
int potValue = analogRead(potPin);
int waterLevel = map(potValue, 0, 4095, 0, 100);
// Update time if necessary
if (updateTime || waterLevel == 100 || waterLevel < 50) {
updateTime = false;
now = time(nullptr); // Update time
}
// Control LED based on water level
controlLED(waterLevel);
// Display water level and LED status
displayWaterLevel(waterLevel);
displayLEDStatus();
// Check for tank events
checkTankEvents(waterLevel);
// Refresh screen every 20 seconds
static unsigned long lastRefresh = 0;
if (millis() - lastRefresh >= 20000) {
lastRefresh = millis();
updateTime = true; // Flag to update time
}
// Delay for stability
delay(1000);
}
void displayWaterLevel(int level) {
lcd.setCursor(0, 1);
lcd.print("Water Level: ");
lcd.print(level);
lcd.print("% ");
}
void displayLEDStatus() {
lcd.setCursor(0, 2);
lcd.print("LED Status: ");
if (ledState) {
lcd.print("On ");
} else {
lcd.print("Off ");
}
}
void checkTankEvents(int level) {
if (level == 100 && lastTankFullTime == 0) {
lastTankFullTime = time(nullptr);
writeLastTankEventTimesToEEPROM();
displayMessage("Pump Off - Water Level Full");
} else if (level < 100 && lastTankFullTime != 0 && lastTankEmptyTime == 0) {
lastTankEmptyTime = time(nullptr);
writeLastTankEventTimesToEEPROM();
}
}
void readLastTankEventTimesFromEEPROM() {
EEPROM.get(EEPROM_ADDR_LAST_TANK_FULL, lastTankFullTime);
EEPROM.get(EEPROM_ADDR_LAST_TANK_EMPTY, lastTankEmptyTime);
}
void writeLastTankEventTimesToEEPROM() {
EEPROM.put(EEPROM_ADDR_LAST_TANK_FULL, lastTankFullTime);
EEPROM.put(EEPROM_ADDR_LAST_TANK_EMPTY, lastTankEmptyTime);
}
void controlLED(int level) {
if (level < 25) {
digitalWrite(ledPin1, HIGH);
digitalWrite(ledPin2, HIGH);
ledState = false;
} else if (level >= 25 && level < 75) {
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, HIGH);
ledState = false;
} else if (level >= 75 && level < 100) {
digitalWrite(ledPin1, HIGH);
digitalWrite(ledPin2, LOW);
ledState = true;
} else {
digitalWrite(ledPin1, LOW);
digitalWrite(ledPin2, LOW);
ledState = false;
}
}
void displayMessage(String message) {
lcd.setCursor(0, 3);
lcd.print(message);
}