#include <Wire.h>
#include <RTClib.h>
#include <Servo.h>
#include <Keypad.h>
#include <LiquidCrystal.h>
#include <EEPROM.h>
RTC_DS3231 rtc;
Servo compuerta;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int servoPin = 10;
const int buzzer = 8;
const int boton = 7;
const int ledVerde = 22;
const int ledNaranja = 23;
const int ledRojo = 24;
const byte FILAS = 4;
const byte COLS = 4;
char teclas[FILAS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte filasPins[FILAS] = {30,31,32,33};
byte colsPins[COLS] = {34,35,36,37};
Keypad keypad = Keypad(
makeKeymap(teclas),
filasPins,
colsPins,
FILAS,
COLS
);
int horas[8];
int minutos[8];
bool alarmaActiva = false;
bool preAlarmaActiva = false;
bool mostrandoOlvidos = false;
bool compuertaAbiertaManual = false;
bool modoEmergencia = false;
unsigned long tiempoEstado = 0;
unsigned long inicioEmergencia = 0;
int estado = 0;
int olvidos = 0;
int contadorCeros = 0;
unsigned long ultimoCero = 0;
void setup() {
Serial.begin(9600);
Wire.begin();
if (!rtc.begin()) {
while (1);
}
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
compuerta.attach(servoPin);
compuerta.write(0);
pinMode(buzzer, OUTPUT);
pinMode(boton, INPUT_PULLUP);
pinMode(ledVerde, OUTPUT);
pinMode(ledNaranja, OUTPUT);
pinMode(ledRojo, OUTPUT);
lcd.begin(16,2);
olvidos = EEPROM.read(0);
if(olvidos == 255){
olvidos = 0;
EEPROM.write(0,0);
}
for(int i=0;i<8;i++){
horas[i] = -1;
minutos[i] = -1;
}
pantallaInicio();
}
void loop() {
manejarTeclado();
configurarHorarios();
DateTime ahora = rtc.now();
Serial.print("RTC: ");
Serial.print(ahora.hour());
Serial.print(":");
if(ahora.minute() < 10){
Serial.print("0");
}
Serial.print(ahora.minute());
Serial.print(":");
if(ahora.second() < 10){
Serial.print("0");
}
Serial.println(ahora.second());
verificarHorarios(ahora);
gestionarEstados();
}
void pantallaInicio(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Olvidos:");
lcd.setCursor(0,1);
lcd.print(olvidos);
delay(2000);
lcd.clear();
lcd.print("Sistema listo");
}
void sonidoElefante(){
tone(buzzer,180);
delay(250);
tone(buzzer,260);
delay(250);
tone(buzzer,150);
delay(350);
tone(buzzer,320);
delay(300);
noTone(buzzer);
}
void sonidoRecompensa(){
tone(buzzer,523);
delay(150);
tone(buzzer,659);
delay(150);
tone(buzzer,784);
delay(250);
noTone(buzzer);
}
void abrirCompuerta(){
compuerta.write(90);
}
void cerrarCompuerta(){
compuerta.write(0);
}
void parpadeoRojoRapido(){
for(int i=0;i<8;i++){
digitalWrite(ledRojo,HIGH);
delay(120);
digitalWrite(ledRojo,LOW);
delay(120);
}
}
void verificarHorarios(DateTime ahora){
for(int i=0;i<8;i++){
if(horas[i] == -1){
continue;
}
int horaPre = horas[i];
int minutoPre = minutos[i] - 1;
if(minutoPre < 0){
minutoPre += 60;
horaPre--;
if(horaPre < 0){
horaPre = 23;
}
}
if(
ahora.hour() == horaPre &&
ahora.minute() == minutoPre &&
ahora.second() < 3 &&
!preAlarmaActiva
){
preAlarmaActiva = true;
lcd.clear();
lcd.print("Inserte");
lcd.setCursor(0,1);
lcd.print("medicina");
sonidoElefante();
parpadeoRojoRapido();
delay(2000);
lcd.clear();
lcd.print("Sistema listo");
}
if(
ahora.hour() == horas[i] &&
ahora.minute() == minutos[i] &&
ahora.second() < 3 &&
!alarmaActiva
){
alarmaActiva = true;
estado = 1;
tiempoEstado = millis();
lcd.clear();
lcd.print("Tome medicina");
abrirCompuerta();
sonidoElefante();
digitalWrite(ledRojo,HIGH);
}
}
}
void gestionarEstados(){
if(
alarmaActiva &&
digitalRead(boton) == LOW
){
confirmarToma();
delay(300);
return;
}
if(
estado == 1 &&
millis() - tiempoEstado >= 10000
){
estado = 2;
tiempoEstado = millis();
digitalWrite(ledRojo,LOW);
digitalWrite(ledNaranja,HIGH);
sonidoElefante();
lcd.clear();
lcd.print("Tiempo limite");
}
if(
estado == 2 &&
millis() - tiempoEstado >= 10000
){
estado = 3;
tiempoEstado = millis();
digitalWrite(ledNaranja,LOW);
digitalWrite(ledRojo,HIGH);
lcd.clear();
lcd.print("Ultima alerta");
sonidoElefante();
}
if(
estado == 3 &&
millis() - tiempoEstado >= 7000
){
digitalWrite(ledRojo,LOW);
cerrarCompuerta();
registrarOlvido();
}
if(
estado == 4 &&
millis() - tiempoEstado >= 7000
){
digitalWrite(ledVerde,LOW);
resetSistema();
lcd.clear();
lcd.print("Sistema listo");
}
if(
modoEmergencia &&
millis() - inicioEmergencia >= 20000
){
modoEmergencia = false;
digitalWrite(ledNaranja,LOW);
cerrarCompuerta();
lcd.clear();
lcd.print("Sistema listo");
}
}
void confirmarToma(){
digitalWrite(ledRojo,LOW);
digitalWrite(ledNaranja,LOW);
digitalWrite(ledVerde,HIGH);
cerrarCompuerta();
sonidoRecompensa();
lcd.clear();
lcd.print("Medicamento");
lcd.setCursor(0,1);
lcd.print("OK!");
estado = 4;
tiempoEstado = millis();
}
void registrarOlvido(){
olvidos++;
EEPROM.write(0, olvidos);
lcd.clear();
lcd.print("Olvido");
lcd.setCursor(0,1);
lcd.print("guardado");
estado = 5;
alarmaActiva = false;
preAlarmaActiva = false;
}
void resetSistema(){
digitalWrite(ledRojo,LOW);
digitalWrite(ledNaranja,LOW);
digitalWrite(ledVerde,LOW);
alarmaActiva = false;
preAlarmaActiva = false;
compuertaAbiertaManual = false;
estado = 0;
}
void configurarHorarios(){
static bool configurado = false;
if(configurado) return;
for(int i=0;i<8;i++){
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Horario ");
lcd.print(i+1);
lcd.setCursor(0,1);
lcd.print("HHMM/# o D");
String entrada = "";
while(true){
char tecla = keypad.getKey();
if(tecla){
if(tecla == 'D'){
horas[i] = -1;
minutos[i] = -1;
break;
}
if(tecla >= '0' && tecla <= '9'){
if(entrada.length() < 4){
entrada += tecla;
lcd.setCursor(
entrada.length()-1,
1
);
lcd.print(tecla);
}
}
if(
tecla == 'B' &&
entrada.length() > 0
){
entrada.remove(
entrada.length()-1
);
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(entrada);
}
if(
tecla == '#' &&
entrada.length() == 4
){
horas[i] =
entrada.substring(0,2).toInt();
minutos[i] =
entrada.substring(2,4).toInt();
break;
}
}
}
}
lcd.clear();
lcd.print("Config lista");
delay(1500);
lcd.clear();
lcd.print("Sistema listo");
configurado = true;
}
void manejarTeclado(){
char tecla = keypad.getKey();
if(!tecla){
return;
}
if(tecla == '*'){
asm volatile ("jmp 0");
}
if(tecla == '0'){
if(millis() - ultimoCero < 1500){
contadorCeros++;
} else {
contadorCeros = 1;
}
ultimoCero = millis();
if(contadorCeros >= 3){
contadorCeros = 0;
modoEmergencia = true;
inicioEmergencia = millis();
abrirCompuerta();
digitalWrite(ledNaranja,HIGH);
sonidoElefante();
lcd.clear();
lcd.print("Acceso manual");
}
}
if(tecla == 'C'){
mostrandoOlvidos = !mostrandoOlvidos;
lcd.clear();
if(mostrandoOlvidos){
lcd.print("Olvidos:");
lcd.setCursor(0,1);
lcd.print(olvidos);
}
else{
lcd.print("Sistema listo");
}
delay(1000);
}
}