#include "RTClib.h"
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
#define LuzVerm 4 //Pino PWM luz vermelha
#define LuzVerd 2 //Pino PWM luz verde
#define LuzAzul 15 //Pino PWM luz azul
#define kyPinA 13 //CLK
#define kyPinB 12 //DT
#define kyBtn 14 //SW
#define PwmRange 1023 //Resolução PWM
#define PI 3.14159
#define EPGERAL 0//EEPROM DE USO GERAL. BIT 0=MODO
#define EPHLIGAR 1//EEPROM HORA DE LIGAR
#define EPMLIGAR 2//EEPROM MINUTO DE LIGAR
#define EPDLIGAR 3//EEPROM DURAÇÃO DE LIGAR
#define EPHDESL 4//EEPROM HORA DE DESLIGAR
#define EPMDESL 5//EEPROM MINUTO DE DESLIGA
#define EPDDESL 6//EEPROM DURAÇÃO DE DESLIGAR
RTC_DS1307 rtc;
LiquidCrystal_I2C lcd(0x27, 16, 2);
void GirarKnobInt();
void Knob();
void PressBtnInt();
void PressBtn();
void MostrarDisplay();
void Menu(byte p); //Mostrar menu no display
void PrintMenu(int y);
void Alterar(byte x); //Entra no estado de alteração de dados e coloca o cursor no local indicado. Caso seja 0, desativa estado de alteração.
void MenuIn(byte a); //Entar no menu indicado. Indica o menu para o qual deve voltar.
void GradBranco(int valor);
void GradNatural(int valor);
void GradMarinho(int valor);
void GradCalculo();
//char *mPrincipal[]={"Modo","Pré-Definidas","Personalizada","Intensidade","Ligar","Desligar","Configurações","Sair"};
//char *mCores[]={"Vermel","Verde","Azul","Magent","Ciano","Amarel","Branco"};
//char *mPerson[]={"Vermelho","Verde","Azul","Voltar"};
//char *mLigar[]={"Hora","Duração","Estilo","Voltar"};
//char *mDesl[]={"Hora","Duração","Estilo","Voltar"};
//char *mConfig[]={"Hora","Data","Rede SSID","Rede Senha","Informações","Voltar"};
byte limMenu[9]={0,4,3,2,2,5,0,0,0};
int menu=0;
int mPos=0;
int giro;
bool interagindo=false;
bool alterando=false;
bool botao=false;
String txt;
//byte corPre=0;
//int intensidade=0;
int aux;
byte aux2;
int lastTime,lastTrigger=0;
//Menu
bool modo; //manual ou automatico: 0-Manual 1-Automatico
//no modelo simples, 0-Doce 1-Marinho
int hora, minuto, segundo;
int hora2,min2;
int dia, mes, ano;
int dia2,mes2,ano2;
//String rede;
DateTime now;
//Automatico
bool estado; //Define se led (iluminação) está ligado ou desligado 0=Desligado - 1=Ligado
int grad; //GRADIENTE - Intensidade para ligar ou desligar a iluminação gradativamente
//Ligar
unsigned int hLigar[2]; //hora[0] e minuto[1] para ligar
unsigned int dLigar; //duração em minutos para ligar
//int eLigar; //estilo para ligar. 0=Branco - 1=Céu natural - 2=Azul primeiro
//Desligar
unsigned int hDesl[2]; //hora[0] e minuto[1] para desligar
unsigned int dDesl; //duração em minutos para desligar
//int eDesl; //estilo para ligar. 0=Branco - 1=Céu natural - 2=Azul primeiro
//int rgb[3];// pRed,pGreen,pBlue; //Mistura de cores para personaluizado
void setup() {
//put your setup code here, to run once:
Serial.begin(115200);
//Serial.println("Hello, ESP32!");
EEPROM.begin(7);
rtc.begin(); // Inicia o módulo RTC
lcd.init(); // Inicia o Display
//lcd.backlight(); // Inicia o Backlight
lcd.noBacklight();
lcd.noCursor();
//Pegar valores da EEPROM
if(bitRead(EEPROM.read(EPGERAL),0))modo=1;
else modo=0;
LEREEPROM:
hLigar[0]=EEPROM.read(EPHLIGAR);
hLigar[1]=EEPROM.read(EPMLIGAR);
dLigar=EEPROM.read(EPDLIGAR);
hDesl[0]=EEPROM.read(EPHDESL);
hDesl[1]=EEPROM.read(EPMDESL);
dDesl=EEPROM.read(EPDDESL);
if(max(hLigar[0],hDesl[0])>23||max(hLigar[1],hDesl[1])>59||max(dLigar,dDesl)>120){
EEPROM.write(EPHLIGAR,0);
EEPROM.write(EPMLIGAR,0);
EEPROM.write(EPDLIGAR,0);
EEPROM.write(EPHDESL,0);
EEPROM.write(EPMDESL,0);
EEPROM.write(EPDDESL,0);
EEPROM.commit();
goto LEREEPROM;
}
LerRTC();
if(ano<2023||ano>2099){
rtc.adjust(DateTime(2023,1,1,0,0,0));
}
lastTrigger=millis();
menu=0;
mPos=0;
giro=0;
interagindo=false;
alterando=false;
botao=false;
pinMode(LuzVerd,OUTPUT);
pinMode(LuzAzul,OUTPUT);
pinMode(LuzVerm,OUTPUT);
pinMode(kyPinA,INPUT);
pinMode(kyPinB,INPUT);
pinMode(kyBtn,INPUT);
attachInterrupt(digitalPinToInterrupt(kyPinA),GirarKnobInt,FALLING);
attachInterrupt(digitalPinToInterrupt(kyPinB),GirarKnobInt,FALLING);
attachInterrupt(digitalPinToInterrupt(kyBtn),PressBtnInt,RISING);
menu=0;
}
void loop() {
lastTime=millis();
if(lastTime<lastTrigger)lastTrigger=0;
if((lastTime-lastTrigger)>=1000){
LerRTC();
if(!interagindo)MostrarDisplay();
lastTrigger=lastTime;
}
//put your main code here, to run repeatedly:
delay(100); // this speeds up the simulation
if(botao)PressBtn();
//Serial.println(giro);
if(giro)Knob();
//GradCalculo();
//Serial.println(hora);
//Serial.println(minuto);
//Serial.println(segundo);
//digitalWrite(LuzVerm,0);
//digitalWrite(LuzVerd,1);
//digitalWrite(LuzAzul,0);
}
void GirarKnobInt(){
if(digitalRead(kyPinA)!=digitalRead(kyPinB)){
giro=digitalRead(kyPinA)?-1:1;
}
//Serial.println(giro);
//return;
}
void Knob(){
if(menu){
//Serial.println(interagindo);
if(interagindo){
//Serial.println(giro);
if(!alterando){
if(giro==1){
if(mPos<limMenu[menu]){
mPos++;
Menu(0);
}
}
else if(mPos>0){
mPos--;
Menu(0);
}
}
else{
if(menu==1){ //Menu principal
//Serial.println(modo);
if(mPos==0){
modo=!modo;
aux2=15;
}
/*
else if(mPos==1){ //Cor pre-definida
if(giro==1&&corPre<6)corPre++;
else if(giro=-1&&corPre>0)corPre--;
aux2=10;
}
else if(mPos==3){ //Intensidade
if(giro==1){
if(intensidade<100)intensidade++;
}
else if(intensidade>0)intensidade--;
aux2=12;
}*/
else if(mPos==3){
if(giro==1){
if(!aux){
hora2++;
if(hora2>23)hora2-=24;
aux2=11;
}
else{
min2++;
if(min2>59)min2-=60;
aux2=14;
}
}
else{
if(!aux){
hora2--;
if(hora2<0)hora2+=24;
aux2=11;
}
else{
min2--;
if(min2<0)min2+=60;
aux2=14;
}
}
}
}
/*
else if(menu==2){ //Cor personalizada
if(giro==1){
if(rgb[mPos]<255)rgb[mPos]++;
}
else if(rgb[mPos]>0)rgb[mPos]--;
aux2=12;
}*/
else if(menu==3){ //Ligar
if(mPos==0){
if(giro==1){
if(!aux){
if(hLigar[0]<23)hLigar[0]++;
else hLigar[0]=0;
aux2=11;
}
else{
if(hLigar[1]<59)hLigar[1]++;
else hLigar[1]=0;
aux2=14;
}
}
else{
if(!aux){
if(hLigar[0]>0)hLigar[0]--;
else hLigar[0]=23;
aux2=11;
}
else{
if(hLigar[1]>0)hLigar[1]--;
else hLigar[1]=59;
aux2=14;
}
}
}
else if(mPos==1){
if(giro==1){
if(dLigar<120)dLigar++;
}
else if(dLigar>0)dLigar--;
aux2=10;
}
/*
else if(mPos==2){
if(giro==1){
if(eLigar<3)eLigar++;
}
else if(eLigar>0)eLigar--;
}*/
}
else if(menu==4){ //Desligar
if(mPos==0){
if(giro==1){
if(!aux){
if(hDesl[0]<23)hDesl[0]++;
else hDesl[0]=0;
aux2=11;
}
else{
if(hDesl[1]<59)hDesl[1]++;
else hDesl[1]=0;
aux2=14;
}
}
else{
if(!aux){
if(hDesl[0]>0)hDesl[0]--;
else hDesl[0]=23;
aux2=11;
}
else{
if(hDesl[1]>0)hDesl[1]--;
else hDesl[1]=59;
aux2=14;
}
}
}
else if(mPos==1){
if(giro==1){
if(dDesl<120)dDesl++;
}
else if(dDesl>0)dDesl--;
aux2=10;
}
/*
else if(mPos==2){
if(giro==1){
if(eDesl<3)eDesl++;
}
else if(eDesl>0)eDesl--;
}*/
}
Menu(aux2);
}
}
}
giro=0;
}
void PressBtnInt(){
botao=true;
}
void PressBtn(){
botao=false;
if(menu==0){ //Entrar no menu principal
interagindo=true;
lcd.backlight();
MenuIn(1);
lcd.cursor();
lcd.blink();
}
else if(menu==1){ //Menu principal
if(mPos==1)MenuIn(3);
/*
else if(mPos==4){
aux=0;
MenuIn(3);
}*/
else if(mPos==2)MenuIn(4);
else if(mPos==3){
if(!alterando){
hora2=hora;
min2=minuto;
aux=0;
Alterar(11);
}
else if(aux==0){
aux=1;
Alterar(14);
}
else{
hora=hora2;
minuto=min2;
rtc.adjust(DateTime(ano,mes,dia,hora,minuto,0));
aux=0;
Alterar(0);
}
}
else if(mPos==4){
menu=0;
mPos=0;
interagindo=false;
alterando=false;
MostrarDisplay();
lcd.noCursor();
}
else{ //mPos==0
if(!alterando)Alterar(15);
else Alterar(0);
}
}
/*
else if(menu==2){ //Personalizada
if(mPos<3){alterando?Alterar(0):Alterar(12);}
else MenuIn(1);
}*/
else if(menu==3||menu==4){ //Ligar / Desligar
if(mPos==0){ //Ajuste de hora
if(!alterando){
aux=0;
Alterar(11);
}
else{
if(aux==0){
aux=1;
Alterar(14);
}
else{
if(menu==3){
EEPROM.write(EPHLIGAR,hLigar[0]);
EEPROM.write(EPMLIGAR,hLigar[1]);
}
else{
EEPROM.write(EPHLIGAR,hDesl[0]);
EEPROM.write(EPMLIGAR,hDesl[1]);
}
EEPROM.commit();
aux=0;
Alterar(0);
}
}
}
else if(mPos==1){//Ajuste da duração
if(alterando){
if(menu==3)EEPROM.write(EPDLIGAR,dLigar);
else EEPROM.write(EPDDESL,dDesl);
EEPROM.commit();
Alterar(0);
}
else Alterar(10);
}
//else if(mPos==2)alterando?Alterar(0):Alterar(9); //Ajuste do estilo
else MenuIn(1); //Voltar para menu principal
}
/*
else if(menu==5){ //Configurações
if(mPos==0){ //Ajuste de hora
if(!alterando){
aux=0;
Alterar(11);
}
else{
if(aux==0){
aux=1;
Alterar(14);
}
else{
aux=0;
Alterar(0);
}
}
}
else if(mPos==1){ //Ajustar data
if(!alterando){
aux=1;
Alterar(6);
}
else{
if(aux==1){
aux=2;
Alterar(9);
}
else if(aux==2){
aux=3;
Alterar(12);
}
else{
aux=1;
Alterar(0);
}
}
}
else if(mPos==2)MenuIn(6); //Rede SSID
else if(mPos==3)MenuIn(7); //Rede Senha
else if(mPos==4)MenuIn(8); //Rede Informações
else MenuIn(0);
}
else if(menu==6){ //Rede SSID
MenuIn(5);
}
else if(menu==7){ //Rede Senha
MenuIn(5);
}
else{ //Rede Informações
MenuIn(5);
}*/
}
void MostrarDisplay(){
if(menu==0){
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(hora);
lcd.print(":");
lcd.print(minuto);
lcd.print(':');
lcd.print(segundo);
}
}
void Menu(byte p){
lcd.clear();
PrintMenu(0);
if(mPos!=limMenu[menu]){
mPos++;
PrintMenu(1);
mPos--;
}
lcd.setCursor(p,0);
}
void PrintMenu(int y){
if(menu==1){ //Menu principal
if(mPos==0){
txt="Modo ";
txt=txt+(modo?" Doce":"Marinho");
}
/*
else if(mPos==1){
txt="Pre-Def ";
txt=txt+mCores[corPre];
}
else if(mPos==2) txt="Personalizada";
else if(mPos==3){
txt="Intens ";
txt=txt+(intensidade<10?" ":(intensidade<100?" ":""))+intensidade+'%';
}*/
else if(mPos==1){
txt="Ligar ";
txt=txt+(hLigar[0]<10?"0":"")+hLigar[0]+":"+(hLigar[1]<10?"0":"")+hLigar[1];
}
else if(mPos==2){
txt="Desligar ";
txt=txt+(hDesl[0]<10?"0":"")+hDesl[0]+":"+(hDesl[1]<10?"0":"")+hDesl[1];
}
//else if(mPos==3) txt="Configurações";
else if(mPos==3) {
txt="Hora ";
if(!alterando){
txt=txt+(hora<10?"0":"")+hora+":"+(minuto<10?"0":"")+minuto;
}
else{
txt=txt+(hora2<10?"0":"")+hora2+":"+(min2<10?"0":"")+min2;
}
}
else if(mPos==4) txt="Sair";
}
/*
else if(menu==2){ //Cor Personalizada
if(mPos==0){
txt="Vermelho ";
txt=txt+(rgb[0]<10?" ":(rgb[0]<100?" ":""))+rgb[0];
}
else if(mPos==1){
txt="Verde ";
txt=txt+(rgb[1]<10?" ":(rgb[1]<100?" ":""))+rgb[1];
}
else if(mPos==2){
txt="Azul ";
txt=txt+(rgb[2]<10?" ":(rgb[2]<100?" ":""))+rgb[2];
}
else if(mPos==3)txt="Sair";
}*/
else if(menu==3){ //Ligar
if(mPos==0){
txt="Hora ";
txt=txt+(hLigar[0]<10?"0":"")+hLigar[0]+":"+(hLigar[1]<10?"0":"")+hLigar[1];
}
else if(mPos==1){
txt="Duração ";
txt=txt+(dLigar<10?" ":(dLigar<100?" ":""))+dLigar+"min";
}
/*
else if(mPos==2){
txt="Estilo ";
txt=txt+(eLigar==0?" Branco":(eLigar==1?"Natural":"Marinho"));
}*/
else if(mPos==2)txt="Sair";
}
else if(menu==4){ //Desligar
if(mPos==0){
txt="Hora ";
txt=txt+(hDesl[0]<10?"0":"")+hDesl[0]+":"+(hDesl[1]<10?"0":"")+hDesl[1];
}
else if(mPos==1){
txt="Duração ";
txt=txt+(dDesl<10?" ":(dDesl<100?" ":""))+dDesl+"min";
}
/*
else if(mPos==2){
txt="Estilo ";
txt=txt+(eDesl==0?" Branco":(eDesl==1?"Natural":"Marinho"));
}*/
else if(mPos==2)txt="Sair";
}
/*
else if(menu==5){ //Configurações
if(mPos==0){
txt="Hora ";
txt=txt+(hora<10?"0":"")+hora+":"+(minuto<10?"0":"")+minuto;
}
else if(mPos==1){
txt="Data ";
txt=txt+(dia<10?" ":"")+dia+"/"+(mes<10?" ":"")+mes+"/"+ano;
}
else if(mPos==2){
txt="Rede ";
txt=txt+rede.c_str();
}
else if(mPos==3){
txt="Senha ";
txt=txt+rede.c_str();
}
else if(mPos==4)txt="Informações";
else if(mPos==5)txt="Sair";
}
else if(menu==6){ //Rede
if(mPos==0)txt="Sair";
}
else if(menu==7){ //Senha
if(mPos==0)txt="Sair";
}
else if(menu==8){ //Informações de Rede
if(mPos==0)txt="Sair";
}*/
lcd.setCursor(0,y);
lcd.print(txt.c_str());
}
void Alterar(byte x){
alterando=(x?true:false);
lcd.setCursor(x,0);
}
void MenuIn(byte a){
menu=a;
mPos=0;
Menu(0);
}
void LerRTC(){
now = rtc.now();
hora = now.hour(); // Chama o horário de Hor
minuto = now.minute(); // Chama o minuto de Min
segundo = now.second(); // Chama os segundos de Seg
dia=now.day();
mes=now.month();
ano=now.year();
}
void GradBranco(int valor)
{
analogWrite(LuzVerm,valor);
analogWrite(LuzVerd,valor);
analogWrite(LuzAzul,valor);
}
void GradNatural(int valor)
{/*
float intens=float(valor);
float fRed,fBlue;
intens=intens/PwmRange*PI/2;
fRed=sen(intens)*PwmRange;
fBlue=(sen(intens-PI/2)+1)*PwmRange;
analogWrite(LuzVerm,int(fRed));
analogWrite(LuzVerd,valor);
analogWrite(LuzAzul,int(fBlue));*/
}
void GradMarinho(int valor)
{
}
void GradCalculo(){/*
estado=TRUE; //Ativa iluminação por padrão
aux=hDesl[0]; //aux recebe a hora que desliga
aux2=hora; //aux2 recebe a hora atual
if(aux<hLigar[0])aux+=24; //Ajusta aux para ficar a hora de desligar sempre depois da hora de ligar para comparação
if(aux2<hLigar[0])aux2+=24; //Ajusta aux2 para ficar sempre acima do horário de ligar, para comparação. Horário de ligar será a referência de tempo 0
if(aux2==hLigar[0]&&hLigar[1]<min)!estado; //Desativa iluminação caso hora de ligar seja a atual, porém ainda não chegou no minuto de ligar
else if(aux2>aux)!estado; //Desativa iluminação caso já tenha passado do horário de desligar
else if(aux2==aux&&min>=hDesl[1])!estado; //Se estiver na hora de desligar, compara os minutos para saber se deve desligar ou manter ligado ainda
//Define intensidade no modo automático
if(estado){
aux2=(aux2-hLigar[0])*60+min-hLigar[1];
grad=dLigar;
}
else{
aux2=(aux2-aux)*60+min-hDesl[1];
grad=dDesl;
}
if(aux2<grad){
grad=(PwmRange/grad*aux2)+((PwmRange/(grad*60))*seg);
}
else grad=PwmRange;
if(!estado)grad=PwmRange-grad;
//Seleciona função de gradiente
if(grad>0&&grad<PwmRange){
if(estado){
if(modo==0)GradNatural(grad);
else if(modo==1)GradMarinho(grad);
}
}*/
/*
//Liga a ventoinha
if(grad==0)digitalWrite(Vent,HIGH);
else digitalWrite(Vent,LOW);
*/
}