#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Button pins
#define UP 2
#define DOWN 3
#define LEFT 4
#define RIGHT 5
#define OK 6
#define LED 7
String menuItems[] = {"Timer", "Stop Timer", "WiFi Mode"};
int menuIndex = 0;
enum State { MENU, SET_HOUR, SET_MIN, SET_SEC };
State currentState = MENU;
int hour = 0, minute = 0, second = 0;
unsigned long timerStart = 0;
unsigned long timerDuration = 0;
bool timerRunning = false;
bool showCountdown = true;
unsigned long lastInteraction = 0;
const unsigned long HIDE_INTERVAL = 180000; // 3 minutes
void setup() {
lcd.init();
lcd.backlight();
pinMode(UP, INPUT_PULLUP);
pinMode(DOWN, INPUT_PULLUP);
pinMode(LEFT, INPUT_PULLUP);
pinMode(RIGHT, INPUT_PULLUP);
pinMode(OK, INPUT_PULLUP);
pinMode(LED, OUTPUT);
lcd.setCursor(0, 0);
lcd.print("LED Menu System");
delay(1000);
lcd.clear();
showMenu();
}
void loop() {
handleButtons();
handleTimer();
handleCountdownDisplay();
}
void handleButtons() {
if (currentState == MENU) {
if (digitalRead(UP) == LOW) {
menuIndex = (menuIndex - 1 + 3) % 3;
showMenu();
delay(200);
}
if (digitalRead(DOWN) == LOW) {
menuIndex = (menuIndex + 1) % 3;
showMenu();
delay(200);
}
if (digitalRead(OK) == LOW) {
lastInteraction = millis();
if (menuItems[menuIndex] == "Timer") {
hour = 0; minute = 0; second = 0;
currentState = SET_HOUR;
delay(200);
showSetTime("Hour", hour);
} else if (menuItems[menuIndex] == "Stop Timer") {
digitalWrite(LED, LOW);
timerRunning = false;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Timer Stopped");
delay(1000);
showMenu();
} else if (menuItems[menuIndex] == "WiFi Mode") {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("WiFi Mode On");
delay(1000);
showMenu();
}
}
} else {
handleSetTime();
}
}
void showMenu() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(">");
lcd.print(menuItems[menuIndex]);
currentState = MENU;
}
void handleSetTime() {
int *currentValue;
String label;
State nextState;
if (currentState == SET_HOUR) {
currentValue = &hour;
label = "Hour";
nextState = SET_MIN;
} else if (currentState == SET_MIN) {
currentValue = &minute;
label = "Minute";
nextState = SET_SEC;
} else {
currentValue = &second;
label = "Second";
nextState = MENU;
}
if (digitalRead(UP) == LOW) {
(*currentValue)++;
showSetTime(label, *currentValue);
delay(200);
}
if (digitalRead(DOWN) == LOW) {
if (*currentValue > 0) (*currentValue)--;
showSetTime(label, *currentValue);
delay(200);
}
if (digitalRead(OK) == LOW) {
delay(200);
if (currentState == SET_SEC) {
timerDuration = (unsigned long)hour * 3600000UL +
(unsigned long)minute * 60000UL +
(unsigned long)second * 1000UL;
timerStart = millis();
timerRunning = true;
digitalWrite(LED, HIGH);
showCountdown = true;
lastInteraction = millis();
showMenu(); // Return to menu
} else {
currentState = nextState;
showSetTime(nextState == SET_MIN ? "Minute" : "Second", *currentValue);
}
}
}
void showSetTime(String label, int value) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set ");
lcd.print(label);
lcd.setCursor(0, 1);
lcd.print("Value: ");
lcd.print(value);
lcd.print(" ");
}
void handleTimer() {
if (timerRunning && millis() - timerStart >= timerDuration) {
digitalWrite(LED, LOW);
timerRunning = false;
showCountdown = false;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Timer Done");
delay(1500);
showMenu();
}
}
void handleCountdownDisplay() {
if (timerRunning && showCountdown) {
unsigned long remaining = timerDuration - (millis() - timerStart);
unsigned int rem_h = remaining / 3600000UL;
unsigned int rem_m = (remaining % 3600000UL) / 60000UL;
unsigned int rem_s = (remaining % 60000UL) / 1000UL;
lcd.setCursor(0, 1);
lcd.print("T:");
if (rem_h < 10) lcd.print("0");
lcd.print(rem_h);
lcd.print(":");
if (rem_m < 10) lcd.print("0");
lcd.print(rem_m);
lcd.print(":");
if (rem_s < 10) lcd.print("0");
lcd.print(rem_s);
if (digitalRead(OK) == LOW) {
showCountdown = false;
lcd.setCursor(0, 1);
lcd.print(" ");
lastInteraction = millis();
delay(200);
}
}
// Redisplay countdown after inactivity
if (!showCountdown && timerRunning && (millis() - lastInteraction > HIDE_INTERVAL)) {
showCountdown = true;
}
}