Control de Incubadora con LabVIEW y ESP32
Objetivos de la Práctica
-
Controlar temperatura y humedad en una incubadora
-
Monitorear condiciones en tiempo real con LabVIEW
-
Implementar sistema de volteo automático de huevos
-
Crear sistema de alertas y registro de datos
-
Desarrollar interfaz HMI profesional en LabVIEW
Materiales Requeridos
Hardware:
-
ESP32 Dev Board
-
Sensor DHT22 (Temperatura y Humedad)
-
Sensor DS18B20 (Temperatura adicional)
-
Módulo Relé 4 canales
-
Calentador (resistencia 100W o bombilla incandescente)
-
Humidificador (nebulizador ultrasónico)
-
2 Servomotores MG996R (volteo de huevos)
-
Ventilador DC 5V
-
Display LCD 16×2 (opcional)
-
Fuente de alimentación 12V/5A
-
Protoboard y cables
-
Caja aislante para incubadora
Software:
-
LabVIEW
-
Arduino IDE
-
VI Package Manager
-
LIFA Toolkit
Parte 1: Esquema de Conexiones
Diagrama de Conexiones ESP32:
// Sensores DHT22 → GPIO 4 DS18B20 → GPIO 5 // Actuadores RELE_CALENTADOR → GPIO 12 RELE_HUMIDIFICADOR → GPIO 13 RELE_VENTILADOR → GPIO 14 SERVO_1 → GPIO 18 SERVO_2 → GPIO 19 // Comunicación LCD I2C → GPIO 21 (SDA), GPIO 22 (SCL)
Esquema Eléctrico:
Fuente 12V ────┐
│
┌──────┴──────┐
│ RELÉS 4CH │
└──────┬──────┘
│
┌─────────┼─────────┐
│ │ │
Calentador Humidificador Ventilador
(AC 110V) (DC 12V) (DC 12V)
Parte 2: Programación del ESP32
Código Principal (Incubadora_ESP32.ino):
#include <DHT.h> #include <OneWire.h> #include <DallasTemperature.h> #include <Servo.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> // Definición de pines #define DHT_PIN 4 #define ONE_WIRE_PIN 5 #define RELAY_HEATER 12 #define RELAY_HUMIDIFIER 13 #define RELAY_FAN 14 #define SERVO1_PIN 18 #define SERVO2_PIN 19 // Tipos de sensores #define DHT_TYPE DHT22 // Instancias DHT dht(DHT_PIN, DHT_TYPE); OneWire oneWire(ONE_WIRE_PIN); DallasTemperature sensors(&oneWire); Servo servo1, servo2; LiquidCrystal_I2C lcd(0x27, 16, 2); // Variables de control float targetTemp = 37.5; // Temperatura objetivo float targetHumidity = 60.0; // Humedad objetivo float tempTolerance = 0.5; // Tolerancia temperatura float humTolerance = 5.0; // Tolerancia humedad int flipInterval = 3600; // Intervalo volteo (segundos) bool autoMode = true; // Modo automático // Variables de estado float currentTemp = 0; float currentHumidity = 0; float currentTemp2 = 0; bool heaterState = false; bool humidifierState = false; bool fanState = false; unsigned long lastFlipTime = 0; int flipCount = 0; String incubadoraStatus = "INICIANDO"; void setup() { // Inicializar comunicación Serial.begin(115200); // Inicializar sensores dht.begin(); sensors.begin(); // Configurar pines pinMode(RELAY_HEATER, OUTPUT); pinMode(RELAY_HUMIDIFIER, OUTPUT); pinMode(RELAY_FAN, OUTPUT); // Configurar servos servo1.attach(SERVO1_PIN); servo2.attach(SERVO2_PIN); resetServos(); // Configurar LCD lcd.init(); lcd.backlight(); lcd.setCursor(0, 0); lcd.print("INCUBADORA AVICOLA"); // Inicialmente apagar todos los relays digitalWrite(RELAY_HEATER, HIGH); // HIGH = Apagado digitalWrite(RELAY_HUMIDIFIER, HIGH); digitalWrite(RELAY_FAN, HIGH); Serial.println("INCUBADORA_READY"); } void loop() { // Leer sensores cada 2 segundos static unsigned long lastSensorRead = 0; if (millis() - lastSensorRead >= 2000) { readSensors(); lastSensorRead = millis(); } // Control automático if (autoMode) { controlTemperature(); controlHumidity(); controlVentilation(); controlEggFlip(); } // Actualizar LCD cada 5 segundos static unsigned long lastLCDUpdate = 0; if (millis() - lastLCDUpdate >= 5000) { updateLCD(); lastLCDUpdate = millis(); } // Enviar datos a LabVIEW cada 3 segundos static unsigned long lastDataSend = 0; if (millis() - lastDataSend >= 3000) { sendDataToLabVIEW(); lastDataSend = millis(); } // Procesar comandos seriales processSerialCommands(); delay(100); } void readSensors() { // Leer DHT22 currentTemp = dht.readTemperature(); currentHumidity = dht.readHumidity(); // Leer DS18B20 sensors.requestTemperatures(); currentTemp2 = sensors.getTempCByIndex(0); // Verificar errores de sensor if (isnan(currentTemp) || isnan(currentHumidity)) { incubadoraStatus = "ERROR_SENSOR"; return; } // Promedio de temperaturas float avgTemp = (currentTemp + currentTemp2) / 2.0; currentTemp = avgTemp; } void controlTemperature() { if (currentTemp < (targetTemp - tempTolerance)) { digitalWrite(RELAY_HEATER, LOW); // Encender calentador heaterState = true; } else if (currentTemp > (targetTemp + tempTolerance)) { digitalWrite(RELAY_HEATER, HIGH); // Apagar calentador heaterState = false; // Encender ventilador si temperatura muy alta if (currentTemp > (targetTemp + 1.0)) { digitalWrite(RELAY_FAN, LOW); fanState = true; } } else { digitalWrite(RELAY_FAN, HIGH); fanState = false; } } void controlHumidity() { if (currentHumidity < (targetHumidity - humTolerance)) { digitalWrite(RELAY_HUMIDIFIER, LOW); // Encender humidificador humidifierState = true; } else if (currentHumidity > (targetHumidity + humTolerance)) { digitalWrite(RELAY_HUMIDIFIER, HIGH); // Apagar humidificador humidifierState = false; } } void controlVentilation() { // Ventilación periódica cada 30 minutos static unsigned long lastVentilation = 0; if (millis() - lastVentilation >= 1800000) { // 30 minutos digitalWrite(RELAY_FAN, LOW); delay(60000); // Ventilar por 1 minuto digitalWrite(RELAY_FAN, HIGH); lastVentilation = millis(); } } void controlEggFlip() { if (millis() - lastFlipTime >= (flipInterval * 1000)) { flipEggs(); lastFlipTime = millis(); flipCount++; } } void flipEggs() { // Volteo a 45 grados servo1.write(45); servo2.write(45); delay(2000); // Regresar a posición inicial servo1.write(0); servo2.write(0); incubadoraStatus = "VOLTEO_COMPLETADO"; } void resetServos() { servo1.write(0); servo2.write(0); } void updateLCD() { lcd.clear(); lcd.setCursor(0, 0); lcd.print("T:"); lcd.print(currentTemp, 1); lcd.print("C H:"); lcd.print(currentHumidity, 0); lcd.print("%"); lcd.setCursor(0, 1); lcd.print("E:"); lcd.print(heaterState ? "ON " : "OFF"); lcd.print(" V:"); lcd.print(flipCount); } void sendDataToLabVIEW() { Serial.print("DATA:"); Serial.print(currentTemp); Serial.print(","); Serial.print(currentHumidity); Serial.print(","); Serial.print(currentTemp2); Serial.print(","); Serial.print(heaterState ? "1" : "0"); Serial.print(","); Serial.print(humidifierState ? "1" : "0"); Serial.print(","); Serial.print(fanState ? "1" : "0"); Serial.print(","); Serial.print(flipCount); Serial.print(","); Serial.println(incubadoraStatus); } void processSerialCommands() { if (Serial.available()) { String command = Serial.readStringUntil('\n'); command.trim(); if (command == "STATUS") { sendDetailedStatus(); } else if (command.startsWith("SET_TEMP:")) { targetTemp = command.substring(9).toFloat(); Serial.println("TEMP_SET:" + String(targetTemp)); } else if (command.startsWith("SET_HUM:")) { targetHumidity = command.substring(8).toFloat(); Serial.println("HUM_SET:" + String(targetHumidity)); } else if (command.startsWith("SET_FLIP_INT:")) { flipInterval = command.substring(13).toInt(); Serial.println("FLIP_INT_SET:" + String(flipInterval)); } else if (command == "FLIP_NOW") { flipEggs(); Serial.println("FLIP_EXECUTED"); } else if (command == "AUTO_ON") { autoMode = true; Serial.println("AUTO_MODE_ON"); } else if (command == "AUTO_OFF") { autoMode = false; Serial.println("AUTO_MODE_OFF"); } else if (command == "HEATER_ON") { digitalWrite(RELAY_HEATER, LOW); heaterState = true; Serial.println("HEATER_ON"); } else if (command == "HEATER_OFF") { digitalWrite(RELAY_HEATER, HIGH); heaterState = false; Serial.println("HEATER_OFF"); } } } void sendDetailedStatus() { Serial.println("=== INCUBADORA STATUS ==="); Serial.print("Temperature: "); Serial.println(currentTemp); Serial.print("Humidity: "); Serial.println(currentHumidity); Serial.print("Temp2: "); Serial.println(currentTemp2); Serial.print("Heater: "); Serial.println(heaterState ? "ON" : "OFF"); Serial.print("Humidifier: "); Serial.println(humidifierState ? "ON" : "OFF"); Serial.print("Fan: "); Serial.println(fanState ? "ON" : "OFF"); Serial.print("Flip Count: "); Serial.println(flipCount); Serial.print("Auto Mode: "); Serial.println(autoMode ? "ON" : "OFF"); Serial.print("Status: "); Serial.println(incubadoraStatus); Serial.println("========================"); }
Parte 3: Programación en LabVIEW
VI Principal: Control_Incubadora.vi
Front Panel Design:
// PESTAÑA: MONITOREO PRINCIPAL - Grupo: Indicadores de Temperatura * Termómetro: Temperatura Actual (0-50°C) * Numérico: Temperatura Objetivo * LED: Alarma Temperatura Alta * LED: Alarma Temperatura Baja - Grupo: Indicadores de Humedad * Medidor: Humedad Actual (0-100%) * Numérico: Humedad Objetivo * LED: Alarma Humedad Alta * LED: Alarma Humedad Baja - Grupo: Estado del Sistema * LED: Calentador Estado * LED: Humidificador Estado * LED: Ventilador Estado * LED: Modo Automático * Numérico: Contador de Volteos - Grupo: Gráficos * Waveform Chart: Temperatura vs Tiempo * Waveform Chart: Humedad vs Tiempo * Waveform Chart: Estados Actuadores // PESTAÑA: CONFIGURACIÓN - Grupo: Parámetros de Control * Numérico: Temperatura Objetivo (35-39°C) * Numérico: Humedad Objetivo (40-80%) * Numérico: Tolerancia Temperatura (0.1-1.0) * Numérico: Tolerancia Humedad (1-10%) * Numérico: Intervalo Volteo (minutos) - Grupo: Control Manual * Botón: Encender/Apagar Calentador * Botón: Encender/Apagar Humidificador * Botón: Volteo Manual * Botón: Activar/Desactivar Automático // PESTAÑA: REGISTRO Y ALERTAS - Grupo: Registro de Datos * Tabla: Histórico de Eventos * Botón: Exportar a Excel * Botón: Limpiar Registro - Grupo: Sistema de Alertas * Lista: Log de Alertas * Numérico: Umbral Alerta Temperatura * Numérico: Umbral Alerta Humedad * Botón: Test Sonido Alerta
Diagrama de Bloques Principal:
// ESTRUCTURA PRINCIPAL While Loop con [Stop] button // INICIALIZACIÓN Case Structure: First Call? - VISA Configure Serial Port - Inicializar variables globales - Configurar gráficos // COMUNICACIÓN SERIAL Event Structure dentro del While Loop: - Timeout: 1000ms → Leer datos seriales - Value Change: Botones de control → Enviar comandos // PROCESAMIENTO DE DATOS VISA Bytes at Serial Port → If bytes > 0 → VISA Read → Parsear datos → Actualizar indicadores // SUBVIs ESPECIALIZADOS - SubVI: "Parsear Datos Serial.vi" - SubVI: "Controlar Actuadores.vi" - SubVI: "Gestión Alertas.vi" - SubVI: "Registro Datos.vi"
SubVI: Parsear Datos Serial.vi
// Input: String de datos seriales // Output: Cluster con todos los datos // Ejemplo de datos: "DATA:37.5,65.2,37.6,1,0,1,15,VOLTEO_COMPLETADO" // Algoritmo: 1. Buscar "DATA:" en string 2. Separar por comas → Array de strings 3. Convertir elementos a números/booleanos 4. Crear cluster de salida: - Temperatura (DBL) - Humedad (DBL) - Temperatura2 (DBL) - Estado Calentador (BOOL) - Estado Humidificador (BOOL) - Estado Ventilador (BOOL) - Contador Volteos (I32) - Estado Sistema (String)
SubVI: Gestión Alertas.vi
// Inputs: Temperatura, Humedad, Umbrales // Output: String de Alerta, LED Alerta Case Structure: - Si Temp > Umbral Alto: "ALERTA: Temperatura ALTA" - Si Temp < Umbral Bajo: "ALERTA: Temperatura BAJA" - Si Hum > Umbral Alto: "ALERTA: Humedad ALTA" - Si Hum < Umbral Bajo: "ALERTA: Humedad BAJA" - Si sensor error: "ALERTA: Error de sensor" // Acciones: - Activar LED correspondiente - Agregar a log de alertas - Reproducer sonido (si configurado) - Guardar en archivo de registro
Parte 4: Configuración Paso a Paso
Paso 1: Montaje Físico
-
Construcción de la Incubadora:
-
Usar caja de espuma de poliestireno
-
Instalar ventana de observación
-
Colocar rejilla para huevos
-
Posicionar sensores a 5cm sobre huevos
-
-
Instalación Eléctrica:
-
Conectar relés según diagrama
-
Aislar cables de alta potencia
-
Instalar fusibles de protección
-
Verificar puesta a tierra
-
Paso 2: Configuración ESP32
-
Cargar código en Arduino IDE
-
Verificar comunicación serial
-
Calibrar sensores
-
Probar actuadores individualmente
Paso 3: Programación LabVIEW
-
Crear proyecto nuevo:
File → New Project Add VI: Control_Incubadora.vi Add SubVIs: Parsear, Alertas, Registro
-
Configurar comunicación:
-
Puerto COM correcto
-
Baud rate 115200
-
Timeout 10 segundos
-
-
Pruebas iniciales:
-
Comando «STATUS»
-
Control manual de actuadores
-
Registro de datos
-
Parte 5: Protocolo de Operación
Procedimiento de Inicio:
-
Encender sistema de control
-
Establecer parámetros iniciales:
-
Temperatura: 37.5°C
-
Humedad: 60%
-
Volteo cada 4 horas
-
-
Verificar estabilidad por 2 horas
-
Colocar huevos fértiles
Monitoreo Continuo:
-
Revisar gráficas cada 4 horas
-
Verificar contador de volteos
-
Registrar eventos importantes
-
Exportar datos diariamente
Mantenimiento:
-
Limpieza semanal
-
Calibración mensual de sensores
-
Verificación de actuadores
-
Backup de datos
Parte 6: Sistema de Seguridad
Protecciones Implementadas:
En ESP32:
// Watchdog timer #include <esp_task_wdt.h> void setup() { esp_task_wdt_init(10, true); // 10 segundos } // Verificación de sensores bool checkSensors() { if (currentTemp > 45.0 || currentTemp < 20.0) { emergencyShutdown(); return false; } return true; } void emergencyShutdown() { digitalWrite(RELAY_HEATER, HIGH); digitalWrite(RELAY_HUMIDIFIER, HIGH); digitalWrite(RELAY_FAN, HIGH); incubadoraStatus = "EMERGENCY_SHUTDOWN"; }
En LabVIEW:
// Monitoreo de timeout - Timer para verificar recepción de datos - Si no hay datos en 30 segundos → Alerta - Reintento automático de conexión // Validación de datos - Rango válido temperatura: 20-45°C - Rango válido humedad: 0-100% - Checksum de datos (opcional)
Parte 7: Análisis de Datos
Indicadores de Rendimiento:
-
Estabilidad Térmica: ±0.3°C
-
Estabilidad Humedad: ±5%
-
Eficiencia Energética: kWh por ciclo
-
Tasa de Éxito: Huevos eclosionados
Gráficos de Análisis:
// Trend Analysis.vi - Temperatura promedio por día - Histograma de fluctuaciones - Correlación temperatura-humedad - Eficiencia de actuadores
Parte 8: Evaluación de la Práctica
Criterios de Evaluación:
-
✅ Comunicación estable ESP32-LabVIEW
-
✅ Control preciso de temperatura (±0.5°C)
-
✅ Control preciso de humedad (±5%)
-
✅ Sistema de volteo automático funcional
-
✅ Interfaz intuitiva y completa
-
✅ Sistema de alertas efectivo
-
✅ Registro de datos confiable
Entregables:
-
Código completo ESP32
-
VIs de LabVIEW funcionando
-
Diagramas de conexión
-
Manual de operación
-
Reporte de pruebas (24 horas)
-
Análisis de datos de incubación
Pruebas de Validación:
-
Prueba de Estabilidad: 24 horas sin huevos
-
Prueba de Respuesta: Cambios bruscos de setpoint
-
Prueba de Fallos: Desconexión de sensores
-
Prueba de Seguridad: Límites de temperatura
