#include <EEPROM.h>
#include <LiquidCrystal_I2C.h>
// LCD and button definitions
LiquidCrystal_I2C lcd(0x27, 20, 4);
const int startButton = 2;
const int resetButton = 3;
const int upButton = 4;
const int downButton = 5;
const int selectButton = 6;
const int relayPin = 7;
// Variables to store the on/off times and number of cycles
int onSeconds = 0;
int onMinutes = 0;
int onHours = 0;
int offSeconds = 0;
int offMinutes = 0;
int offHours = 0;
int numCycles = 0;
int cycleCount = 0;
// Enum to track the current menu being displayed
enum Menu {
ON_SECONDS,
ON_MINUTES,
ON_HOURS,
OFF_SECONDS,
OFF_MINUTES,
OFF_HOURS,
NUM_CYCLES,
START,
STOP
};
Menu currentMenu = ON_SECONDS;
bool isProgramRunning = false;
void setup()
{
// Initialize the LCD screen and buttons
lcd.begin(0,0);
pinMode(startButton, INPUT);
pinMode(resetButton, INPUT);
pinMode(upButton, INPUT);
pinMode(downButton, INPUT);
pinMode(selectButton, INPUT);
pinMode(relayPin, OUTPUT);
// Load the on/off times and number of cycles from EEPROM
onSeconds = EEPROM.read(0);
onMinutes = EEPROM.read(1);
onHours = EEPROM.read(2);
offSeconds = EEPROM.read(3);
offMinutes = EEPROM.read(4);
offHours = EEPROM.read(5);
numCycles = EEPROM.read(6);
}
void loop()
{
// Check the buttons and update the values accordingly
if (digitalRead(resetButton) == LOW) {
resetValues();
} else if (digitalRead(upButton) == LOW) {
incrementValue();
} else if (digitalRead(downButton) == LOW) {
decrementValue();
} else if (digitalRead(selectButton) == LOW) {
nextMenu();
} else if (digitalRead(startButton) == LOW) {
delay(20);
if (digitalRead(startButton) == LOW) {
if (isProgramRunning) {
stopProgram();
} else {
startProgram();
}
}
}
// Display the current menu on the LCD screen
displayMenu();
delay(500);
// Only execute the program when it is running
if (isProgramRunning) {
executeProgram();
}
}
void resetValues()
{
// Reset the on/off times and number of cycles to their default values
onSeconds = 0;
onMinutes = 0;
onHours = 0;
offSeconds = 0;
offMinutes = 0;
offHours = 0;
numCycles = 0;
// Save the new values to EEPROM
EEPROM.write(0, onSeconds);
EEPROM.write(1, onMinutes);
EEPROM.write(2, onHours);
EEPROM.write(3, offSeconds);
EEPROM.write(4, offMinutes);
EEPROM.write(5, offHours);
EEPROM.write(6, numCycles);
}
void incrementValue()
{
switch (currentMenu) {
case ON_SECONDS:
onSeconds++;
if (onSeconds > 59) {
onSeconds = 0;
}
EEPROM.write(0, onSeconds);
break;
case ON_MINUTES:
onMinutes++;
if (onMinutes > 59) {
onMinutes = 0;
}
EEPROM.write(1, onMinutes);
break;
case ON_HOURS:
onHours++;
if (onHours > 23) {
onHours = 0;
}
EEPROM.write(2, onHours);
break;
case OFF_SECONDS:
offSeconds++;
if (offSeconds > 59) {
offSeconds = 0;
}
EEPROM.write(3, offSeconds);
break;
case OFF_MINUTES:
offMinutes++;
if (offMinutes > 59) {
offMinutes = 0;
}
EEPROM.write(4, offMinutes);
break;
case OFF_HOURS:
offHours++;
if (offHours > 23) {
offHours = 0;
}
EEPROM.write(5, offHours);
break;
case NUM_CYCLES:
numCycles++;
EEPROM.write(6, numCycles);
break;
default:
break;
}
}
void decrementValue()
{
switch (currentMenu) {
case ON_SECONDS:
onSeconds--;
if (onSeconds < 0) {
onSeconds = 59;
}
EEPROM.write(0, onSeconds);
break;
case ON_MINUTES:
onMinutes--;
if (onMinutes < 0) {
onMinutes = 59;
}
EEPROM.write(1, onMinutes);
break;
case ON_HOURS:
onHours--;
if (onHours < 0) {
onHours = 23;
}
EEPROM.write(2, onHours);
break;
case OFF_SECONDS:
offSeconds--;
if (offSeconds < 0) {
offSeconds = 59;
}
EEPROM.write(3, offSeconds);
break;
case OFF_MINUTES:
offMinutes--;
if (offMinutes < 0) {
offMinutes = 59;
}
EEPROM.write(4, offMinutes);
break;
case OFF_HOURS:
offHours--;
if (offHours < 0) {
offHours = 23;
}
EEPROM.write(5, offHours);
break;
case NUM_CYCLES:
numCycles--;
if (numCycles < 0) {
numCycles = 0;
}
EEPROM.write(6, numCycles);
break;
default:
break;
}
}
void nextMenu()
{
// Move to the next menu item in the enum
currentMenu = static_cast<Menu>(static_cast<int>(currentMenu) + 1);
if (currentMenu > NUM_CYCLES) {
currentMenu = ON_SECONDS;
}
}
void startProgram()
{
// Start the program
isProgramRunning = true;
currentMenu = STOP;
cycleCount = 0;
}
void stopProgram()
{
// Stop the program
isProgramRunning = false;
currentMenu = START;
}
void executeProgram()
{
int onDuration = (onHours * 3600 + onMinutes * 60 + onSeconds) * 1000;
int offDuration = (offHours * 3600 + offMinutes * 60 + offSeconds) * 1000;
int cycleCount = 0;
unsigned long startTime = millis();
while (cycleCount < numCycles) {
if (millis() - startTime < onDuration) {
digitalWrite(relayPin, HIGH);
} else if (millis() - startTime < onDuration + offDuration) {
digitalWrite(relayPin, LOW);
} else {
startTime = millis();
cycleCount++;
}
}
stopProgram();
}
void displayMenu()
{
lcd.clear();
switch (currentMenu)
{
case ON_SECONDS:
lcd.setCursor(0, 0);
lcd.print("On Seconds:");
lcd.setCursor(13, 0);
lcd.print(onSeconds);
break;
case ON_MINUTES:
lcd.setCursor(0, 0);
lcd.print("On Minutes:");
lcd.setCursor(13, 0);
lcd.print(onMinutes);
break;
case ON_HOURS:
lcd.setCursor(0, 0);
lcd.print("On Hours:");
lcd.setCursor(13, 0);
lcd.print(onHours);
break;
case OFF_SECONDS:
lcd.setCursor(0, 0);
lcd.print("Off Seconds:");
lcd.setCursor(13, 0);
lcd.print(offSeconds);
break;
case OFF_MINUTES:
lcd.setCursor(0, 0);
lcd.print("Off Minutes:");
lcd.setCursor(13, 0);
lcd.print(offMinutes);
break;
case OFF_HOURS:
lcd.setCursor(0, 0);
lcd.print("Off Hours:");
lcd.setCursor(13, 0);
lcd.print(offHours);
break;
case NUM_CYCLES:
lcd.setCursor(0, 0);
lcd.print("Num Cycles:");
lcd.setCursor(13, 0);
lcd.print(numCycles);
break;
case START:
lcd.setCursor(0, 0);
lcd.print("Start");
lcd.setCursor(5, 1);
lcd.print("Program");
break;
case STOP:
lcd.setCursor(0, 0);
lcd.print("Stop");
lcd.setCursor(5, 1);
lcd.print("Program");
break;
default:
lcd.clear();
lcd.print("Error");
break;
}
}