#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal_I2C.h>
// Inicializamos el RTC y la pantalla LCD I2C
RTC_DS3231 rtc; // Módulo RTC
LiquidCrystal_I2C lcd(0x27, 16, 2); // Pantalla LCD en la dirección I2C 0x26 (16x2)
char daysOfTheWeek[7][12] = {"Dom", "Lun", "Mar", "Mie", "Jue", "Vie", "Sab"};
bool adjustMode = false; // Modo de ajuste (false = no ajustar, true = ajustar)
int adjustField = 0; // Campo que estamos ajustando (0 = hora, 1 = minuto, etc.)
DateTime now; // Variable para almacenar la hora actual del RTC
// Pines de los botones
const int btnAdjustEnter = 2; // Pin D2 para entrar al modo de ajuste
const int btnAdjustExit = 3; // Pin D3 para salir del modo de ajuste
const int btnInc = A0; // Pin A0 para incrementar valores
const int btnDec = A1; // Pin A1 para disminuir valores
const int btnNext = A2; // Pin A2 para moverse al siguiente campo
// Variables para almacenar la fecha y hora ajustables
int year, month, day, hour, minute, second, dayOfWeek;
void setup() {
// Configuramos los pines de los botones
pinMode(btnAdjustEnter, INPUT_PULLUP); // Botón en D2 para entrar al modo de ajuste
pinMode(btnAdjustExit, INPUT_PULLUP); // Botón en D3 para salir del modo de ajuste
pinMode(btnInc, INPUT_PULLUP); // Botón en A0 para incrementar
pinMode(btnDec, INPUT_PULLUP); // Botón en A1 para decrementar
pinMode(btnNext, INPUT_PULLUP); // Botón en A2 para moverse al siguiente campo
// Iniciamos la comunicación I2C y la pantalla LCD
Wire.begin();
lcd.init();
lcd.backlight(); // Encendemos la luz de fondo del LCD
// Verificamos si el RTC está conectado correctamente
if (!rtc.begin()) {
lcd.setCursor(0, 0);
lcd.print("No RTC");
while (1); // Detenemos el programa si no se encuentra el RTC
}
// Si el RTC perdió energía, podemos establecer una fecha predeterminada
if (rtc.lostPower()) {
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // Ajustar la fecha y hora predeterminada
}
lcd.setCursor(0, 0);
lcd.print("Iniciando...");
delay(2000);
lcd.clear();
// Cargamos la hora y fecha actuales desde el RTC
loadTime();
}
void loop() {
// Verificamos si el usuario presionó el botón para entrar al modo de ajuste (D0)
if (digitalRead(btnAdjustEnter) == LOW) {
adjustMode = true; // Activamos el modo de ajuste
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Modo Ajuste");
delay(500); // Pequeño retardo para evitar rebotes en los botones
}
// Verificamos si el usuario presionó el botón para salir del modo de ajuste (D1)
if (adjustMode && digitalRead(btnAdjustExit) == LOW) {
adjustMode = false; // Desactivamos el modo de ajuste
rtc.adjust(DateTime(year, month, day, hour, minute, second)); // Guardamos la hora ajustada en el RTC
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Hora Actualizada");
delay(2000);
lcd.clear();
return;
}
if (adjustMode) {
adjustClock(); // Ejecutamos la función para ajustar la hora
} else {
// Mostramos la hora actual en la pantalla LCD
displayTime();
delay(1000); // Actualizamos cada segundo
}
}
// Cargamos la hora y fecha actuales desde el RTC a variables
void loadTime() {
now = rtc.now(); // Obtenemos la fecha y hora actual desde el RTC
year = now.year();
month = now.month();
day = now.day();
hour = now.hour();
minute = now.minute();
second = now.second();
dayOfWeek = now.dayOfTheWeek(); // Día de la semana
}
// Función para mostrar la hora y fecha en la pantalla LCD
void displayTime() {
now = rtc.now(); // Obtenemos la fecha y hora actual
// Mostramos la hora en formato HH:MM:SS
lcd.setCursor(0, 0);
lcd.print("Hora: ");
lcd.print(now.hour() < 10 ? "0" : ""); lcd.print(now.hour());
lcd.print(":");
lcd.print(now.minute() < 10 ? "0" : ""); lcd.print(now.minute());
lcd.print(":");
lcd.print(now.second() < 10 ? "0" : ""); lcd.print(now.second());
// Mostramos la fecha en formato "Fecha: DD/MM/AA"
lcd.setCursor(0, 1);
lcd.print("Fecha: ");
lcd.print(now.day() < 10 ? "0" : ""); lcd.print(now.day());
lcd.print("/");
lcd.print(now.month() < 10 ? "0" : ""); lcd.print(now.month());
lcd.print("/");
lcd.print(now.year() % 100); // Mostramos sólo los últimos dos dígitos del año
}
// Función para ajustar la hora usando los botones
void adjustClock() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Ajustando...");
while (adjustMode) { // Mientras estemos en modo de ajuste
// Mostramos los valores actuales que se están ajustando
lcd.setCursor(0, 1);
switch (adjustField) {
case 0: lcd.print("Hora: "); lcd.print(hour); break;
case 1: lcd.print("Min: "); lcd.print(minute); break;
case 2: lcd.print("Seg: "); lcd.print(second); break;
case 3: lcd.print("Dia: "); lcd.print(day); break;
case 4: lcd.print("Mes: "); lcd.print(month); break;
case 5: lcd.print("Ano: "); lcd.print(year); break;
}
// Incrementamos o decrementamos el campo seleccionado
if (digitalRead(btnInc) == LOW) {
incrementField(); // Incrementamos el campo
delay(200); // Retardo para evitar rebotes en los botones
}
if (digitalRead(btnDec) == LOW) {
decrementField(); // Decrementamos el campo
delay(200); // Retardo para evitar rebotes
}
// Nos movemos al siguiente campo
if (digitalRead(btnNext) == LOW) {
adjustField = (adjustField + 1) % 6; // Cambiamos de campo (hora, minuto, etc.)
delay(200); // Retardo para evitar rebotes
}
// Salimos del modo de ajuste cuando se presiona el botón en D1
if (digitalRead(btnAdjustExit) == LOW) {
adjustMode = false; // Salimos del modo de ajuste
rtc.adjust(DateTime(year, month, day, hour, minute, second)); // Guardamos la hora ajustada en el RTC
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Hora Actualizada");
delay(2000);
lcd.clear();
return;
}
}
}
// Función para incrementar el valor del campo seleccionado
void incrementField() {
switch (adjustField) {
case 0: hour = (hour + 1) % 24; break; // Incrementar hora
case 1: minute = (minute + 1) % 60; break; // Incrementar minuto
case 2: second = (second + 1) % 60; break; // Incrementar segundo
case 3: day = (day + 1) > 31 ? 1 : day + 1; break; // Incrementar día
case 4: month = (month + 1) > 12 ? 1 : month + 1; break; // Incrementar mes
case 5: year++; break; // Incrementar año
}
}
// Función para decrementar el valor del campo seleccionado
void decrementField() {
switch (adjustField) {
case 0: hour = (hour - 1 + 24) % 24; break; // Decrementar hora
case 1: minute = (minute - 1 + 60) % 60; break; // Decrementar minuto
case 2: second = (second - 1 + 60) % 60; break; // Decrementar segundo
case 3: day = (day - 1 < 1) ? 31 : day - 1; break; // Decrementar día
case 4: month = (month - 1 < 1) ? 12 : month - 1; break; // Decrementar mes
case 5: year--; break; // Decrementar año
}
}