Control de Temperatura con ESP32, LCD I2C y Dimmer Digital
Materiales Necesarios
-
1 × ESP32 (NodeMCU ESP32 o similar)
-
1 × Display LCD 16×2 con módulo I2C
-
4 × Botones pulsadores
-
1 × Sensor de temperatura (LM35, NTC o DS18B20)
-
1 × MOC3031 (Optoacoplador triac)
-
1 × Triac (BT136 o similar, según potencia requerida)
-
1 × Resistencia de 180Ω 1/4W
-
1 × Resistencia de 330Ω 1/4W
-
1 × Carga resistiva (calefactor, foco incandescente, etc.)
-
1 × Protoboard y cables
-
1 × Disipador de calor para el triac (opcional, según potencia)
Esquema de Conexiones
Conexiones ESP32:
-
LCD I2C:
-
SDA → GPIO 21
-
SCL → GPIO 22
-
VCC → 3.3V
-
GND → GND
-
-
Botones (con pull-up interno):
-
UP → GPIO 12
-
DOWN → GPIO 13
-
PLAY → GPIO 14
-
SETTING → GPIO 27
-
Todos los botones conectados también a GND
-
-
Sensor de Temperatura (LM35):
-
VCC → 3.3V
-
OUT → GPIO 35 (ADC1_CH7)
-
GND → GND
-
-
Salida Dimmer:
-
CONTROL → GPIO 26 (Salida PWM)
-
Circuito de Potencia con MOC3031 y Triac:
ESP32 GPIO26 → Resistencia 330Ω → Pin 1 MOC3031 Pin 2 MOC3031 → GND Pin 6 MOC3031 → Resistencia 180Ω → Compuerta Triac MT1 Triac → Línea AC MT2 Triac → Carga La otra terminal de la carga → Línea AC neutral
Código Adaptado para ESP32
#include <Wire.h> #include <LiquidCrystal_I2C.h> #include <PID_v1.h> // Configuración del LCD I2C LiquidCrystal_I2C lcd(0x27, 16, 2); // Dirección I2C 0x27, display 16x2 // Definición de pines const int up = 12; const int down = 13; const int play = 14; const int setting = 27; const int salidaPWM = 26; const int sensorTemp = 35; // Variables de control int var_modo = 1; // modo de control (0: on/off, 1: PID) double temp; // temperatura medida double Output; // Salida PWM double error; // error setpoint-temp double p = 1; double i = 1; double d = 1; double tdes = 25; int tmin = 25; int tmax = 27; // Crear objeto PID PID myPID(&temp, &Output, &tdes, p, i, d, DIRECT); // Estados del sistema #define modo 0 #define ganancia_P 1 #define ganancia_I 2 #define ganancia_D 3 #define temp_des 4 #define pid 5 #define temp_min 6 #define temp_max 7 #define on_off 8 int estado = modo; // Estado actual del sistema // Configuración PWM para ESP32 const int freq = 1000; const int pwmChannel = 0; const int resolution = 8; void setup() { Serial.begin(115200); // Inicializar LCD lcd.init(); lcd.backlight(); lcd.clear(); // Configurar pines pinMode(up, INPUT_PULLUP); pinMode(down, INPUT_PULLUP); pinMode(play, INPUT_PULLUP); pinMode(setting, INPUT_PULLUP); pinMode(sensorTemp, INPUT); // Configurar PWM para el dimmer ledcSetup(pwmChannel, freq, resolution); ledcAttachPin(salidaPWM, pwmChannel); ledcWrite(pwmChannel, 0); // Configurar PID myPID.SetSampleTime(20); myPID.SetMode(AUTOMATIC); myPID.SetOutputLimits(0, 255); mostrarMensajeInicial(); } void loop() { // Leer temperatura (LM35: 10mV/°C) int lectura = analogRead(sensorTemp); temp = (lectura * 3.3 * 100) / 4096.0; // Convertir a °C para ESP32 (3.3V reference) switch (estado) { case modo: manejarModo(); break; case ganancia_P: manejarGananciaP(); break; case ganancia_I: manejarGananciaI(); break; case ganancia_D: manejarGananciaD(); break; case temp_des: manejarTempDeseada(); break; case pid: manejarPID(); break; case temp_min: manejarTempMin(); break; case temp_max: manejarTempMax(); break; case on_off: manejarOnOff(); break; } delay(10); } void manejarModo() { lcd.setCursor(0, 0); lcd.print("Modo:"); lcd.setCursor(7, 0); if (var_modo == 0) { lcd.print("on_off"); } else { lcd.print("pid"); } lcd.setCursor(0, 1); lcd.print("Ti:"); lcd.print(temp, 1); lcd.print("C"); if (digitalRead(down) == LOW) { var_modo = !var_modo; lcd.clear(); delay(200); } if (digitalRead(play) == LOW) { lcd.clear(); if (var_modo == 0) { estado = temp_min; } else { estado = ganancia_P; } delay(200); } } void manejarGananciaP() { lcd.setCursor(0, 0); lcd.print("Ganancia P"); lcd.setCursor(0, 1); lcd.print(p, 2); if (digitalRead(up) == LOW) { p += 0.1; actualizarDisplayVariable(p); } if (digitalRead(down) == LOW) { if (p > 0.1) { p -= 0.1; actualizarDisplayVariable(p); } else { lcd.setCursor(0, 1); lcd.print("No permitido"); delay(200); lcd.setCursor(0, 1); lcd.print(p, 2); } } if (digitalRead(play) == LOW) { estado = ganancia_I; lcd.clear(); delay(200); } if (digitalRead(setting) == LOW) { estado = modo; lcd.clear(); delay(200); } } void manejarGananciaI() { lcd.setCursor(0, 0); lcd.print("Ganancia I"); lcd.setCursor(0, 1); lcd.print(i, 2); if (digitalRead(up) == LOW) { i += 0.1; actualizarDisplayVariable(i); } if (digitalRead(down) == LOW) { if (i > 0.1) { i -= 0.1; actualizarDisplayVariable(i); } } if (digitalRead(play) == LOW) { estado = ganancia_D; lcd.clear(); delay(200); } if (digitalRead(setting) == LOW) { estado = modo; lcd.clear(); delay(200); } } void manejarGananciaD() { lcd.setCursor(0, 0); lcd.print("Ganancia D"); lcd.setCursor(0, 1); lcd.print(d, 2); if (digitalRead(up) == LOW) { d += 0.1; actualizarDisplayVariable(d); } if (digitalRead(down) == LOW) { if (d > 0.1) { d -= 0.1; actualizarDisplayVariable(d); } } if (digitalRead(play) == LOW) { estado = temp_des; lcd.clear(); delay(200); } if (digitalRead(setting) == LOW) { estado = modo; lcd.clear(); delay(200); } } void manejarTempDeseada() { lcd.setCursor(0, 0); lcd.print("Temp deseada"); lcd.setCursor(0, 1); lcd.print(tdes, 1); lcd.print("C"); if (digitalRead(up) == LOW) { tdes += 0.5; actualizarDisplayVariable(tdes); } if (digitalRead(down) == LOW) { tdes -= 0.5; actualizarDisplayVariable(tdes); } if (digitalRead(play) == LOW) { if (p == 0 && i == 0 && d == 0) { estado = ganancia_P; } else if (tdes != 0) { estado = pid; } lcd.clear(); delay(200); } if (digitalRead(setting) == LOW) { estado = modo; lcd.clear(); delay(200); } } void manejarPID() { myPID.SetTunings(p, i, d); error = tdes - temp; myPID.Compute(); // Controlar dimmer con PWM ledcWrite(pwmChannel, (int)Output); lcd.setCursor(0, 0); lcd.print("Tm:"); lcd.print(temp, 1); lcd.print("C"); lcd.setCursor(0, 1); lcd.print("Td:"); lcd.print(tdes, 1); lcd.print("C Out:"); lcd.print((int)Output); if (digitalRead(setting) == LOW) { estado = modo; lcd.clear(); delay(200); } delay(200); } void manejarTempMin() { lcd.setCursor(0, 0); lcd.print("Temp minima"); lcd.setCursor(0, 1); lcd.print(tmin); lcd.print("C"); if (digitalRead(up) == LOW) { tmin++; actualizarDisplayVariable(tmin); } if (digitalRead(down) == LOW) { tmin--; actualizarDisplayVariable(tmin); } if (digitalRead(play) == LOW) { estado = temp_max; lcd.clear(); delay(200); } if (digitalRead(setting) == LOW) { estado = modo; lcd.clear(); delay(200); } } void manejarTempMax() { lcd.setCursor(0, 0); lcd.print("Temp max"); lcd.setCursor(0, 1); lcd.print(tmax); lcd.print("C"); if (digitalRead(up) == LOW) { tmax++; actualizarDisplayVariable(tmax); } if (digitalRead(down) == LOW) { tmax--; actualizarDisplayVariable(tmax); } if (digitalRead(play) == LOW) { estado = on_off; lcd.clear(); delay(200); } if (digitalRead(setting) == LOW) { estado = modo; lcd.clear(); delay(200); } } void manejarOnOff() { lcd.setCursor(0, 0); lcd.print("Temp:"); lcd.print(temp, 1); lcd.print("C"); lcd.setCursor(0, 1); lcd.print("min"); lcd.print(tmin); lcd.print(" max"); lcd.print(tmax); if (temp <= tmin) { ledcWrite(pwmChannel, 255); // Encender completamente } if (temp >= tmax) { ledcWrite(pwmChannel, 0); // Apagar completamente } if (digitalRead(setting) == LOW) { estado = modo; lcd.clear(); delay(200); } delay(200); } void actualizarDisplayVariable(double valor) { lcd.setCursor(0, 1); lcd.print(" "); lcd.setCursor(0, 1); lcd.print(valor, 1); delay(200); } void mostrarMensajeInicial() { lcd.clear(); lcd.setCursor(0, 0); lcd.print("Control Temp"); lcd.setCursor(0, 1); lcd.print("ESP32 + PID"); delay(2000); lcd.clear(); }
Funcionamiento del Dimmer con MOC3031 y Triac
Principio de Operación:
-
El ESP32 genera una señal PWM en el pin de control
-
Esta señal controla el MOC3031 (optoacoplador con detector de cruce por cero)
-
El MOC3031 activa el triac en el momento preciso del ciclo AC
-
El triac regula la potencia entregada a la carga
Características del MOC3031:
-
Optoacoplador con detector de cruce por cero
-
Aislamiento eléctrico entre el circuito de control y la red AC
-
Diseñado específicamente para control de triacs
-
Voltaje de activación: 5-30V
Consideraciones de Seguridad:
-
AISLAMIENTO ELÉCTRICO: El MOC3031 proporciona aislamiento entre el ESP32 y la red AC
-
PROTECCIÓN: Usar un fusible en serie con la carga
-
DISIPACIÓN DE CALOR: El triac necesita disipador de calor según la potencia manejada
-
PRECAUCIÓN: La parte de potencia trabaja con voltajes peligrosos (110V/220V AC)
Calibración y Ajustes
-
Calibración del sensor de temperatura: Ajustar según el sensor utilizado
-
Sintonización del PID: Ajustar las constantes P, I, D para obtener la respuesta deseada
-
Frecuencia PWM: Ajustar según las características de la carga
-
Límites de temperatura: Configurar según los requerimientos específicos
Funcionalidades del Sistema
-
Dos modos de control: PID y On/Off
-
Ajuste de parámetros PID desde la interfaz
-
Visualización de temperatura actual y deseada
-
Control seguro de cargas AC mediante dimmer digital
-
Interfaz intuitiva con botones y LCD
Este sistema permite un control preciso de temperatura con seguridad eléctrica y flexibilidad de configuración gracias al uso del ESP32 y el dimmer digital basado en MOC3031 y triac.
