#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
#include <EEPROM.h>
RTC_DS3231 rtc;
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Buttons
const int btnUp = 2;
const int btnDown = 3;
const int btnNext = 4;
// Relay pin
const int relayPin = 5; // Relay on pin 5
bool relayOn = false;
bool configMenu = false;
// Configuration steps
int step = 0;
int totalSteps = 0;
// Temporary time for adjustment
int hNow = 0, mNow = 0;
// On and off times
int hOn = 6, mOn = 0, hOff = 14, mOff = 0;
void setup() {
Serial.begin(9600);
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, setting the time!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
pinMode(btnUp, INPUT_PULLUP);
pinMode(btnDown, INPUT_PULLUP);
pinMode(btnNext, INPUT_PULLUP);
pinMode(relayPin, OUTPUT);
lcd.init();
lcd.backlight();
loadEEPROM();
display();
}
void loop() {
DateTime now = rtc.now();
relayOn = isTimeInRange(now.hour(), now.minute(), hOn, mOn, hOff, mOff);
digitalWrite(relayPin, relayOn ? HIGH : LOW); // Relay on and off
if (digitalRead(btnUp) == LOW) {
adjust(1);
delay(250);
}
if (digitalRead(btnDown) == LOW) {
adjust(-1);
delay(250);
}
if (digitalRead(btnNext) == LOW) {
configMenu = true;
step++;
totalSteps++;
if (step == 1) {
hNow = now.hour();
mNow = now.minute();
if(totalSteps == 1) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Configuration");
delay(800);
lcd.clear();
}
}
if (step > 6) {
saveEEPROM();
DateTime now = rtc.now();
rtc.adjust(DateTime(now.year(), now.month(), now.day(), hNow, mNow, now.second()));
step = 0;
}
display();
delay(250);
} else if(configMenu == false) {
display();
totalSteps = 0;
delay(250);
}
}
void adjust(int delta) {
switch (step) {
case 1: hNow = (hNow + delta + 24) % 24; break;
case 2: mNow = (mNow + delta + 60) % 60; break;
case 3: hOn = (hOn + delta + 24) % 24; break;
case 4: mOn = (mOn + delta + 60) % 60; break;
case 5: hOff = (hOff + delta + 24) % 24; break;
case 6: mOff = (mOff + delta + 60) % 60; break;
}
display();
}
void display() {
char buffer[6]; // Declaração da variável buffer
if (configMenu) {
// Menu de configuração
switch (step) {
case 0:
break;
case 1:
lcd.setCursor(0, 0);
lcd.print("Set Hour:");
lcd.setCursor(0, 1);
sprintf(buffer, "%02d:%02d", hNow, mNow);
lcd.print(buffer);
break;
case 2:
lcd.setCursor(0, 0);
lcd.print("Set Minute:");
lcd.setCursor(0, 1);
sprintf(buffer, "%02d:%02d", hNow, mNow);
lcd.print(buffer);
break;
case 3:
lcd.setCursor(0, 0);
lcd.print("Turn On Hour:");
lcd.setCursor(0, 1);
sprintf(buffer, "%02d:%02d", hOn, mOn);
lcd.print(buffer);
break;
case 4:
lcd.setCursor(0, 0);
lcd.print("Turn On Minute:");
lcd.setCursor(0, 1);
sprintf(buffer, "%02d:%02d", hOn, mOn);
lcd.print(buffer);
break;
case 5:
lcd.setCursor(0, 0);
lcd.print("Turn Off Hour:");
lcd.setCursor(0, 1);
sprintf(buffer, "%02d:%02d", hOff, mOff);
lcd.print(buffer);
break;
case 6:
lcd.setCursor(0, 0);
lcd.print("Turn Off Minute:");
lcd.setCursor(0, 1);
sprintf(buffer, "%02d:%02d", hOff, mOff);
lcd.print(buffer);
break;
}
} else {
// Tela principal
DateTime now = rtc.now();
lcd.setCursor(0, 0);
lcd.print("Now: ");
char fullBuffer[9]; // hh:mm:ss + null
sprintf(fullBuffer, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());
lcd.print(fullBuffer);
lcd.setCursor(0, 1);
lcd.print("Relay: ");
lcd.print(relayOn ? "on" : "off");
}
}
void saveEEPROM() {
EEPROM.write(0, hOn);
EEPROM.write(1, mOn);
EEPROM.write(2, hOff);
EEPROM.write(3, mOff);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Config Saved!");
configMenu = false;
delay(1000);
display();
}
void loadEEPROM() {
hOn = (EEPROM.read(0) == 255) ? 6 : EEPROM.read(0);
mOn = (EEPROM.read(1) == 255) ? 0 : EEPROM.read(1);
hOff = (EEPROM.read(2) == 255) ? 14 : EEPROM.read(2);
mOff = (EEPROM.read(3) == 255) ? 0 : EEPROM.read(3);
}
// Check if current time is between ON and OFF
bool isTimeInRange(int h, int m, int hIni, int mIni, int hFim, int mFim) {
int now = h * 60 + m;
int start = hIni * 60 + mIni;
int end = hFim * 60 + mFim;
if (start <= end) {
return now >= start && now < end;
} else {
return now >= start || now < end; // spans over midnight
}
}