#include <LiquidCrystal_I2C.h>
#include <RTClib.h>
#include <Wire.h>
const int k1_pin = 4;
const int k2_pin = 5;
const int k3_pin = 6;
const int relay_pin = 2;
boolean relay_state = LOW;
boolean k1_state;
boolean k1_prevState = HIGH;
unsigned long last_press_k1;
unsigned long k1_time_press;
boolean k2_state;
boolean k2_prevState = HIGH;
unsigned long last_press_k2;
unsigned long k2_time_press;
boolean k3_state;
boolean k3_prevState = HIGH;
unsigned long last_press_k3;
unsigned long k3_time_press;
boolean newMinute = false;
boolean newHour = false;
boolean timerScreen = false;
boolean startTimerScreenTimeCounting = false;
unsigned long timerTimeScreen;
boolean timerSettingsScreen = false;
boolean doneTimerSettings = false;
unsigned long previousMillisScreenBlink = 0;
// 0 - t_on,години; 1 - t_on,хвилини; 2 - t_on,секунди.
// 4 - t_off,години; 5 - t_off,хвилини; 6 - t_off,секунди.
uint8_t t_on_off[6] = {00,00,00,00,00,00};
unsigned int currentTimerValueToChange = 0;
char tOnString[16] = "T.ON=0:0:0";
char tOffString[16] = "T.OFF=0:0:0";
LiquidCrystal_I2C lcd(0x27,16,2);
RTC_DS1307 RTC;
void setup() {
Serial.begin(9600);
pinMode(k1_pin, INPUT_PULLUP);
pinMode(k2_pin, INPUT_PULLUP);
pinMode(k3_pin, INPUT_PULLUP);
pinMode(relay_pin, OUTPUT);
lcd.init();
lcd.backlight();
RTC.begin();
}
void loop() {
if(!timerSettingsScreen) {
k1_state = digitalRead(k1_pin);
unsigned long k1_time = checkButtonPressTime(k1_state, k1_prevState, last_press_k1, k1_time_press);
if((k1_time !=0 && k1_time < 1000) || timerScreen){
timerScreen = true;
showTimerScreen();
if (!startTimerScreenTimeCounting){
timerTimeScreen = millis();
startTimerScreenTimeCounting = true;
Serial.println("Start timer for 10 sec,timer screen");
}
if(millis() - timerTimeScreen > 10000){
Serial.println("10 sec");
timerScreen = false;
lcd.clear();
startTimerScreenTimeCounting = false;
}
k1_state = digitalRead(k1_pin);
k1_time = checkButtonPressTime(k1_state, k1_prevState, last_press_k1, k1_time_press);
if (k1_time > 1000){
timerSettingsScreen = true;
Serial.println("Settings timer screen");
k1_prevState = HIGH;
unsigned long last_press_k1;
unsigned long k1_time_press;
}
}
}
else {
blinkScreen();
k1_state = digitalRead(k1_pin);
unsigned long k1_time = checkButtonPressTime(k1_state, k1_prevState, last_press_k1, k1_time_press);
if(k1_time != 0 && k1_time < 1000){
currentTimerValueToChange >= 5 ? currentTimerValueToChange = 0 : currentTimerValueToChange = currentTimerValueToChange + 1;
Serial.println(currentTimerValueToChange);
}
else if(k1_time > 1000){
Serial.println("Exit from timer settings");
timerSettingsScreen = false;
timerScreen = true;
startTimerScreenTimeCounting = false;
doneTimerSettings = true;
}
k2_state = digitalRead(k2_pin);
unsigned long k2_time = checkButtonPressTime(k2_state, k2_prevState, last_press_k2, k2_time_press);
if(k2_time != 0 && k2_time < 1000){
Serial.println("plus hour");
increaseTime();
}
k3_state = digitalRead(k3_pin);
unsigned long k3_time = checkButtonPressTime(k3_state, k3_prevState, last_press_k3, k3_time_press);
if(k3_time != 0 && k3_time < 1000){
Serial.println("minus hour");
reduceTime();
}
}
if(!timerScreen){
showActualTime();
if (doneTimerSettings) {
DateTime now = RTC.now();
int comparison1 = compareTimes(now.hour(), now.minute(), now.second(), t_on_off[0], t_on_off[1], t_on_off[2]);
int comparison2 = compareTimes(now.hour(), now.minute(), now.second(), t_on_off[3], t_on_off[4], t_on_off[5]);
if ((comparison1 == 1) && (comparison2 == -1)) {
pullRelayHIGH();
} else {
pullRelayLOW();
}
}
}
}
void blinkScreen() {
unsigned long currentMillisScreenBlink = millis();
if (currentMillisScreenBlink - previousMillisScreenBlink >= 1000) {
previousMillisScreenBlink = currentMillisScreenBlink;
switch (currentTimerValueToChange)
{
case 0:
lcd.setCursor(0, 0);
snprintf(tOnString, sizeof(tOnString), "T.ON= :%02u:%02u", t_on_off[1], t_on_off[2]);
lcd.print(tOnString);
break;
case 1:
lcd.setCursor(0, 0);
snprintf(tOnString, sizeof(tOnString), "T.ON=%02u: :%02u", t_on_off[0], t_on_off[3]);
lcd.print(tOnString);
break;
case 2:
lcd.setCursor(0, 0);
snprintf(tOnString, sizeof(tOnString), "T.ON=%02u:%02u: ", t_on_off[0], t_on_off[1]);
lcd.print(tOnString);
break;
case 3:
lcd.setCursor(0, 1);
snprintf(tOffString, sizeof(tOnString), "T.OFF= :%02u:%02u", t_on_off[4], t_on_off[5]);
lcd.print(tOffString);
break;
case 4:
lcd.setCursor(0, 1);
snprintf(tOffString, sizeof(tOnString), "T.OFF=%02u: :%02u", t_on_off[3], t_on_off[5]);
lcd.print(tOffString);
break;
case 5:
lcd.setCursor(0, 1);
snprintf(tOffString, sizeof(tOnString), "T.OFF=%02u:%02u: ", t_on_off[3], t_on_off[4]);
lcd.print(tOffString);
break;
default:
showTimerScreen();
break;
};
}
else if(currentMillisScreenBlink - previousMillisScreenBlink >= 300){
showTimerScreen();
}
}
void increaseTime(){
if(currentTimerValueToChange == 0 || currentTimerValueToChange == 3) {
t_on_off[currentTimerValueToChange] = t_on_off[currentTimerValueToChange] + 1;
if (t_on_off[currentTimerValueToChange] > 23 ) {
t_on_off[currentTimerValueToChange] = 23;
}
}
else {
if (t_on_off[currentTimerValueToChange] == 59) {
t_on_off[currentTimerValueToChange] = 59;
}
else t_on_off[currentTimerValueToChange] = t_on_off[currentTimerValueToChange] + 1;
}
}
void reduceTime(){
t_on_off[currentTimerValueToChange] <= 0 ? t_on_off[currentTimerValueToChange] = 0 : t_on_off[currentTimerValueToChange] = t_on_off[currentTimerValueToChange] - 1;
}
void fixTimeDisplay(uint8_t second,uint8_t minute){
if(second == 0){
if(newMinute == false){
lcd.clear();
newMinute = true;
}
}
else newMinute = false;
if(minute == 0){
if(newHour == false){
lcd.clear();
newHour = true;
}
}
else newHour = false;
}
unsigned long checkButtonPressTime(boolean buttonState, boolean &prevState, unsigned long &lastPress, unsigned long &timePress){
if (buttonState == HIGH && prevState == LOW) {
prevState = HIGH;
unsigned long buttonPressDuration = millis() - timePress;
return buttonPressDuration;
}
if (buttonState == LOW && prevState == HIGH && millis() - lastPress > 50) {
prevState = LOW;
lastPress = millis();
timePress = millis();
}
return 0;
}
void showTimerScreen(){
lcd.setCursor(0, 0);
snprintf(tOnString, sizeof(tOnString), "T.ON=%02u:%02u:%02u", t_on_off[0], t_on_off[1], t_on_off[2]);
lcd.print(tOnString);
lcd.setCursor(0, 1);
snprintf(tOffString, sizeof(tOffString), "T.OFF=%02u:%02u:%02u", t_on_off[3], t_on_off[4], t_on_off[5]);
lcd.print(tOffString);
}
void showActualTime(){
DateTime now = RTC.now();
fixTimeDisplay(now.second(),now.minute());
lcd.setCursor(0, 0);
lcd.print(now.hour()); lcd.print(":");
lcd.print(now.minute()); lcd.print(":");
lcd.print(now.second());
}
int compareTimes(uint8_t t1_hour, uint8_t t1_minute, uint8_t t1_second, uint8_t t2_hour, uint8_t t2_minute, uint8_t t2_second)
{
if (t1_hour < t2_hour)
return -1;
else if (t1_hour > t2_hour)
return 1;
if (t1_hour == t2_hour)
{
if (t1_minute < t2_minute)
return -1;
else if (t1_minute > t2_minute)
return 1;
else if (t1_second < t2_second)
return -1;
else if(t1_second > t2_second)
return 1;
else
return 0;
}
}
void pullRelayHIGH() {
if(relay_state != HIGH){
digitalWrite(relay_pin, HIGH);
relay_state = HIGH;
Serial.println("RELAY ON");
}
}
void pullRelayLOW() {
if(relay_state != LOW){
digitalWrite(relay_pin, LOW);
relay_state = LOW;
Serial.println("RELAY OFF");
}
}