Casa Domótica

Casa Automatizada Completa

 

Haciendo uso de los diferentes Proyectos finales desarrollados hasta ahora, y combinándolos en un solo código, obtendremos una Maqueta de Casa Domótica completa y funcional.

Tu Maqueta de Casa Domótica es más que un proyecto; es la materialización de tus conocimientos en programación y electrónica. Es la prueba de que puedes crear entornos inteligentes, seguros y confortables. Tómate un momento para apreciar el resultado de tu esfuerzo y para reflexionar sobre las infinitas posibilidades que la domótica ofrece.


 

    Nota importante

Recuerda reajustar los mensajes mostrados en la pantalla OLED, para que la monitorización sea constante y no te pierdas ningún detalle del estado de tu casa.

#include <MentorBit.h>
#include <MentorBitMotores.h>
#include <MentorBitPantallas.h>
#include <MentorBitVL53.h>
#include <MentorBitIR.h>
#include <MentorBitDisplay.h>
#include <MentorBitSensores.h>
#include <MentorBitLDR.h>
#include <MentorBitDHT11.h>
#include <MentorBitPir.h>
#include <MentorBitRGB.h>
#include <MentorBitPuertos.h>
#include <MentorBitMQ.h>
#include <MentorBitDataLogger.h>

// --- DEFINICIÓN DE PINES (¡AJUSTA ESTO SEGÚN TUS CONEXIONES!) ---

// Actuadores
#define LED_PIN_1   MentorBitPuertos::PUERTO_MODULO_2_DIGITAL
// Pin para el Sensor IR de entrada
#define PIN_IR MentorBitPuertos::PUERTO_GENERICO_1_DIGITAL_5
// Pin para el Micro Servo SG90 (puerta auxiliar)
#define SERVO MentorBitMotores::SERVOMOTOR_1

// --- INSTANCIACIÓN DE OBJETOS ---
MentorBit miMentorBit;
MentorBitMotores DriverMotores;
MentorBitDisplay Display;
MentorBitPantallas DriverPantallas;
MentorBitPuertos miModuloPuertos;
MentorBitVL53 laser;
MentorBitDataLogger miDataLogger;

// Sensores
MentorBitPir miPIR(miModuloPuertos.PUERTO_GENERICO_1_DIGITAL_2);
MentorBitDHT11 miDHT(miModuloPuertos.PUERTO_MODULO_1_DIGITAL);
MentorBitIR miIR_Entrada(PIN_IR);
MentorBitMQ2 miMQ(miMQ.co, miModuloPuertos.PUERTO_GENERICO_1_ANALOG_1);

// Declaramos el objeto de los RGBs
MentorBitRGB led_rgb1(LED_PIN_1);


// --- VARIABLES GLOBALES ---
unsigned long tiempoUltimaPresencia = 0;
const unsigned long TIMEOUT_PRESENCIA = 10000; // 10 segundos sin presencia para apagar luces (ajustable)

const int UMBRAL_HUMEDAD_ALTA = 70; // % RH (Humedad Relativa)
const int UMBRAL_TEMP_ALTA    = 28; // Grados Celsius

const int UMBRAL_LUMINOSIDAD_BAJA = 700; // Valor del LDR para considerar que hay poca luz
const int UMBRAL_LUMINOSIDAD_ALTA = 200; // Valor del LDR para considerar que hay mucha luz

const int UMBRAL_DISTANCIA_COCHE = 40; // Distancia en mm para detectar coche aparcado (85cm si no hay objeto)
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

// Umbral de PPM para considerar la concentración de CO como peligrosa
const float CO_ALTO = 1.5; //5 ppm, puedes ajustar este valor
const float GLP_ALTO = 1; //0 ppm
const float H2_BAJO = 1; //1 ppm
const float ALCOHOL_ALTO = 1; //0 ppm
const float PROPANO_ALTO = 1; //0 ppm

// Variables para el parpadeo de la alarma
unsigned long lastBlinkTime = 0;
const unsigned long BLINK_INTERVAL = 200; // Intervalo de parpadeo en ms (200ms ON, 200ms OFF)
bool alarmState = false; // true = alarma activa (sonando y parpadeando)

// Variable con el nombre del Archivo que vamos a emplear
String archivo = "Alarma.txt";

// --- 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 = "",
                    String linea5 = "", String linea6 = "") {
    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.setCursor(0, 40); DriverPantallas.oled.print(linea5);
    DriverPantallas.oled.setCursor(0, 50); DriverPantallas.oled.print(linea6);
    DriverPantallas.oled.display(); // Muestra el contenido en la pantalla
}

