/*
V2.01 Mudanca no teste de reles, adicionado mais reles
e troca da barra
V2.03 Ajuste de data adicionado e mudanca nos reles
V2.035 Correcoes de erros
V2.04 Final Ok
*/
#include <Arduino.h>
#include <Wire.h>
#include <RTClib.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
RTC_DS3231 rtc;
const int LIGAF2_PIN = 2; // BT Liga F2
const int LIGAF1_PIN = 3; // BT Liga F1
const int BUTTON_PIN = 4; // BT Modo
const int buttonPower = 13; // Botão Power
const int BUZZER_PIN = 11; // Buzzer
//--------------------------------------------------------------------
unsigned long lastUpdate = 0;
unsigned long currentMillisH = 0;
const long intervalHora = 300;
// Variáveis para detectar o clique triplo
int clickCount = 0;
int x = 0;
int y = 0;
int h = 0;//Evita travamento do relogio durante o ajuste
bool RelogioAdj = true;
unsigned long lastClickTime = 0;
bool lastButtonState = HIGH;
const long debounceTime = 50;
//------------------------------------------------------------------------
void setup() {
pinMode(LIGAF1_PIN, INPUT_PULLUP);
pinMode(LIGAF2_PIN, INPUT_PULLUP);
pinMode(BUTTON_PIN, INPUT_PULLUP);
pinMode(buttonPower, INPUT_PULLUP);
pinMode(BUZZER_PIN, OUTPUT);
rtc.begin();
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.display();
SelfTest();
}//=============================================
void SelfTest() {/*
const int relePins[] = {5, 6, 7, 8, 9, 10};
const int totalReles = sizeof(relePins) / sizeof(relePins[0]);
// Inicializa os pinos dos relés como saída
for (int i = 0; i < totalReles; i++) {
pinMode(relePins[i], OUTPUT);
digitalWrite(relePins[i], LOW); // Garante que todos comecem desligados
}
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 10);
display.print("Self-Test");
display.display();
for (int i = 0; i < totalReles; i++) {
digitalWrite(relePins[i], HIGH);
delay(200);
digitalWrite(relePins[i], LOW);
delay(200);
digitalWrite(relePins[i], HIGH);
delay(200);
digitalWrite(relePins[i], LOW);
// Atualiza a barra de progresso
int barWidth = (SCREEN_WIDTH * (i + 1)) / totalReles;
display.fillRect(0, 40, barWidth, 10, SSD1306_WHITE);
display.display();
}
delay(500);
display.clearDisplay();
display.setCursor(10, 25);
display.print("Bem Vindo");
display.display();
delay(1000);
display.clearDisplay();
display.display();
*/
}
//=============== Loop ================================
void loop() {
InHora();
}
//============================================================
void InHora() {
if (x == 0) {
if (h ==0){
bool currentButtonState = digitalRead(buttonPower);
if (lastButtonState == LOW && currentButtonState == HIGH && (millis() - lastClickTime > debounceTime)) {
if (millis() - lastClickTime < 2000) {
clickCount++;
} else {
clickCount = 0;
}
lastClickTime = millis();
}
lastButtonState = currentButtonState;
}
if (clickCount >= 4) {
RelogioAdj = true;
y = 1;//Trava o Botao para nao ligar
h = 1;//trava o botao power
AdjHora();
}
}
}
//=====================================================
void AdjHora() {
// Variáveis estáticas mantêm seus valores entre as chamadas da função
static int etapaDeAjuste = 0; // 0:hora, 1:min, 2:dia, 3:mes, 4:ano
static bool ajusteIniciado = false;
static int hora, minuto, dia, mes, ano;
// Timers para debounce dos botões
static unsigned long lastBtSobe = 0;
static unsigned long lastBtDesce = 0;
static unsigned long lastBtModo = 0;
DateTime now = rtc.now();
// Bloco de inicialização: Executa apenas na primeira vez que a função é chamada
if (!ajusteIniciado) {
hora = now.hour();
minuto = now.minute();
dia = now.day();
mes = now.month();
ano = now.year();
etapaDeAjuste = 0; // Garante que o ajuste comece sempre pela hora
ajusteIniciado = true;
}
// BOTÃO DE MODO (BUTTON_PIN): Avança para a próxima etapa de ajuste
if (digitalRead(BUTTON_PIN) == LOW && millis() - lastBtModo > 200) {
lastBtModo = millis();
etapaDeAjuste++; // Avança para a próxima etapa
// Se passou da última etapa (ano), salva tudo e sai do modo de ajuste
if (etapaDeAjuste > 4) {
// Salva os novos valores no RTC
rtc.adjust(DateTime(ano, mes, dia, hora, minuto, now.second()));
// PREPARA PARA SAIR DO MODO DE AJUSTE
ajusteIniciado = false; // Reseta para a próxima vez que o ajuste for chamado
// *** PONTO CRÍTICO: Reseta as variáveis que te mantêm no modo de ajuste ***
clickCount = 0; // Isso fará a condição em InHora() se tornar falsa!
RelogioAdj = false;
y = 0;
h = 0;//Destrava o botao
display.clearDisplay();
display.display();
return; // Sai da função para finalizar o ajuste
}
}
// BOTÃO DE AUMENTAR (LIGAF1_PIN): Incrementa o valor da etapa atual
if (digitalRead(LIGAF1_PIN) == LOW && millis() - lastBtSobe > 200) {
lastBtSobe = millis();
switch (etapaDeAjuste) {
case 0: hora = (hora + 1) % 24; break;
case 1: minuto = (minuto + 1) % 60; break;
case 2: dia = (dia % 31) + 1; break;
case 3: mes = (mes % 12) + 1; break;
case 4: ano++; break;
}
}
// BOTÃO DE DIMINUIR (LIGAF2_PIN): Decrementa o valor da etapa atual
if (digitalRead(LIGAF2_PIN) == LOW && millis() - lastBtDesce > 200) {
lastBtDesce = millis();
switch (etapaDeAjuste) {
case 0: hora = (hora - 1 + 24) % 24; break;
case 1: minuto = (minuto - 1 + 60) % 60; break;
case 2: dia = (dia - 1 < 1) ? 31 : dia - 1; break;
case 3: mes = (mes - 1 < 1) ? 12 : mes - 1; break;
case 4: ano = (ano - 1 < 2020) ? 2099 : ano - 1; break;
}
}
// ATUALIZAÇÃO DO DISPLAY: Mostra os valores e pisca o campo ativo
if (millis() - lastUpdate > 100) {
lastUpdate = millis();
display.clearDisplay();
display.setTextSize(1);
display.setCursor(22, 2);display.print("Ajuste Relogio");
display.setTextSize(2);
display.setCursor(30, 20);
if (hora < 10) display.print("0");
display.print(hora);
display.print(":");
if (minuto < 10) display.print("0");
display.print(minuto);
display.setCursor(5, 43);
if (dia < 10) display.print("0");
display.print(dia);
display.print("/");
if (mes < 10) display.print("0");
display.print(mes);
display.print("/");
display.print(ano);
bool pisca = (millis() / 400) % 2; // Pisca a cada 400ms
if (pisca) {
switch (etapaDeAjuste) { //A L C
//L A
case 0: display.setCursor(31, 30); display.print("--");break;//Hora
case 1: display.setCursor(66, 30); display.print("--");break;//Minuto
case 2: display.setCursor(6, 53); display.print("--");break;//Dia
case 3: display.setCursor(42, 53); display.print("--");break;//Mes
case 4: display.setCursor(77, 53); display.print("----");break;//Ano
}
}
display.display();
}
}