#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define UP_BTN 2
#define DOWN_BTN 3
#define ENTER_BTN 4
#define BACK_BTN 5
#define BUZZER 6
#define WATER_PUMP 7
#define DRAIN_VALVE 8
#define WATER_LEVEL_SENSOR A0
LiquidCrystal_I2C lcd(0x27, 16, 2);
int menuIndex = -1; // Tracks the current menu (Main, Wash Cycle, Dryer)
int selectedMenuItem = 0; // Tracks the selected menu item (0: Wash Cycle, 1: Dryer)
int stepIndex = -1; // Tracks the current step inside a menu
int washCycles = 1;
int washTimes[4] = {1, 1, 1, 1};
int drainTime = 1;
int dryTime = 5; // Dryer time in minutes
int waterLevelThreshold = 500;
unsigned long previousMillis = 0;
bool isFilling = false;
bool isDraining = false;
void setup() {
pinMode(UP_BTN, INPUT_PULLUP);
pinMode(DOWN_BTN, INPUT_PULLUP);
pinMode(ENTER_BTN, INPUT_PULLUP);
pinMode(BACK_BTN, INPUT_PULLUP);
pinMode(BUZZER, OUTPUT);
pinMode(WATER_PUMP, OUTPUT);
pinMode(DRAIN_VALVE, OUTPUT);
pinMode(WATER_LEVEL_SENSOR, INPUT);
lcd.init();
lcd.backlight();
lcd.clear();
lcd.print("Washing Mach V1");
lcd.setCursor(0,1);
lcd.print("Press Enter");
}
void loop() {
if (!digitalRead(ENTER_BTN)) {
if (menuIndex == -1) {
// Enter the selected menu item
menuIndex = selectedMenuItem;
showMenu();
} else if (stepIndex == -1) {
nextMenuStep();
} else {
nextStep();
}
delay(200);
}
if (!digitalRead(UP_BTN)) {
if (menuIndex == -1) {
// Navigate up in the main menu
selectedMenuItem = (selectedMenuItem == 0) ? 1 : 0; // Toggle between 0 and 1
showMenu();
} else if (stepIndex != -1) {
adjustValue(1);
}
delay(200);
}
if (!digitalRead(DOWN_BTN)) {
if (menuIndex == -1) {
// Navigate down in the main menu
selectedMenuItem = (selectedMenuItem == 0) ? 1 : 0; // Toggle between 0 and 1
showMenu();
} else if (stepIndex != -1) {
adjustValue(-1);
}
delay(200);
}
if (!digitalRead(BACK_BTN)) {
previousStep();
delay(200);
}
}
void showMenu() {
lcd.clear();
if (menuIndex == -1) {
// Main menu
lcd.print(selectedMenuItem == 0 ? ">1. Wash Cycles" : " 1. Wash Cycles");
lcd.setCursor(0,1);
lcd.print(selectedMenuItem == 1 ? ">2. Dryer" : " 2. Dryer");
} else if (menuIndex == 0) {
// Wash Cycle menu
showStep();
} else if (menuIndex == 1) {
// Dryer menu
showStep();
}
}
void nextMenuStep() {
if (menuIndex == 0) {
stepIndex = 0;
showStep();
} else if (menuIndex == 1) {
stepIndex = 5; // Dryer step index
showStep();
}
}
void showStep() {
lcd.clear();
if (stepIndex == 0) {
lcd.print(">Wash Cycles:");
lcd.setCursor(0,1);
lcd.print(washCycles);
} else if (stepIndex >= 1 && stepIndex <= washCycles) {
lcd.print(">Wash ");
lcd.print(stepIndex);
lcd.print(" Time:");
lcd.setCursor(0,1);
lcd.print(washTimes[stepIndex - 1]);
lcd.print(" min");
} else if (stepIndex == 5) {
lcd.print(">Dryer Time:");
lcd.setCursor(0,1);
lcd.print(dryTime);
lcd.print(" min");
} else {
lcd.print("Press Enter");
lcd.setCursor(0,1);
lcd.print("to Start");
}
}
void adjustValue(int change) {
if (stepIndex == 0) {
washCycles = constrain(washCycles + change, 1, 4);
} else if (stepIndex >= 1 && stepIndex <= washCycles) {
washTimes[stepIndex - 1] = constrain(washTimes[stepIndex - 1] + change, 1, 10);
} else if (stepIndex == 5) {
dryTime = constrain(dryTime + change, 1, 60); // Dryer time can be set from 1 to 60 minutes
}
showStep();
}
void nextStep() {
if (stepIndex < washCycles + 1) {
stepIndex++;
showStep();
} else if (stepIndex == 5) {
// Dryer step is complete, go back to main menu
menuIndex = -1;
stepIndex = -1;
lcd.clear();
lcd.print("Washing Mach V1");
lcd.setCursor(0,1);
lcd.print("Press Enter");
} else {
executeProcess();
}
}
void previousStep() {
if (stepIndex > 0) {
stepIndex--;
showStep();
} else if (menuIndex != -1) {
menuIndex = -1;
stepIndex = -1;
lcd.clear();
lcd.print("Washing Mach V1");
lcd.setCursor(0,1);
lcd.print("Press Enter");
}
}
void executeProcess() {
lcd.clear();
lcd.print("Filling...");
digitalWrite(WATER_PUMP, HIGH);
previousMillis = millis();
while (analogRead(WATER_LEVEL_SENSOR) < waterLevelThreshold) {
if (millis() - previousMillis >= 500) {
previousMillis = millis();
}
}
digitalWrite(WATER_PUMP, LOW);
lcd.clear();
lcd.print("Level Reached");
delay(2000);
for (int i = 0; i < washCycles; i++) {
performStep("Wash ", washTimes[i]);
drainWater();
}
// Start Dryer
lcd.clear();
lcd.print("Drying...");
performStep("Dry ", dryTime);
lcd.clear();
lcd.print("Cycle Done!");
beepAlert();
}
void performStep(const char* stepName, int duration) {
lcd.clear();
lcd.print(stepName);
lcd.print("Time Left:");
digitalWrite(WATER_PUMP, HIGH);
unsigned long startMillis = millis();
while (millis() - startMillis < duration * 60000) {
unsigned long elapsedMillis = millis() - startMillis;
unsigned long remainingMillis = duration * 60000 - elapsedMillis;
int remainingSeconds = remainingMillis / 1000;
lcd.setCursor(0,1);
lcd.print(remainingSeconds / 60);
lcd.print(":");
if (remainingSeconds % 60 < 10) {
lcd.print("0");
}
lcd.print(remainingSeconds % 60);
delay(1000); // Update every second
}
digitalWrite(WATER_PUMP, LOW);
}
void drainWater() {
lcd.clear();
lcd.print("Draining...");
digitalWrite(DRAIN_VALVE, HIGH);
unsigned long startMillis = millis();
while (millis() - startMillis < drainTime * 1000) {
// Wait without blocking
}
digitalWrite(DRAIN_VALVE, LOW);
}
void beepAlert() {
for (int i = 0; i < 5; i++) {
digitalWrite(BUZZER, HIGH);
delay(500);
digitalWrite(BUZZER, LOW);
delay(500);
}
}