// NUEVA FUNCIÓN QUE REEMPLAZA A activarAlarmaVisualAuditiva y desactivarAlarma
void gestionarAlarma(bool hayAlarma, float concentracion, const String& nombreGas,
                     String& linea5, String& linea6) {

    if (hayAlarma) {
        // --- Activar alarma física ---
        unsigned long currentTime = millis();
        if (currentTime - lastBlinkTime >= BLINK_INTERVAL) {
            lastBlinkTime = currentTime;
            alarmState = !alarmState; // Alternar estado (ON/OFF)
            if (alarmState) {
                digitalWrite(miMentorBit.LED_ROJO, HIGH);
                digitalWrite(miMentorBit.LED_AZUL, LOW);
                tone(miMentorBit.ZUMBADOR, 1000, 300);
            } else {
                digitalWrite(miMentorBit.LED_ROJO, LOW);
                noTone(miMentorBit.ZUMBADOR);
            }
        }
       
        // --- Preparar mensajes para el OLED ---
        linea5 = "ALARMA: " + nombreGas;
        linea6 = String(concentracion, 1) + " PPM. ¡VENTILE!";

        // --- Registrar en SD (DataLogger) ---
        // (Esta lógica se mantiene aquí para no repetirla en el loop)
        Serial.print("ALARMA DE GAS " + nombreGas + ": ");
        Serial.print(concentracion, 1);
        Serial.println(" ppm");
        String fecha_hora_actual = miDataLogger.obtenerHoraRTC();
        String fecha_actual = fecha_hora_actual.substring(0, 10);
        String hora_actual = fecha_hora_actual.substring(11);
        String registro = "Alarma por " + nombreGas +
                          " el " + fecha_actual +
                          " a las " + hora_actual +
                          " (" + String(concentracion, 1) + " ppm)";
        miDataLogger.escribirEnArchivo(archivo, registro);
        Serial.println(registro);

    } else {
        // --- Desactivar alarma física ---
        digitalWrite(miMentorBit.LED_AZUL, HIGH);
        noTone(miMentorBit.ZUMBADOR);
        alarmState = false;

        // --- Preparar mensajes de estado normal ---
        linea5 = "Calidad del Aire: OK";
        linea6 = "";
    }
}

void setup() {
    Serial.begin(9600);
    Serial.println("Iniciando Casa Domótica...");

    pinMode(miModuloPuertos.PUERTO_GENERICO_1_ANALOG_2, INPUT); //LDR
    // Inicializar sensor IR de entrada
    pinMode(PIN_IR, INPUT);
    // Inicializar servo
    DriverMotores.inicializarServo(SERVO);
    DriverMotores.moverServo(SERVO, 0);

    // Inicializamos la pantalla LCD
    DriverPantallas.inicializarLCD();
    DriverPantallas.lcd.backlight();
    DriverPantallas.lcd.clear();
    DriverPantallas.lcd.setCursor(0, 0);
    DriverPantallas.lcd.print("Casa Domotica");
    DriverPantallas.lcd.setCursor(0, 1);
    DriverPantallas.lcd.print("Iniciando...");
    // Inicializar pantalla OLED
    DriverPantallas.inicializarOLED();
    DriverPantallas.oled.setTextSize(1);
    DriverPantallas.oled.setTextColor(SSD1306_WHITE);
    actualizarOLED("Casa Domotica", "Iniciando...");
    delay(2000);

    // Inicializamos el Display 7 Segmentos
    Display.inicializarDisplay();
    Display.imprimir(0); // Mostrar 0 al inicio

    // Inicializar pin del zumbador apagado
    noTone(miMentorBit.ZUMBADOR);

    // Inicializar LED RGB del MentorBit
    miMentorBit.apagarRGB();

    led_rgb1.begin(); // INICIALIZA la librería
    led_rgb1.cambiarBrillo(50);

    digitalWrite(miMentorBit.LED_ROJO, LOW);
    digitalWrite(miMentorBit.LED_VERDE, LOW);
    digitalWrite(miMentorBit.LED_AZUL, LOW);

    // Inicializar sensor de distancia láser
    laser.begin();
    actualizarOLED("Casa Domotica", "Listo para operar");

    establecerColorRGB(0, 255, 0); // Verde - Listo
    delay(1000);

    // Calibrar el sensor MQ-2
    Serial.println("Calibrando sensor MQ-2. Esto puede tardar 20-30 segundos...");
    actualizarOLED("Calibrando MQ-2...", "Mantener en aire limpio");
    miMQ.calibrar();
    Serial.println("Calibracion MQ-2 completa.");
    actualizarOLED("Calibracion OK", "Sistema Listo!");
    delay(1000);

    // Inicalizamos el RTC
    miDataLogger.inicializarRTC();
    // Configuramos el RTC con la fecha y la hora del PC
    miDataLogger.ajustarHoraRTC();
    // Guardamos un primer mensaje distintivo al comienzo de la cuenta
    miDataLogger.escribirEnArchivo(archivo, "---- Registro de alarmas ----");

    // Esperamos un poco antes de empezar
    delay(2000);

    // Limpiamos la pantalla antes de empezar
    DriverPantallas.lcd.clear();
}

