#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include <cmath> // For the fmod function
// Define the number of bytes you want to access
#define EEPROM_SIZE 64
int address = 0;
LiquidCrystal_I2C lcd(0x27, 20, 4);
#define fillingTankSwitch 17
#define inletValve 14
#define outletValve 26 //wastage water
#define uvLED 27
#define warningLED 12
#define Reset_filter1Runtime 16
#define Reset_filter2Runtime 4
#define Reset_filter3Runtime 15
#define reversePump 13
unsigned long ValveOpenTime = 0; // Variable to store the total duration the holding tank valve is open
float flowRate = 0.5; // Example flow rate in liters per second (adjust according to your system)
unsigned long previousMillis = 0; // Variable to store the previous millis value
unsigned long pumpStartTime = 0; // Variable to store the time when the pump was turned on
unsigned long warningLEDPreviousMillis = 0; // Variable to store the previous millis value for warning LED
const unsigned long warningLEDInterval = 200; // Warning LED blink interval (200 ms)
float waterConsumed;
float previousWaterConsumed; // Variable to store the previous water consumed value
// Filter capacities in liters
const int filter1Capacity = 3;
const int filter2Capacity = 8;
const int filter3Capacity = 13;
const int washAfterConsumption = 10;
// Filter water consumption in liters
float filter1Consumption = 0;
float filter2Consumption = 0;
float filter3Consumption = 0;
// Addresses in EEPROM for storing filter consumptions
int filter1Address = address + sizeof(float);
int filter2Address = filter1Address + sizeof(float);
int filter3Address = filter2Address + sizeof(float);
bool uvLEDOn = false;
bool warningLEDState = false;
bool filter1Dead = false;
bool filter2Dead = false;
bool filter3Dead = false;
bool pumpOn = false;
bool inletValveOn = false;
bool whetherPumpOn = false;
const long pumpOnTime = 3000; // 3 second interval
void setup() {
Serial.begin(115200);
EEPROM.begin(EEPROM_SIZE);
pinMode(inletValve, OUTPUT);
pinMode(outletValve, OUTPUT);
pinMode(uvLED, OUTPUT);
pinMode(warningLED, OUTPUT);
pinMode(fillingTankSwitch, INPUT);
pinMode(Reset_filter1Runtime, INPUT);
pinMode(Reset_filter2Runtime, INPUT);
pinMode(Reset_filter3Runtime, INPUT);
pinMode(reversePump, OUTPUT);
inlet_valve_off();
pump_off();
digitalWrite(warningLED, LOW);
lcd.init();
lcd.backlight();
// Read the initial water consumed value from EEPROM
EEPROM.get(address, waterConsumed);
// Read filter consumptions from EEPROM
EEPROM.get(filter1Address, filter1Consumption);
EEPROM.get(filter2Address, filter2Consumption);
EEPROM.get(filter3Address, filter3Consumption);
// Check if the read values are valid, if not initialize to 0
if (isnan(waterConsumed) || waterConsumed < 0) {
waterConsumed = 0;
}
if (isnan(filter1Consumption) || filter1Consumption < 0) {
filter1Consumption = 0;
}
if (isnan(filter2Consumption) || filter2Consumption < 0) {
filter2Consumption = 0;
}
if (isnan(filter3Consumption) || filter3Consumption < 0) {
filter3Consumption = 0;
}
previousWaterConsumed = waterConsumed; // Initialize previous water consumed
Serial.print("Initial waterConsumed = ");
Serial.println(waterConsumed);
lcd.setCursor(0, 0);
lcd.print("Arpina Aqua");
}
void loop() {
unsigned long currentMillis = millis(); // Get the current time
if (!filter1Dead && !filter2Dead && !filter3Dead) {
// Tank filling logic
if (digitalRead(fillingTankSwitch) == LOW) { // Full
inlet_valve_off();
} else if (!pumpOn) {
inlet_valve_on();
}
if (inletValveOn) {
ValveOpenTime += currentMillis - previousMillis; // Update the total duration
}
// Convert the duration to volume
float waterFlow = (ValveOpenTime / 1000.0) * flowRate; // in liters
waterConsumed += waterFlow;
ValveOpenTime = 0; // Reset ValveOpenTime after calculation
// Distribute water consumption among filters
filter1Consumption += waterFlow;
filter2Consumption += waterFlow;
filter3Consumption += waterFlow;
Serial.print("Water Consumed (L): ");
Serial.println(waterConsumed);
lcd.setCursor(0, 0);
lcd.print("Consumed(L): ");
lcd.print(waterConsumed);
// reverse pump logic
int waterConsumed_Mod = static_cast<int>(fmod(waterConsumed, washAfterConsumption));
Serial.println(waterConsumed_Mod);
if (waterConsumed_Mod == washAfterConsumption * 0.4 && !pumpOn && !whetherPumpOn) {
pump_on();
whetherPumpOn = true;
pumpStartTime = currentMillis; // Record the time the pump was turned on
}
if (pumpOn && (currentMillis - pumpStartTime >= pumpOnTime)) {
pump_off();
}
if (waterConsumed_Mod == washAfterConsumption * 0.9 ) {
whetherPumpOn = false;
}
// Write the updated waterConsumed value to EEPROM only if it is greater than the previous value
if (waterConsumed > previousWaterConsumed) {
EEPROM.put(address, waterConsumed);
EEPROM.commit();
previousWaterConsumed = waterConsumed; // Update previous water consumed
}
// Check filter capacities and display warnings if necessary
checkFilterCapacity();
} else {
inlet_valve_off();
pump_off();
}
// Reset filter consumptions if reset button is pressed
if (digitalRead(Reset_filter1Runtime) == HIGH) {
filter1Consumption = 0;
filter1Dead = false;
lcd.setCursor(0, 1);
lcd.print("filter1 replaced");
EEPROM.put(filter1Address, filter1Consumption);
EEPROM.commit();
Serial.println("Filter 1 reset");
inlet_valve_on();
}
if (digitalRead(Reset_filter2Runtime) == HIGH) {
filter2Consumption = 0;
filter2Dead = false;
lcd.setCursor(0, 2);
lcd.print("filter2 replaced");
EEPROM.put(filter2Address, filter2Consumption);
EEPROM.commit();
Serial.println("Filter 2 reset");
inlet_valve_on();
}
if (digitalRead(Reset_filter3Runtime) == HIGH) {
filter3Consumption = 0;
filter3Dead = false;
lcd.setCursor(0, 3);
lcd.print("filter3 replaced");
EEPROM.put(filter3Address, filter3Consumption);
EEPROM.commit();
Serial.println("Filter 3 reset");
inlet_valve_on();
}
Serial.println("----------------------------------------------------");
previousMillis = currentMillis; // Update previousMillis
}
void checkFilterCapacity() {
unsigned long currentMillis = millis(); // Get the current time
// Check if any filter is at 90% of its capacity and display warnings
if (filter1Consumption >= filter1Capacity * 0.9) {
lcd.setCursor(0, 1);
lcd.print("Filter 1: 90% used");
Serial.println("Warning: Filter 1 is 90% consumed");
if (filter1Consumption >= filter1Capacity) {
filter1Dead = true;
inlet_valve_off();
lcd.setCursor(0, 1);
lcd.print("Replace filter 1 ");
}
}
if (filter2Consumption >= filter2Capacity * 0.9) {
lcd.setCursor(0, 2);
lcd.print("Filter 2: 90% used");
Serial.println("Warning: Filter 2 is 90% consumed");
if (filter2Consumption >= filter2Capacity) {
filter2Dead = true;
inlet_valve_off();
lcd.setCursor(0, 2);
lcd.print("Replace filter 2 ");
}
}
if (filter3Consumption >= filter3Capacity * 0.9) {
lcd.setCursor(0, 3);
lcd.print("Filter 3: 90% used");
Serial.println("Warning: Filter 3 is 90% consumed");
if (filter3Consumption >= filter3Capacity) {
filter3Dead = true;
inlet_valve_off();
lcd.setCursor(0, 3);
lcd.print("Replace filter 3 ");
}
}
// Blink warning LED if any filter is over 90% capacity
if (filter1Consumption >= filter1Capacity * 0.9 || filter2Consumption >= filter2Capacity * 0.9 || filter3Consumption >= filter3Capacity * 0.9) {
if (currentMillis - warningLEDPreviousMillis >= warningLEDInterval) {
warningLEDPreviousMillis = currentMillis;
warningLEDState = !warningLEDState;
digitalWrite(warningLED, warningLEDState ? HIGH : LOW);
}
} else {
digitalWrite(warningLED, LOW); // Ensure warning LED is off if below threshold
}
// Write the updated filter consumptions to EEPROM
EEPROM.put(filter1Address, filter1Consumption);
EEPROM.put(filter2Address, filter2Consumption);
EEPROM.put(filter3Address, filter3Consumption);
EEPROM.commit();
}
bool inlet_valve_on() {
digitalWrite(inletValve, LOW); // Valve on
pump_off();
//digitalWrite(outletValve, HIGH); // Valve off
//digitalWrite(reversePump, HIGH); // Motor off
return inletValveOn = true;
}
bool inlet_valve_off() {
digitalWrite(inletValve, HIGH);
return inletValveOn = false;
}
bool pump_on() {
inlet_valve_off(); // Ensure inlet valve is off when pump is on
digitalWrite(outletValve, LOW); // Valve on
digitalWrite(reversePump, LOW); // Motor on
// Serial.println("??????????????????????????????????????????");
// spinner(20, 0, 100);
return pumpOn = true;
}
bool pump_off() {
digitalWrite(reversePump, HIGH); // Motor off
digitalWrite(outletValve, HIGH); // Valve off
// Serial.println("=====================================");
// whetherPumpOn = false;
return pumpOn = false;
}
bool uvLED_on() {
digitalWrite(uvLED, HIGH);
return uvLEDOn = true;
}
bool uvLED_off() {
digitalWrite(uvLED, LOW);
return uvLEDOn = false;
}
void spinner(int8_t col, int8_t row, uint16_t time) {
lcd.setCursor(col, row);
lcd.print("x");
delay(time);
lcd.setCursor(col, row);
lcd.print("+");
delay(time);
}