#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
RTC_DS1307 rtc;
LiquidCrystal_I2C lcd(0x27, 20, 4);
struct AlarmSetting {
byte mode = 0;
byte hourStart = 0;
byte minuteStart = 0;
byte hourStop = 0;
byte minuteStop = 0;
};
AlarmSetting alarms[5];
const int relayPin[4] = {2,3,4,5};
char daysOfTheWeek[7][12] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
const int buttonMenu = A0;
const int buttonChannel = A1;
const int buttonSelectTimer = A2;
const int buttonSetTimer = A3;
int settingMode = 0;
int selectedMenu = 4;
int selectedTimer = 0;
int setPointWaktu[4]={6,23,59,59};
int timerVar[4];
char clockBuffer[8];
char hourRTCBuffer[3];
char minuteRTCBuffer[3];
char secondRTCBuffer[3];
char hourStartBuffer[4][3];
char hourStopBuffer[4][3];
char minuteStartBuffer[4][3];
char minuteStopBuffer[4][3];
bool alarmCondition[4];
String alarmMode[2] = {"OFF","ON "};
String channelMode[3] = {"AUTO","ON ","OFF "};
unsigned long previousMillis = 0;
const long interval = 250;
int ledState = LOW;
unsigned long realtimeStamp;
unsigned long timeStart[4];
unsigned long timeStop[4];
void setup() {
Wire.begin();
Serial.begin(115200);
lcd.init();
lcd.backlight();
if (!rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
if (!rtc.isrunning()) {
Serial.println("RTC is not running!");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
pinMode(buttonMenu, INPUT_PULLUP);
pinMode(buttonChannel, INPUT_PULLUP);
pinMode(buttonSelectTimer, INPUT_PULLUP);
pinMode(buttonSetTimer, INPUT_PULLUP);
for (int i = 0; i < 4; i++) {
pinMode(relayPin[i-1], OUTPUT);
int addr = i * (sizeof(AlarmSetting)*2);
EEPROM.get(addr, alarms[i]);
if(alarms[i].mode>2){alarms[i].mode=0;}
if(alarms[i].hourStart>23){alarms[i].hourStart=0;}
if(alarms[i].minuteStart>59){alarms[i].minuteStart=0;}
if(alarms[i].hourStop>23){alarms[i].hourStop=0;}
if(alarms[i].minuteStop>59){alarms[i].minuteStop=0;}
}
lcd.setCursor(0, 0);
lcd.print("Timer Relay v1.0");
lcd.setCursor(0, 3);
for(int x=0; x<20; x++){
lcd.print(".");
delay(50);
}
delay(1000);
lcd.clear();
}
void loop() {
DateTime now = rtc.now();
if (millis() - previousMillis >= (interval*2)) {
previousMillis = millis();
realtimeStamp = ((now.hour() * 3600L) + (now.minute() * 60L) + now.second());
Serial.println("Realtime Seconds: "+String(realtimeStamp));
for (int i = 0; i < 4; i++) {
Serial.print("Schedule Start"+String(i+1)+" : "+String(timeStart[i])+"\t");
Serial.println("Schedule Stop"+String(i+1)+" : "+String(timeStop[i]));
}
}
for (int i = 0; i < 4; i++) {
if(alarms[i].mode == 0){
if (realtimeStamp >= timeStart[i] && realtimeStamp < timeStop[i]){
activateRelay(i);
alarmCondition[i] = true;
}
else if (realtimeStamp >= timeStop[i]){
deactivateRelay(i);
alarmCondition[i] = false;
}
}
else if(alarms[i].mode == 1){activateRelay(i);alarmCondition[i] = true;}
else if(alarms[i].mode == 2){deactivateRelay(i);alarmCondition[i] = false;}
}
if(!digitalRead(buttonMenu)){
if (settingMode == 0) {
timerVar[0] = now.dayOfTheWeek();
timerVar[1] = now.hour();
timerVar[2] = now.minute();
timerVar[3] = now.second();
}
if (settingMode == 1 && selectedMenu == 4) {
rtc.adjust(DateTime(now.year(), now.month(), now.day(), timerVar[1], timerVar[2], timerVar[3]));
}
settingMode++;
if(settingMode>1)settingMode=0;
for (int i = 0; i < 4; i++) {
int addr = i * (sizeof(AlarmSetting)*2);
EEPROM.put(addr, alarms[i]);
}
selectedMenu = 4;
selectedTimer = 0;
lcd.clear();
delay(200);
}
if (settingMode == 1) {
handleSettingMode();
}
else if(settingMode == 0){
handleNormalMode();
}
}
void handleNormalMode() {
DateTime now = rtc.now();
for (int i = 0; i < 4; i++) {
lcd.setCursor(0, i);
lcd.print("CH "+String(i+1)+" : "+alarmMode[alarmCondition[i]]);
}
for(int x=0; x<4; x++){
lcd.setCursor(11, x);
lcd.print("|");
}
lcd.setCursor(12, 0);
lcd.print(daysOfTheWeek[now.dayOfTheWeek()]);
sprintf(clockBuffer, "%02d:%02d:%02d", now.hour(),now.minute(),now.second());
lcd.setCursor(12, 1);
lcd.print(clockBuffer);
}
void handleSettingMode() {
if(!digitalRead(buttonChannel)){
lcd.clear();
int addr = (selectedMenu) * (sizeof(AlarmSetting)*2);
EEPROM.put(addr, alarms[selectedMenu]);
selectedMenu++;
if(selectedMenu>4){selectedMenu=0;}
selectedTimer=0;
delay(100);
}
if(selectedMenu==4){
if(!digitalRead(buttonSelectTimer)){
selectedTimer++;
if(selectedTimer>3){selectedTimer=0;}
delay(100);
}
if(!digitalRead(buttonSetTimer)){
timerVar[selectedTimer]++;
if(timerVar[selectedTimer]>setPointWaktu[selectedTimer]){timerVar[selectedTimer]=0;}
delay(100);
}
sprintf(hourRTCBuffer, "%02d", timerVar[1]);
sprintf(minuteRTCBuffer, "%02d", timerVar[2]);
sprintf(secondRTCBuffer, "%02d", timerVar[3]);
lcd.setCursor(0, 0);
lcd.print(" Set RTC ");
lcd.setCursor(4, 1);
lcd.print(String(daysOfTheWeek[timerVar[0]])+","+String(hourRTCBuffer)+":"+String(minuteRTCBuffer)+":"+String(secondRTCBuffer));
lcd.setCursor(0, 2);
if(selectedTimer==0){lcd.println(" ^^^ ");}
if(selectedTimer==1){lcd.println(" ^^ ");}
if(selectedTimer==2){lcd.println(" ^^ ");}
if(selectedTimer==3){lcd.println(" ^^ ");}
}
else{
if(!digitalRead(buttonSelectTimer)){
selectedTimer++;
if(selectedTimer>4){selectedTimer=0;}
delay(100);
}
if(!digitalRead(buttonSetTimer)&&selectedTimer==0){
alarms[selectedMenu].mode++;
if(alarms[selectedMenu].mode == 1){activateRelay(selectedMenu);}
else if(alarms[selectedMenu].mode == 2){deactivateRelay(selectedMenu);}
if(alarms[selectedMenu].mode>2)alarms[selectedMenu].mode=0;
delay(100);
}
if(!digitalRead(buttonSetTimer)&&selectedTimer==1){
alarms[selectedMenu].hourStart++;
if(alarms[selectedMenu].hourStart>23)alarms[selectedMenu].hourStart=0;
timeStart[selectedMenu] = (alarms[selectedMenu].hourStart * 3600L) + (alarms[selectedMenu].minuteStart * 60L);
delay(100);
}
if(!digitalRead(buttonSetTimer)&&selectedTimer==2){
alarms[selectedMenu].minuteStart++;
if(alarms[selectedMenu].minuteStart>59)alarms[selectedMenu].minuteStart=0;
timeStart[selectedMenu] = (alarms[selectedMenu].hourStart * 3600L) + (alarms[selectedMenu].minuteStart * 60L);
delay(100);
}
if(!digitalRead(buttonSetTimer)&&selectedTimer==3){
alarms[selectedMenu].hourStop++;
if(alarms[selectedMenu].hourStop>23)alarms[selectedMenu].hourStop=0;
timeStop[selectedMenu] = (alarms[selectedMenu].hourStop * 3600L) + (alarms[selectedMenu].minuteStop * 60L);
delay(100);
}
if(!digitalRead(buttonSetTimer)&&selectedTimer==4){
alarms[selectedMenu].minuteStop++;
if(alarms[selectedMenu].minuteStop>59)alarms[selectedMenu].minuteStop=0;
timeStop[selectedMenu] = (alarms[selectedMenu].hourStop * 3600L) + (alarms[selectedMenu].minuteStop * 60L);
delay(100);
}
sprintf(hourStartBuffer[selectedMenu], "%02d", alarms[selectedMenu].hourStart);
sprintf(minuteStartBuffer[selectedMenu], "%02d", alarms[selectedMenu].minuteStart);
sprintf(hourStopBuffer[selectedMenu], "%02d", alarms[selectedMenu].hourStop);
sprintf(minuteStopBuffer[selectedMenu], "%02d", alarms[selectedMenu].minuteStop);
lcd.setCursor(0, 0);lcd.print("Set Timer Channel "+String(selectedMenu+1));
lcd.setCursor(0, 1);lcd.print("Mode - Start - Stop ");
lcd.setCursor(0, 2);
lcd.print(channelMode[alarms[selectedMenu].mode]+" | "+String(hourStartBuffer[selectedMenu])+":"+String(minuteStartBuffer[selectedMenu])+" | "+String(hourStopBuffer[selectedMenu])+":"+String(minuteStopBuffer[selectedMenu]));
lcd.setCursor(0, 3);
if(selectedTimer==0){lcd.println("^^^^ ");}
if(selectedTimer==1){lcd.println(" ^^ ");}
if(selectedTimer==2){lcd.println(" ^^ ");}
if(selectedTimer==3){lcd.println(" ^^ ");}
if(selectedTimer==4){lcd.println(" ^^");}
}
}
void activateRelay(int relayNum) {
digitalWrite(relayPin[relayNum], HIGH); // Aktifkan Relay
}
void deactivateRelay(int relayNum) {
digitalWrite(relayPin[relayNum], LOW); // Nonaktifkan Relay
}