void loop() {
    // --- Variables para la pantalla OLED ---
    String oledL1, oledL2, oledL3, oledL4, oledL5, oledL6;
   
    // --- 1. Lectura de Sensores ---
    int temperatura_dht = miDHT.obtenerTemperatura();
    int humedad_dht = miDHT.obtenerHumedad();
    int luminosidad_ldr = analogRead(miModuloPuertos.PUERTO_GENERICO_1_ANALOG_2);
    int lectura_pir = miPIR.lecturaDigital(); // 1 si hay presencia, 0 si no
    int velocidad_potenciometro = analogRead(miMentorBit.POTENCIOMETRO); // Lectura del potenciómetro (0-1023)

    // --- 2. Control de Ventilación (Motor N20 DC) ---
    int velocidad_ventilador_pwm = 0; // Velocidad del ventilador (0-255 para PWM)
    String estadoVentilador = "OFF";

    if (humedad_dht > UMBRAL_HUMEDAD_ALTA || temperatura_dht > UMBRAL_TEMP_ALTA) {
        velocidad_ventilador_pwm = map(velocidad_potenciometro, 0, 1023, 50, 255); // Mínimo 50 para que gire
        estadoVentilador = "ON";
        DriverMotores.moverMotorDC(velocidad_ventilador_pwm, 0);
    }
    else{
        DriverMotores.moverMotorDC(0, 0);
    }
   
    int nivel_ventilacion_display = map(velocidad_ventilador_pwm, 0, 255, 0, 9);
    Display.imprimir(nivel_ventilacion_display);

    // --- 3. Control de Iluminación y Presencia (LDR, PIR, RGB Externo) ---
    bool hayPresencia = (miPIR.lecturaDigital());

    if (hayPresencia) {
        tiempoUltimaPresencia = millis();
    }

    if (hayPresencia || (millis() - tiempoUltimaPresencia < TIMEOUT_PRESENCIA)) {
        digitalWrite(miMentorBit.LED_ROJO, HIGH);
        digitalWrite(miMentorBit.LED_VERDE, HIGH);
        digitalWrite(miMentorBit.LED_AZUL, HIGH);
    } else {
        digitalWrite(miMentorBit.LED_ROJO, LOW);
        digitalWrite(miMentorBit.LED_VERDE, LOW);
        digitalWrite(miMentorBit.LED_AZUL, LOW);
    }

    int brilloRGB = 50;
    if (luminosidad_ldr > UMBRAL_LUMINOSIDAD_BAJA) {
        brilloRGB = 255;
        led_rgb1.cambiarBrillo(brilloRGB);
    } else if (luminosidad_ldr > UMBRAL_LUMINOSIDAD_ALTA) {
        brilloRGB = 100;
        led_rgb1.cambiarBrillo(brilloRGB);
    } else {
        brilloRGB = 10;
        led_rgb1.cambiarBrillo(brilloRGB);
    }
    led_rgb1.cambiarColor(255, 255, 255);

    // --- 4. Mostrar en Pantalla LCD ---
    DriverPantallas.lcd.clear();
    DriverPantallas.lcd.setCursor(0, 0);
    DriverPantallas.lcd.print("Temp:");
    DriverPantallas.lcd.print(temperatura_dht);
    DriverPantallas.lcd.print("C Hum:");
    DriverPantallas.lcd.print(humedad_dht);
    DriverPantallas.lcd.print("%");
    DriverPantallas.lcd.setCursor(0, 1);
    DriverPantallas.lcd.print("Vent:");
    DriverPantallas.lcd.print(estadoVentilador);
    DriverPantallas.lcd.print(" LDR:");
    DriverPantallas.lcd.print(luminosidad_ldr);

    // --- Lógica del Garaje ---
    bool vehiculoEnEntrada = miIR_Entrada.objetoPresente();
    float distancia_coche_garaje = laser.leerDistancia();
   
    // Manejo de estados de la puerta principal del garaje
    switch (estadoActualPuerta) {
        case CERRADA:
            if (vehiculoEnEntrada) {
                if (distancia_coche_garaje > UMBRAL_DISTANCIA_COCHE) {
                    DriverMotores.moverMotorPP(300, 0);
                    delay(2);
                    estadoActualPuerta = ABRIENDO;
                    tiempoUltimoCambioEstadoPuerta = millis();
                }
            }
            break;
        case ABRIENDO:
            if (millis() - tiempoUltimoCambioEstadoPuerta >= TIEMPO_MOVIMIENTO_PUERTA) {
                estadoActualPuerta = ABIERTA;
                tiempoUltimoCambioEstadoPuerta = millis();
            }
            break;
        case ABIERTA:
            if (millis() - tiempoUltimoCambioEstadoPuerta >= TIEMPO_PUERTA_ABIERTA) {
                DriverMotores.moverMotorPP(300, 1);
                delay(2);
                estadoActualPuerta = CERRANDO;
                tiempoUltimoCambioEstadoPuerta = millis();
            }
            break;
        case CERRANDO:
            if (millis() - tiempoUltimoCambioEstadoPuerta >= TIEMPO_MOVIMIENTO_PUERTA) {
                estadoActualPuerta = CERRADA;
            }
            break;
    }
   
    // Preparar texto para las líneas 1-4 del OLED (Garaje)
    oledL1 = (estadoActualPuerta == CERRADA) ? "Garaje Cerrado" : (estadoActualPuerta == ABRIENDO ? "Abriendo Puerta..." : (estadoActualPuerta == ABIERTA ? "Puerta Abierta" : "Cerrando Puerta..."));
    oledL2 = (estadoActualPuerta == CERRADA) ? "Plaza Libre: Si" : (estadoActualPuerta == ABRIENDO ? "Vehiculo Detectado" : (estadoActualPuerta == ABIERTA ? "Esperando cierre..." : ""));
    oledL3 = "Dist: " + String(distancia_coche_garaje) + "mm";
    oledL4 = (distancia_coche_garaje > 0 && distancia_coche_garaje <= UMBRAL_DISTANCIA_COCHE) ? "Coche Aparcado!" : (distancia_coche_garaje == 0) ? "Sensor Fuera Rango" : "Plaza Libre";


    // Control de Acceso Auxiliar (Servo)
    int reading = digitalRead(miMentorBit.PULSADOR_PULLUP_DIGITAL);
    if (reading != lastButtonStateDigital && (millis() - lastDebounceTimeDigital > DEBOUNCE_DELAY)) {
        lastDebounceTimeDigital = millis();
        if (reading == LOW) {
            if (puertaAuxiliarAbierta) {
                DriverMotores.moverServo(SERVO, 0);
                puertaAuxiliarAbierta = false;
            } else {
                DriverMotores.moverServo(SERVO, 90);
                puertaAuxiliarAbierta = true;
            }
        }
    }
    lastButtonStateDigital = reading;

    // --- Monitorización y Alarma de Gas ---
    miMQ.cambiarDeteccionGas(miMQ.co);
    float concentracion_co_ppm = miMQ.obtenerLecturaMQ();
    miMQ.cambiarDeteccionGas(miMQ.glp);
    float concentracion_glp_ppm = miMQ.obtenerLecturaMQ();
    miMQ.cambiarDeteccionGas(miMQ.h2);
    float concentracion_h2_ppm = miMQ.obtenerLecturaMQ();
    miMQ.cambiarDeteccionGas(miMQ.alcohol);
    float concentracion_alcohol_ppm = miMQ.obtenerLecturaMQ();
    miMQ.cambiarDeteccionGas(miMQ.propano);
    float concentracion_propano_ppm = miMQ.obtenerLecturaMQ();

    // Preparar texto para las líneas 5 y 6 del OLED (Alarma)

    if (concentracion_co_ppm > CO_ALTO) {
        gestionarAlarma(true, concentracion_co_ppm, "CO", oledL5, oledL6);
    }
    else if (concentracion_glp_ppm > GLP_ALTO) {
        gestionarAlarma(true, concentracion_glp_ppm, "GLP", oledL5, oledL6);
    }
    else if (concentracion_h2_ppm < H2_BAJO) {
        gestionarAlarma(true, concentracion_h2_ppm, "H2", oledL5, oledL6);
    }
    else if (concentracion_alcohol_ppm > ALCOHOL_ALTO) {
        gestionarAlarma(true, concentracion_alcohol_ppm, "ALCOHOL", oledL5, oledL6);
    }
    else if (concentracion_propano_ppm > PROPANO_ALTO) {
        gestionarAlarma(true, concentracion_propano_ppm, "PROPANO", oledL5, oledL6);
    }
    else {
        gestionarAlarma(false, 0, "", oledL5, oledL6);
    }

    // --- ACTUALIZACIÓN ÚNICA DE LA PANTALLA OLED ---
    actualizarOLED(oledL1, oledL2, oledL3, oledL4, oledL5, oledL6);

    delay(500);
}
Vistas
2 Número de vistas
2 Vistas de miembros
0 Vistas públicas
Acciones
0 Gustos
0 No me gusta
0 Comentarios
Compartir en redes sociales
Compartir enlace
Compartir por correo

Por favor iniciar sesión para compartir esto webpage por correo.