#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#include <RTClib.h> // Use the RTClib library for RTC functionality
RTC_DS1307 rtc; // Create an RTC object
// Relay pins
#define relay1 2 // Example relay pin on GPIO 2
#define relay2 4 // Example relay pin on GPIO 4
// Add more relay pins as needed
// Define the I2C address for the 20x4 LCD
#define I2C_ADDR 0x27
// Create an LCD object
LiquidCrystal_I2C lcd(I2C_ADDR, 20, 4);
// Define the pins for buttons (you may need to adjust these)
#define btnRIGHT 34
#define btnUP 35
#define btnDOWN 36
#define btnLEFT 39
#define btnSELECT 32
// Mode definitions
#define modeSETUP 1
#define modeNORMAL 2
int mode = modeSETUP; // Set the default mode to SETUP
// EEPROM addressing (adjust as needed)
#define adr1ON 0
#define adr1OF 2
#define adr2ON 4
#define adr2OF 6
// ... Define more EEPROM addresses for additional relays
// Variables for EEPROM settings
int eepromMin = 0;
int eepromHour = 0;
int eepromHourON = 0;
int eepromHourOF = 0;
int eepromMinON = 0;
int eepromMinOF = 0;
void setup() {
// Initialize I2C communication
Wire.begin();
// Initialize the LCD
lcd.init();
lcd.backlight();
// Initialize the serial port for debugging (if needed)
// Serial.begin(9600);
// Initialize the RTC
if (!rtc.begin()) {
// If RTC initialization fails, you can handle it here.
// Serial.println("Couldn't find RTC");
while (1);
}
// Set the RTC to the current date and time (comment out after initial setup)
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// Set all relay pins as OUTPUT
pinMode(relay1, OUTPUT);
pinMode(relay2, OUTPUT);
// Add pinMode statements for more relay pins
}
void loop() {
lcd.setCursor(4, 0);
// Display current time
displayTime();
// Set and display relay status based on EEPROM data
lcd.setCursor(0, 1);
lcd.print("1");
relayAction(adr1ON, adr1OF, 1, relay1);
lcd.setCursor(2, 1);
lcd.print("2");
relayAction(adr2ON, adr2OF, 3, relay2);
// Add more relay status displays as needed
// Handle button presses
int button = read_LCD_buttons();
if (button == btnSELECT) {
while (read_LCD_buttons() == btnSELECT);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("UP. TIME SETTING");
lcd.setCursor(0, 1);
lcd.print("DN. PIN SETTING");
while (read_LCD_buttons() == btnNONE);
if (read_LCD_buttons() == btnUP) {
while (read_LCD_buttons() == btnUP);
setRTC(); // Enter RTC setup menu
} else if (read_LCD_buttons() == btnDOWN) {
while (read_LCD_buttons() == btnDOWN);
setPin(); // Enter relay pin setup menu
}
}
}
void relayAction(int adrON, int adrOF, int pos, int pin) {
DateTime now = rtc.now(); // Get the current date and time from the RTC
int MinToday = (now.hour() * 60) + now.minute();
int MinEprON = (EEPROM.read(adrON) * 60) + EEPROM.read(adrON + 1);
int MinEprOF = (EEPROM.read(adrOF) * 60) + EEPROM.read(adrOF + 1);
lcd.setCursor(pos, 1);
if (MinEprON == MinEprOF) { // If the ON and OFF times are the same, relay is not used
lcd.print(" ");
digitalWrite(pin, LOW);
} else if (MinEprON < MinEprOF) { // ON occurs on the same day
if ((MinEprON <= MinToday) && (MinEprOF > MinToday)) {
lcd.print("*");
digitalWrite(pin, LOW);
} else {
lcd.print("-");
digitalWrite(pin, HIGH);
}
} else if (MinEprON > MinEprOF) { // ON occurs until the next day
if ((MinEprON >= MinToday) || (MinEprOF < MinToday)) {
lcd.print("*");
digitalWrite(pin, LOW);
} else {
lcd.print("-");
digitalWrite(pin, HIGH);
}
}
}
/* ================================================== */
/* SETUP Functions */
/* ================================================== */
void setRTC() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("TIME SETTING");
delay(1000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("CURRENT ");
setupShowValue(rtc.now().hour(), rtc.now().minute(), 0);
lcd.setCursor(0, 1);
lcd.print("NEW ");
DateTime now = rtc.now();
setupShowValue(now.hour(), now.minute(), 1);
while (read_LCD_buttons() == btnNONE);
setupChooseValueSetRTC(now.hour(), now.minute(), 1);
lcd.setCursor(0, 0);
lcd.print("SETTINGS SAVED ");
delay(1000);
lcd.clear();
}
void setPin() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("PIN SETTING");
delay(1000);
// Relay 1 ON
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("RELAY 1 ON");
eepromHour = EEPROM.read(adr1ON);
eepromMin = EEPROM.read(adr1ON + 1);
if (eepromHour >= 24) eepromHour = 0;
if (eepromMin >= 60) eepromMin = 0;
setupShowValue(eepromHour, eepromMin, 0);
while (read_LCD_buttons() == btnNONE);
setupChooseValue(eepromHour, eepromMin, adr1ON, 0);
// Relay 1 OFF
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("RELAY 1 OFF");
eepromHour = EEPROM.read(adr1OF);
eepromMin = EEPROM.read(adr1OF + 1);
if (eepromHour >= 24) eepromHour = 0;
if (eepromMin >= 60) eepromMin = 0;
setupShowValue(eepromHour, eepromMin, 1);
while (read_LCD_buttons() == btnNONE);
setupChooseValue(eepromHour, eepromMin, adr1OF, 1);
// Repeat the above setup for other relays as needed
}
void setupChooseValue(int HourNew, int MinNew, byte Address, byte Pos) {
while (read_LCD_buttons() != btnSELECT) {
if (read_LCD_buttons() == btnRIGHT) {
if (HourNew < 23) {
HourNew++;
}
} else if (read_LCD_buttons() == btnLEFT) {
if (HourNew > 0) {
HourNew--;
}
} else if (read_LCD_buttons() == btnUP) {
if (MinNew < 59) {
MinNew++;
}
} else if (read_LCD_buttons() == btnDOWN) {
if (MinNew > 0) {
MinNew--;
}
}
setupShowValue(HourNew, MinNew, Pos);
delay(150);
}
while (read_LCD_buttons() != btnNONE); // Wait until the button is released
EEPROM.write(Address, HourNew);
EEPROM.write(Address + 1, MinNew);
delay(150);
}
void setupChooseValueSetRTC(int HourNew, int MinNew, byte Pos) {
while (read_LCD_buttons() != btnSELECT) {
if (read_LCD_buttons() == btnRIGHT) {
if (HourNew < 23) {
HourNew++;
}
} else if (read_LCD_buttons() == btnLEFT) {
if (HourNew > 0) {
HourNew--;
}
} else if (read_LCD_buttons() == btnUP) {
if (MinNew < 59) {
MinNew++;
}
} else if (read_LCD_buttons() == btnDOWN) {
if (MinNew > 0) {
MinNew--;
}
}
setupShowValue(HourNew, MinNew, Pos);
delay(150);
}
while (read_LCD_buttons() != btnNONE); // Wait until the button is released
// Set the RTC time
rtc.adjust(DateTime(rtc.now().year(), rtc.now().month(), rtc.now().day(), HourNew, MinNew, 0));
delay(150);
}
void setupShowValue(int Hour, int Min, int Pos) {
lcd.setCursor(11, Pos);
print2digits(Hour);
lcd.print(":");
print2digits(Min);
}
/* ================================================== */
/* LCD Functions */
/* ================================================== */
int read_LCD_buttons() {
int adc_key_in = analogRead(34); // Adjust to the pin you are using for buttons
if (adc_key_in > 1000) return btnNONE;
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 150) return btnUP;
if (adc_key_in < 300) return btnDOWN;
if (adc_key_in < 500) return btnLEFT;
if (adc_key_in < 850) return btnSELECT;
return btnNONE;
}
void displayTime() {
DateTime now = rtc.now(); // Get the current date and time from the RTC
print2digits(now.hour());
lcd.print(":");
print2digits(now.minute());
lcd.print(":");
print2digits(now.second());
}
void print2digits(int number) {
if (number < 10) lcd.print('0');
lcd.print(number);
}