// --- LIBRERIAS ---
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
#include "RTClib.h"
// --- OBJETOS ---
LiquidCrystal_I2C lcd(0x27, 16, 2);
RTC_DS3231 rtc;
Servo tapa;
Servo comedero;
// --- PINES ---
#define SERVO_TAPA 5
#define SERVO_COM 6
#define POS_CERRADO 0
#define POS_ABIERTO 90
int TRIG_PIN = 2;
int ECHO_PIN = 4;
int DISTANCIA_DETECCION = 20;
#define TIEMPO_ESPERA_CIERRE 5000
#define INTERVALO_SENSOR 100
#define INTERVALO_LCD 1000
#define BOTON_PERMITIDO 11
#define BOTON_DENEGADO 12
#define BOTON_COMEDERO 13
// --- VARIABLES ---
char daysOfTheWeek[7][12] = { "Dom", "Lun", "Mar", "Mie", "Jue", "Vie", "Sab" };
long duracion;
int distancia;
bool platoAbierto = false;
bool comidaDispensada = false;
unsigned long ultimaDeteccion = 0;
unsigned long tiempoSensorAnterior = 0;
unsigned long tiempoLCDAnterior = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
// --- RELOJ ---
if (!rtc.begin()) {
Serial.println(F("No se encuentra el RTC"));
lcd.print("Error: RTC");
while (1);
}
if (rtc.lostPower()) {
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
// --- PANTALLA ---
lcd.init();
lcd.backlight();
// --- SERVOS ---
tapa.attach(SERVO_TAPA);
tapa.write(POS_CERRADO);
comedero.attach(SERVO_COM);
comedero.write(0);
platoAbierto = false;
// --- BOTONES ---
pinMode(BOTON_PERMITIDO, INPUT_PULLUP);
pinMode(BOTON_DENEGADO, INPUT_PULLUP);
pinMode(BOTON_COMEDERO, INPUT_PULLUP);
// --- SENSOR ---
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
lcd.setCursor(0, 0);
lcd.print("Comedero listo ");
lcd.setCursor(0, 1);
lcd.print("Esperando... ");
delay(1500);
lcd.clear();
}
void loop() {
// put your main code here, to run repeatedly:
DateTime now = rtc.now();
unsigned long tiempoActual = millis();
// --- DISPENSAR COMIDA (RELOJ) ---
if ((now.hour() == 8 || now.hour() == 14 || now.hour() == 20) && now.minute() == 0) {
if (!comidaDispensada) {
Serial.println("HORA DE COMER: Dispensando...");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Dispensando ");
lcd.setCursor(0, 1);
lcd.print("comida... ");
Serial.println("Girando a 90...");
comedero.write(POS_ABIERTO);
delay(1000);
Serial.println("Regresando a 0...");
comedero.write(POS_CERRADO);
delay(1000);
comidaDispensada = true;
delay(1500);
lcd.clear();
}
}
if (now.minute() == 1 && comidaDispensada == true) {
Serial.println("Comida Dispensada");
comidaDispensada = false;
}
// --- DISPENSAR COMIDA (BOTÓN MANUAL) ---
bool botonManualPresionado = (digitalRead(BOTON_COMEDERO) == LOW);
if (botonManualPresionado) {
Serial.println("BOTÓN MANUAL: Dispensando...");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Dispensando... ");
lcd.setCursor(0, 1);
lcd.print("(Manual) ");
Serial.println("Girando a 90...");
comedero.write(POS_ABIERTO);
delay(1000);
Serial.println("Regresando a 0...");
comedero.write(POS_CERRADO);
delay(1000);
delay(1500);
}
// --- SENSOR ULTRASÓNICO ---
if (tiempoActual - tiempoSensorAnterior > INTERVALO_SENSOR) {
tiempoSensorAnterior = tiempoActual;
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(1000);
digitalWrite(TRIG_PIN, LOW);
duracion = pulseIn(ECHO_PIN, HIGH);
// Calcular la distancia en centímetros
distancia = duracion * 0.0343 / 2;
Serial.print("Distancia: ");
Serial.print(distancia);
Serial.println(" cm");
}
// --- DETECCIÓN DE MASCOTA (SENSOR ULTRASÓNICO) ---
bool gatoPresente = (distancia < DISTANCIA_DETECCION && distancia > 0);
if (gatoPresente) {
ultimaDeteccion = tiempoActual;
if (!platoAbierto) { // Si hay un gato presente y el plato esta cerrado, lee el Tag
lcd.setCursor(0, 0);
lcd.print("Gato detectado ");
lcd.setCursor(0, 1);
lcd.print("Leyendo tag... ");
bool tagPermitidoLeido = (digitalRead(BOTON_PERMITIDO) == LOW);
bool tagDenegadoLeido = (digitalRead(BOTON_DENEGADO) == LOW);
if (tagPermitidoLeido) {
Serial.println("Tag Permitido. Abriendo tapa.");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Acceso Permitido");
lcd.setCursor(0, 1);
lcd.print(" ");
tapa.write(POS_ABIERTO);
platoAbierto = true;
delay(1500);
} else if (tagDenegadoLeido) {
Serial.println("Tag Denegado.");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Acceso Denegado");
lcd.setCursor(0, 1);
lcd.print(" ");
delay(1500);
}
} else { // Si hay un gato presente y el plato esta abierto, esta comiendo
lcd.setCursor(0, 0);
lcd.print("Gato comiendo...");
lcd.setCursor(0, 1);
lcd.print(" ");
}
}
else { // Si NO hay un gato presente
if (platoAbierto) { // Si NO hay un gato presente y el plato esta abierto, cierra la tapa
if (tiempoActual - ultimaDeteccion > TIEMPO_ESPERA_CIERRE) {// Cerrando el plato
Serial.println("El gato se fue. Cerrando tapa.");
lcd.setCursor(0, 0);
lcd.print("Cerrando tapa...");
lcd.setCursor(0, 1);
lcd.print(" ");
tapa.write(POS_CERRADO);
platoAbierto = false;
delay(1000);
}
else { // Aviso de cierre
lcd.setCursor(0, 0);
lcd.print("El gato se fue ");
lcd.setCursor(0, 1);
lcd.print("Cerrando en 5s ");
}
}
else { // Mensaje de reposo
if (tiempoActual - tiempoLCDAnterior > INTERVALO_LCD) {
tiempoLCDAnterior = tiempoActual;
lcd.setCursor(0, 0);
lcd.print(now.day(), DEC);
lcd.print('/');
lcd.print(now.month(), DEC);
lcd.print('/');
lcd.print(now.year(), DEC);
lcd.print(" (");
lcd.print(daysOfTheWeek[now.dayOfTheWeek()]);
lcd.print(") ");
lcd.setCursor(0, 1);
if (now.hour() < 10) lcd.print('0');
lcd.print(now.hour(), DEC);
lcd.print(':');
if (now.minute() < 10) lcd.print('0');
lcd.print(now.minute(), DEC);
lcd.print(':');
if (now.second() < 10) lcd.print('0');
lcd.print(now.second(), DEC);
lcd.print(" ");
}
}
}
}