//Nicolas Jarpa
//Multiple Timer RTC3231+LCD+Single Relay+Select day+eeprom
#include <EEPROM.h>
#include <RTClib.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4);
RTC_DS3231 RTC;
char daysOfTheWeek[7][20] = {"DOMINGO", "SEGUNDA-FEIRA", "TERCA-FEIRA", "Quarta-feira", "Quinta-feira", "Sexta-feira", "Sabado"};
//-----------------------//
//------Variáveis--------//
//-----------------------//
//------Primeiro temporizador
byte onhour1;
byte onmin1;
byte onsec1;
byte offhour1;
byte offmin1;
byte offsec1;
//------Dias da semana
boolean DOM;
boolean SEG;
boolean TER;
boolean QUA;
boolean QUI;
boolean SEX;
boolean SAB;
//------Páginas ou menus
int page_counter=1;
int subpage1_counter=0;
int subpage2_counter=0;
//-------Para converter o relógio em um único número
unsigned long Time;
unsigned long Hour;
unsigned long Min;
unsigned long Sec;
//------Para converter o primeiro temporizador em número único
unsigned long on_Time1;
unsigned long on_hour1;
unsigned long on_min1;
unsigned long on_sec1;
unsigned long off_Time1;
unsigned long off_hour1;
unsigned long off_min1;
unsigned long off_sec1;
//-------Botões de pressão estado atual/último
boolean current_up = LOW;
boolean last_up=LOW;
boolean current_sel = LOW;
boolean last_sel = LOW;
boolean last_down = LOW;
boolean current_down = LOW;
//-------Pins
byte Relay1 =13;//Relé para pino 13
int up=2; //Botão para cima para fixar 2
int sel=3; //Selecione o botão para fixar 3
int down=4; //Botão para baixo no pino 4
//Caractere de retorno personalizado
byte back[8] = {
0b00100,
0b01000,
0b11111,
0b01001,
0b00101,
0b00001,
0b00001,
0b11111
};
//Caractere de seta personalizado
byte arrow[8] = {
0b01000,
0b00100,
0b00010,
0b11111,
0b00010,
0b00100,
0b01000,
0b00000
};
void setup() {
pinMode(Relay1, OUTPUT);
Wire.begin();
RTC.begin();
lcd.init();
lcd.backlight();
lcd.clear();
lcd.createChar(1, back);//Personagens personalizados
lcd.createChar(2, arrow);
//--------valores de leitura eePROM-------//
//------Primeiro temporizador
onhour1=EEPROM.read(0);
onmin1=EEPROM.read(1);
onsec1=EEPROM.read(2);
offhour1=EEPROM.read(3);
offmin1=EEPROM.read(4);
offsec1=EEPROM.read(5);
DOM=EEPROM.read(6);
SEG=EEPROM.read(7);
TER=EEPROM.read(8);
QUA=EEPROM.read(9);
QUI=EEPROM.read(10);
SEX=EEPROM.read(11);
SAB=EEPROM.read(12);
}
//---- Função de de-bouncing para todos os botões----//
boolean debounce(boolean last, int pin)
{
boolean current = digitalRead(pin);
if (last != current)
{
delay(10);
current = digitalRead(pin);
}
return current;
}
void loop() {
current_up = debounce(last_up, up); //Botão Debounce para cima
current_sel = debounce(last_sel, sel); //Botão Debounce para Selecionar
current_down = debounce(last_down, down); //Botão Debounce para baixo
DateTime now = RTC.now(); // Chamada do relógio
now = RTC.now();
//-----Funções para cima/para baixo para mover as páginas principais------///
if(subpage1_counter==0 && subpage2_counter==0){ //botões para cima/para baixo ativados se os contadores de subpáginas forem 0, desativados se 1,2..etc para funcionar em submenus
//Page Up
if (last_up== LOW && current_up == HIGH){ //Botão para cima pressionado
lcd.clear(); //Limpe o lcd se a página for alterada para imprimir uma nova
if(page_counter <4){ //Contador de páginas nunca superior a 4 (total de páginas)
page_counter ++; //Página acima
}
else{
page_counter= 1; //Se for maior que 4 (última página) vá para a página principal
}
}
last_up = current_up; //Último estado do botão Economizar
//Page Down
if (last_down== LOW && current_down == HIGH){//Botão para baixo pressionado
lcd.clear(); //Limpar lcd se a página for alterada para imprimir uma nova
if(page_counter >1){ //Contador de páginas nunca inferior a 1
page_counter --; //Página para baixo
}
else{
page_counter= 4; //Se for menor que 1 (primeira página), vá para a última página
}
}
last_down = current_down; //Último estado do botão Salvar
}
//------------Exibição e controle de páginas e submenus----------//
switch (page_counter){
case 1: //Conteúdo da página principal
last_sel=current_sel; //Salvar o último estado do botão de seleção quando saltarmos da tela de salvamento
lcd.setCursor(0,0);
lcd.print(" TEMPORIZADOR ");
lcd.setCursor(3,2);
lcd.print(daysOfTheWeek[now.dayOfTheWeek()]);
//--------Mostrar hora no LCD
lcd.setCursor(6,3);
if(now.hour() < 10)
{
lcd.print("0");
}
lcd.print(now.hour(), DEC); //Hora de impressão
lcd.print(':');
if(now.minute() < 10)
{
lcd.print("0");
}
lcd.print(now.minute(), DEC); //Imprimir min.
lcd.print(':');
if(now.second() < 10)
{
lcd.print("0");
}
lcd.print(now.second(), DEC); //Imprimir segundo
//case 1
break;
case 2: //Conteúdo e funções da página 2
lcd.setCursor(0,0);
lcd.print(" TEMPORIZADOR ");
lcd.setCursor(3,2);
lcd.print("ON");
lcd.setCursor(1,3);
lcd.write(byte(1));
lcd.setCursor(3,3);
lcd.print("OFF");
lcd.setCursor(7,2); //Printing on/off values
if(onhour1<10){
lcd.print("0");
}
lcd.print(onhour1);
lcd.setCursor(10,2);
if(onmin1<10){
lcd.print("0");
}
lcd.print(onmin1);
lcd.setCursor(13,2);
if(onsec1<10){
lcd.print("0");
}
lcd.print(onsec1);
lcd.setCursor(7,3);
if(offhour1<10){
lcd.print("0");
}
lcd.print(offhour1);
lcd.setCursor(10,3);
if(offmin1<10){
lcd.print("0");
}
lcd.print(offmin1);
lcd.setCursor(13,3);
if(offsec1<10){
lcd.print("0");
}
lcd.print(offsec1);
//--------------Modifying on/off values-------//
// Sub counter control
if (last_sel== LOW && current_sel == HIGH){ //select button pressed
if(subpage1_counter <7){ // subpage counter never higher than 7 (total of items)
subpage1_counter ++; //subcounter to move beetwen submenu
}
else{ //If subpage higher than 7 (total of items) return to first item
subpage1_counter=1;
}
}
last_sel=current_sel; //Save last state of select button
//First item control(subpage_counter =1) onhour1
if(subpage1_counter==1){
lcd.setCursor(0,3); //Delete last arrow position (back)
lcd.print(" ");
lcd.setCursor(6,2); //Place arrow in front of selected item
lcd.write(byte(2));
//Move item + or -
if (last_up== LOW && current_up == HIGH){ //Up
if(onhour1 < 23){
onhour1 ++;
}
else{
onhour1 =0;
}
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){//Down
if(onhour1 >0){
onhour1 --;
}
else{
onhour1=23;
}
}
last_down=current_down;
}//subpage1_counter 1
//Second item control(subpage_counter =2) onmin1
if(subpage1_counter==2){
lcd.setCursor(6,2); //Delete last arrow position (onhour1)
lcd.print(" ");
lcd.setCursor(9,2); //Place arrow in front of selected item
lcd.write(byte(2));
//Move item + or -
if (last_up== LOW && current_up == HIGH){ //Up
if(onmin1 < 59){
onmin1 ++;
}
else{
onmin1 =0;
}
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){//Down
if(onmin1 >0){
onmin1 --;
}
else{
onmin1=59;
}
}
last_down=current_down;
}//subpage1_counter 2
//Tirth item control(subpage_counter =3) onsec1
if(subpage1_counter==3){
lcd.setCursor(9,2); //Delete last arrow position (onmin1)
lcd.print(" ");
lcd.setCursor(12,2); //Place arrow in front of selected item
lcd.write(byte(2));
//Move item + or -
if (last_up== LOW && current_up == HIGH){ //Up
if(onsec1 < 59){
onsec1 ++;
}
else{
onsec1 =0;
}
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){//Down
if(onsec1 >0){
onsec1 --;
}
else{
onsec1=59;
}
}
last_down=current_down;
}//subpage1_counter 3
//fourth item control(subpage_counter =4) offhour1
if(subpage1_counter==4){
lcd.setCursor(12,2); //Delete last arrow position (onsec1)
lcd.print(" ");
lcd.setCursor(6,3); //Place arrow in front of selected item
lcd.write(byte(2));
//Move item + or -
if (last_up== LOW && current_up == HIGH){ //Up
if(offhour1 < 23){
offhour1 ++;
}
else{
offhour1 =0;
}
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){//Down
if(offhour1 >0){
offhour1 --;
}
else{
offhour1=23;
}
}
last_down=current_down;
}//subpage1_counter 4
//fifth item control(subpage_counter =5) offmin1
if(subpage1_counter==5){
lcd.setCursor(6,3); //Delete last arrow position (offhour1)
lcd.print(" ");
lcd.setCursor(9,3); //Place arrow in front of selected item
lcd.write(byte(2));
//Move item + or -
if (last_up== LOW && current_up == HIGH){ //Up
if(offmin1 < 59){
offmin1 ++;
}
else{
offmin1 =0;
}
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){//Down
if(offmin1 >0){
offmin1 --;
}
else{
offmin1=59;
}
}
last_down=current_down;
}//subpage1_counter 5
//sixth item control(subpage_counter =6) offsec1
if(subpage1_counter==6){
lcd.setCursor(9,3); //Delete last arrow position (offmin1)
lcd.print(" ");
lcd.setCursor(12,3); //Place arrow in front of selected item
lcd.write(byte(2));
//Move item + or -
if (last_up== LOW && current_up == HIGH){ //Up
if(offsec1 < 59){
offsec1 ++;
}
else{
offsec1 =0;
}
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){//Down
if(offsec1 >0){
offsec1 --;
}
else{
offsec1=59;
}
}
last_down=current_down;
}//subpage1_counter 6
//seventh item control(subpage_counter =7) back
if(subpage1_counter==7){
lcd.setCursor(12,3); //Delete last arrow position (offsec1)
lcd.print(" ");
lcd.setCursor(0,3); //Place arrow in front of selected item
lcd.write(byte(2));
//Move item + or -
if (last_up== LOW && current_up == HIGH){ //Up
lcd.setCursor(0,3); //Delete last arrow position (back) to exit
lcd.print(" ");
subpage1_counter=0; //Exit submenu. Up/down butons enabled to move main pages
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){//Down
lcd.setCursor(0,3); //Delete last arrow position (back)
lcd.print(" ");
subpage1_counter=1; //Go to first item (onhour1)
}
last_down=current_down;
}//subpage1_counter 7
//case 2
break;
case 3: //Content and funtions of page 3
lcd.setCursor(0,0);
lcd.print(" TEMPORIZADOR ");
lcd.setCursor(1,2);
lcd.print("SEG");
lcd.print(SEG);
lcd.setCursor(6,2);
lcd.print("TER");
lcd.print(TER);
lcd.setCursor(11,2);
lcd.print("QUA");
lcd.print(QUA);
lcd.setCursor(18,2);
lcd.write(byte(1));
lcd.setCursor(1,3);
lcd.print("QUI");
lcd.print(QUI);
lcd.setCursor(6,3);
lcd.print("SEX");
lcd.print(SEX);
lcd.setCursor(11,3);
lcd.print("SAB");
lcd.print(SAB);
lcd.setCursor(16,3);
lcd.print("DOM");
lcd.print(DOM);
//------Modifying days states
// Sub counter control
if (last_sel== LOW && current_sel == HIGH){ //select button pressed
if(subpage2_counter <8){ // subpage counter never higher than 8 (total of items)
subpage2_counter ++; //subcounter to move beetwen submenu
}
else{ //If subpage higher than 8 (total of items) return to first item
subpage2_counter=1;
}
}
last_sel=current_sel; //Save last state of select button
//------Days enabled=1 disabled=0.Up button to set 1 , down button to set 0
//First item to control (subpage2_counter=1) Mon1
if(subpage2_counter ==1){
lcd.setCursor(17,2); //Excluir a última posição da seta (voltar)
lcd.print(" ");
lcd.setCursor(0,2); //Coloque a seta na frente do item selecionado
lcd.write(byte(2));
if (last_up== LOW && current_up == HIGH){ //Acima
SEG=1;
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){//Baixo
SEG=0;
}
last_down=current_down;
}//subpágina2 contador 1
//Segundo item a controlar (subpage2_counter=2) Ter1
if(subpage2_counter ==2){
lcd.setCursor(0,2); //Excluir a última posição da seta (SEG1)
lcd.print(" ");
lcd.setCursor(5,2); //Coloque a seta na frente do item selecionado
lcd.write(byte(2));
if (last_up== LOW && current_up == HIGH){ //Acima
TER=1;
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){////Baixo
TER=0;
}
last_down=current_down;
}//subpage2 counter 2
//Tirth item to control (subpage2_counter=3) Wed1
if(subpage2_counter ==3){
lcd.setCursor(5,2); //Excluir a última posição da seta Ter1
lcd.print(" ");
lcd.setCursor(10,2); //Coloque a seta na frente do item selecionado
lcd.write(byte(2));
if (last_up== LOW && current_up == HIGH){ //Up
QUA=1;
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){//Down
QUA=0;
}
last_down=current_down;
}//subpage2 counter 3
//Fourth item to control (subpage2_counter=4) Thu1
if(subpage2_counter ==4){
lcd.setCursor(10,2); //Excluir a última posição da seta Qua1
lcd.print(" ");
lcd.setCursor(0,3); //Coloque a seta na frente do item selecionado
lcd.write(byte(2));
if (last_up== LOW && current_up == HIGH){ //Up
QUI=1;
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){//Down
QUI=0;
}
last_down=current_down;
}//subpage2 counter 4
//Fifth item to control (subpage2_counter=5) Fri1
if(subpage2_counter ==5){
lcd.setCursor(0,3); //Excluir a última posição da seta Qui1
lcd.print(" ");
lcd.setCursor(5,3); //Coloque a seta na frente do item selecionado
lcd.write(byte(2));
if (last_up== LOW && current_up == HIGH){ //Up
SEX=1;
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){//Down
SEX=0;
}
last_down=current_down;
}//subpage2 counter 5
//sixth item to control (subpage2_counter=6) Sat1
if(subpage2_counter ==6){
lcd.setCursor(5,3); //Delete last arrow position Fri1
lcd.print(" ");
lcd.setCursor(10,3); //Place arrow in front of selected item
lcd.write(byte(2));
if (last_up== LOW && current_up == HIGH){ //Up
SAB=1;
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){//Down
SAB=0;
}
last_down=current_down;
}//subpage2 counter 6
//seventh item to control (subpage2_counter=7) Sun1
if(subpage2_counter ==7){
lcd.setCursor(10,3); //Delete last arrow position Sat1
lcd.print(" ");
lcd.setCursor(15,3); //Place arrow in front of selected item
lcd.write(byte(2));
if (last_up== LOW && current_up == HIGH){ //Up
DOM=1;
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){//Down
DOM=0;
}
last_down=current_down;
}//subpage2 counter 7
//eigth item to control (subpage2_counter=8) back
if(subpage2_counter ==8){
lcd.setCursor(15,3); //Excluir a última posição da seta Sun1
lcd.print(" ");
lcd.setCursor(17,2); //Coloque a seta na frente do item selecionado
lcd.write(byte(2));
if (last_up== LOW && current_up == HIGH){ //Up
lcd.setCursor(17,2);
lcd.print(" ");
subpage2_counter=0; //Exit submenu
}
last_up=current_up;
if(last_down== LOW && current_down == HIGH){//Down
subpage2_counter=1;
}
last_down=current_down;
}//subpage2 counter 8
//case 3
break;
case 4: //Page 4 display and functions
lcd.setCursor(0,0);
lcd.print(" PRESSIONE OK ");
lcd.setCursor(0,1);
lcd.print(" PARA SALVAR: ");
if (last_sel== LOW && current_sel == HIGH){ //select button pressed.Save settings to eeprom
EEPROM.write(0, onhour1);
EEPROM.write(1, onmin1);
EEPROM.write(2, onsec1);
EEPROM.write(3, offhour1);
EEPROM.write(4, offmin1);
EEPROM.write(5, offsec1);
EEPROM.write(6, DOM);
EEPROM.write(7, SEG);
EEPROM.write(8, TER);
EEPROM.write(9, QUA);
EEPROM.write(10, QUI);
EEPROM.write(11, SEX);
EEPROM.write(12, SAB);
lcd.clear(); //Print message "SAVED!"
lcd.setCursor(0,1);
lcd.print(" SALVO! ");
delay(2000);
lcd.clear(); //Clear lcd and go to main page
page_counter=1;
}
last_sel=current_sel; //Save last state of select button
//Case 4
break;
}//switch
//-------------Convertion----------//
//---------Converting clock time into single number
Hour = now.hour();
Min = now.minute();
Sec = now.second();
Time = (Hour*10000+ Min*100 +Sec*1);
//--------Converting first timer on/off into single number
on_hour1=onhour1;
on_min1=onmin1;
on_sec1=onsec1;
on_Time1=(on_hour1*10000 + on_min1*100 + on_sec1);
off_hour1=offhour1;
off_min1=offmin1;
off_sec1=offsec1;
off_Time1=(off_hour1*10000 + off_min1*100 + off_sec1);
//----Relay Function per day----//
switch(now.dayOfTheWeek()){ //now.dayOfTheWeek values 1 to 7, monday to sunday
case 1: //If monday
if(SEG==1){
First_Timer();
}
else{
digitalWrite(Relay1, LOW);
}
break;
case 2: //If tuesday
if(TER==1){
First_Timer();
}
else{
digitalWrite(Relay1, LOW);
}
break;
case 3: //If wednesday
if(QUA==1){
First_Timer();
}
else{
digitalWrite(Relay1, LOW);
}
break;
case 4: //If thursday
if(QUI==1){
First_Timer();
}
else{
digitalWrite(Relay1, LOW);
}
break;
case 5: //If friday
if(SEX==1){
First_Timer();
}
else{
digitalWrite(Relay1, LOW);
}
break;
case 6: //If saturday
if(SAB==1){
First_Timer();
}
else{
digitalWrite(Relay1, LOW);
}
break;
case 7: //If sunday
if(DOM==1){
First_Timer();
}
else{
digitalWrite(Relay1, LOW);
}
break;
}//switch day
}//void loop
void First_Timer() { //Custom function to check timer
if(onhour1 == offhour1 && onmin1==offmin1 && onsec1==offsec1){
digitalWrite(Relay1, LOW);
}
if(on_Time1 < off_Time1){
if(Time >= on_Time1 && Time < off_Time1){ //Start
digitalWrite(Relay1, HIGH);
}
else if(Time >= off_Time1) {
digitalWrite(Relay1, LOW);
}
else{
digitalWrite(Relay1, LOW);
}
}
if (on_Time1 > off_Time1){
if(Time >= on_Time1 && Time <= 235959){ //Start
digitalWrite(Relay1, HIGH);
}
else if(Time < off_Time1 ){
digitalWrite(Relay1, HIGH);
}
else if(Time >= off_Time1 && Time < on_Time1){
digitalWrite(Relay1, LOW);
}
}
}//First timer