#include <MentorBit.h>
#include <MentorBitMotores.h> // Para el Servo y el PaP
#include <MentorBitPantallas.h> // Para la pantalla OLED
#include <MentorBitVL53.h> // Para el sensor de distancia láser
#include <MentorBitIR.h> // Para el sensor de infrarrojos
#include <MentorBitPuertos.h> // Para la gestión de pines
#include <MentorBitRGB.h> // Para el RGB
// --- INSTANCIACIÓN DE OBJETOS ---
MentorBit miMentorBit;
MentorBitPuertos miModuloPuertos;
MentorBitMotores DriverMotores; // Este objeto controlará todos los motores
MentorBitPantallas DriverPantallas; // Este objeto manejará la OLED
MentorBitVL53 laser; // Objeto para el sensor de distancia láser (I2C)
// --- DEFINICIÓN DE PINES (AJUSTA SEGÚN TUS CONEXIONES REALES) ---
// Utiliza los nombres de pines que te proporcione la documentación de MentorBit y del módulo expansor.
// Pin para el Sensor IR de entrada
#define PIN_IR miModuloPuertos.PUERTO_GENERICO_1_DIGITAL_2
// Pin para el Micro Servo SG90 (puerta auxiliar)
#define SERVO MentorBitMotores::SERVOMOTOR_1
MentorBitIR miIR_Entrada(PIN_IR); // Objeto para el sensor IR de entrada
// --- CONSTANTES Y VARIABLES GLOBALES ---
const int UMBRAL_DISTANCIA_COCHE = 40; // Distancia en mm para detectar coche aparcado (85cm si no hay objeto). ¡AJUSTA ESTE VALOR!
const unsigned long TIEMPO_MOVIMIENTO_PUERTA = 4000; // Tiempo en ms que tarda la puerta en abrir/cerrar
const unsigned long TIEMPO_PUERTA_ABIERTA = 5000; // Tiempo en ms que la puerta permanece abierta
// Número de pasos para el motor para abrir/cerrar completamente
const int PASOS_MOTOR_GARAGE = 300;
// Estados de la puerta del garaje
enum EstadoPuerta { CERRADA, ABRIENDO, ABIERTA, CERRANDO };
EstadoPuerta estadoActualPuerta = CERRADA;
unsigned long tiempoUltimoCambioEstadoPuerta = 0; // Para gestionar temporizadores
// --- VARIABLES PARA EL PULSADOR DE LA PUERTA AUXILIAR ---
bool puertaAuxiliarAbierta = false; // Estado de la puerta auxiliar (false = cerrada, true = abierta)
bool lastButtonStateDigital = HIGH; // Estado anterior del pulsador digital (HIGH por INPUT_PULLUP)
unsigned long lastDebounceTimeDigital = 0; // Última vez que se detectó un cambio válido en el pulsador digital
const unsigned long DEBOUNCE_DELAY = 50; // Retardo en ms para el anti-rebotes
// --- FUNCIONES AUXILIARES ---
void establecerColorRGB(int r, int g, int b) {
miMentorBit.encenderRGB(r, g, b);
}
// Función para actualizar la pantalla OLED
void actualizarOLED(String linea1, String linea2 = "", String linea3 = "", String linea4 = "") {
DriverPantallas.oled.clearDisplay(); // Limpia la pantalla
DriverPantallas.oled.setCursor(0, 0); DriverPantallas.oled.print(linea1);
DriverPantallas.oled.setCursor(0, 10); DriverPantallas.oled.print(linea2);
DriverPantallas.oled.setCursor(0, 20); DriverPantallas.oled.print(linea3);
DriverPantallas.oled.setCursor(0, 30); DriverPantallas.oled.print(linea4);
DriverPantallas.oled.display(); // Muestra el contenido en la pantalla
}
void setup() {
Serial.begin(9600);
Serial.println("Iniciando Guardián del Garaje...");
// Inicializar sensor IR de entrada
pinMode(PIN_IR, INPUT);
// Inicializar servo
DriverMotores.inicializarServo(SERVO);
DriverMotores.moverServo(SERVO, 0); // Puerta auxiliar cerrada al inicio (0 grados)
// Inicializar LED RGB
miMentorBit.apagarRGB();
// Inicializar pantalla OLED
DriverPantallas.inicializarOLED();
// Configuramos el tamaño del texto
DriverPantallas.oled.setTextSize(1);
// Configuramos el color del texto
DriverPantallas.oled.setTextColor(SSD1306_WHITE);
actualizarOLED("Garaje Inteligente", "Iniciando...");
delay(2000);
// Inicializar sensor de distancia láser
laser.begin();
actualizarOLED("Garaje Inteligente", "Listo para operar");
establecerColorRGB(0, 255, 0); // Verde - Listo
delay(1000);
}
void loop() {
// --- 1. Detección de Vehículos y Control de Puerta Principal ---
bool vehiculoEnEntrada = miIR_Entrada.objetoPresente(); // true si hay objeto/vehículo
float distancia_coche_garaje = laser.leerDistancia(); // Distancia en mm al coche aparcado
Serial.println(vehiculoEnEntrada);
Serial.println(miIR_Entrada.objetoPresente());
// Manejo de estados de la puerta principal del garaje
switch (estadoActualPuerta) {
case CERRADA:
if (vehiculoEnEntrada) {
Serial.println("Vehiculo detectado");
// Verificar si hay espacio en el garaje
if (distancia_coche_garaje > UMBRAL_DISTANCIA_COCHE) { // Plaza libre
Serial.println("Abriendo puerta...");
actualizarOLED("Abriendo Puerta...", "Vehiculo Detectado");
establecerColorRGB(255, 255, 0); // Amarillo - Abriendo
// --- Lógica para mover motor paso a paso para abrir ---
// Arrancamos el motor paso a paso 300 pasos en una dirección
DriverMotores.moverMotorPP(300, 0);
delay(2); // Controla la velocidad de los pasos
estadoActualPuerta = ABRIENDO;
tiempoUltimoCambioEstadoPuerta = millis();
} else {
Serial.println("Garaje Ocupado. No se puede abrir.");
actualizarOLED("Garaje Ocupado!", "Dist: " + String(distancia_coche_garaje) + "mm");
establecerColorRGB(255, 0, 0); // Rojo - Ocupado
}
} else {
// Si no hay vehículo en entrada y puerta cerrada, mostrar estado normal
actualizarOLED("Garaje Cerrado", "Plaza Libre: Si");
establecerColorRGB(0, 255, 0); // Verde - Listo/Cerrado
}
break;
case ABRIENDO:
if (millis() - tiempoUltimoCambioEstadoPuerta >= TIEMPO_MOVIMIENTO_PUERTA) {
Serial.println("Puerta Abierta.");
actualizarOLED("Puerta Abierta", "Esperando cierre...");
establecerColorRGB(0, 0, 255); // Azul - Abierta
estadoActualPuerta = ABIERTA;
tiempoUltimoCambioEstadoPuerta = millis(); // Reinicia temporizador para el cierre automático
}
break;
case ABIERTA:
if (millis() - tiempoUltimoCambioEstadoPuerta >= TIEMPO_PUERTA_ABIERTA) {
Serial.println("Cerrando puerta...");
actualizarOLED("Cerrando Puerta...", "");
establecerColorRGB(255, 255, 0); // Amarillo - Cerrando
// --- Lógica para mover motor paso a paso para cerrar ---
DriverMotores.moverMotorPP(300, 1);
delay(2);
estadoActualPuerta = CERRANDO;
tiempoUltimoCambioEstadoPuerta = millis();
}
break;
case CERRANDO:
if (millis() - tiempoUltimoCambioEstadoPuerta >= TIEMPO_MOVIMIENTO_PUERTA) {
Serial.println("Puerta Cerrada.");
actualizarOLED("Garaje Cerrado", "Plaza Libre: Si");
establecerColorRGB(0, 255, 0); // Verde - Cerrado
estadoActualPuerta = CERRADA;
}
break;
}
// --- 2. Control de Acceso Auxiliar (Servo SG90 con Pulsador Integrado) ---
int reading = digitalRead(miMentorBit.PULSADOR_PULLUP_DIGITAL);
// Si el estado del pulsador ha cambiado Y ha pasado suficiente tiempo para el debounce
if (reading != lastButtonStateDigital && (millis() - lastDebounceTimeDigital > DEBOUNCE_DELAY)) {
lastDebounceTimeDigital = millis(); // Actualiza el tiempo del último cambio
// Si el pulsador está presionado (LOW, por INPUT_PULLUP)
if (reading == LOW) {
// Alternar estado de la puerta auxiliar
if (puertaAuxiliarAbierta) { // Si la puerta está abierta, la cerramos
DriverMotores.moverServo(SERVO, 0); // Cerrar a 0 grados
Serial.println("Puerta auxiliar cerrada por pulsador.");
puertaAuxiliarAbierta = false;
actualizarOLED("Puerta Auxiliar", "Cerrada!", "", "");
} else { // Si la puerta está cerrada, la abrimos
DriverMotores.moverServo(SERVO, 90); // Abrir a 90 grados
Serial.println("Puerta auxiliar abierta por pulsador.");
puertaAuxiliarAbierta = true;
actualizarOLED("Puerta Auxiliar", "Abierta!", "", "");
}
}
}
lastButtonStateDigital = reading; // Guarda el estado actual como el último estado
// --- 3. Monitoreo de Ocupación del Garaje (Sensor Láser) - Actualización Continua ---
// Esta sección actualiza la distancia y estado de ocupación de la plaza en la OLED
// de forma continua, incluso si la lógica de la puerta no está en acción.
actualizarOLED(
(estadoActualPuerta == CERRADA) ? "Garaje Cerrado" : (estadoActualPuerta == ABRIENDO ? "Abriendo Puerta..." : (estadoActualPuerta == ABIERTA ? "Puerta Abierta" : "Cerrando Puerta...")),
(estadoActualPuerta == CERRADA) ? "Plaza Libre: Si" : (estadoActualPuerta == ABRIENDO ? "Vehiculo Detectado" : (estadoActualPuerta == ABIERTA ? "Esperando cierre..." : "")),
"Dist: " + String(distancia_coche_garaje) + "mm",
(distancia_coche_garaje > 0 && distancia_coche_garaje <= UMBRAL_DISTANCIA_COCHE) ? "Coche Aparcado!" :
(distancia_coche_garaje == 0) ? "Sensor Fuera Rango" : "Plaza Libre"
);
delay(300);
}