/*
*
=========================================================
*
COLEGIO GIMNASIO BILINGÜE MARIE CURIE
*
Proyecto de Tecnología y Automatización
*
Sistema: Casco con Control Automático de Temperatura
*
Desarrollado por: Centro Prisma
*
Versión: 1.4 (Control proporcional con Kp)
*
Fecha: 19 de Febrero de 2026
*
=========================================================
*/
#include <Wire.h>
#include <Adafruit_SHT31.h>
/*
=========================================================
CONTROL AUTOMÁTICO DE TEMPERATURA EN UN
CASCO
=========================================================
¿QUÉ HACE ESTE PROYECTO?
Este sistema usa:
- 1 sensor de temperatura (SHT31)
- 1 ventilador controlado por un módulo
TB6612
- Control proporcional (Kp)
El sistema:
1) Mide la temperatura dentro del casco.
2) La compara con un valor deseado llamado
SETPOINT.
3) Calcula qué tan lejos está de esa
temperatura.
4) Ajusta la velocidad del ventilador
según esa diferencia.
5) Repite el proceso constantemente.
Eso es un sistema de LAZO CERRADO.
El
sistema mide → piensa → actúa → vuelve a medir.
=========================================================
*/
// ================= SENSOR DE TEMPERATURA
=================
//
// Este objeto representa el sensor SHT31.
// El programa lo usa para pedirle la
temperatura al sensor.
// Más adelante llamaremos:
sensorTemperatura.readTemperature()
Adafruit_SHT31 sensorTemperatura =
Adafruit_SHT31();
// ================= PINES DEL CONTROLADOR
DEL MOTOR (TB6612) =================
//
// El TB6612 es el módulo que permite que
el ESP32 controle el ventilador.
// El ESP32 no puede alimentar el motor
directamente, por eso usamos este controlador.
// Este pin “habilita” el TB6612.
// Cuando está en HIGH, el controlador
queda encendido y permite mover el motor.
// Cuando está en LOW, el controlador
queda apagado y el motor no puede girar.
const int PIN_ACTIVAR_CONTROLADOR = 33;
// Estos dos pines eligen el sentido de
giro del ventilador.
// El ventilador DC puede girar en dos
sentidos si el controlador lo permite.
// En este proyecto usamos un solo sentido
fijo, pero igual definimos los dos pines.
const int PIN_SENTIDO_1 = 27;
const int PIN_SENTIDO_2 = 26;
// Este pin recibe la señal PWM.
// PWM es la señal que usamos para
controlar la velocidad del ventilador.
const int PIN_PWM_VENTILADOR = 25;
// ================= CONFIGURACIÓN DEL PWM
(SEÑAL DE VELOCIDAD) =================
//
// El ESP32 puede generar PWM usando
“canales” internos.
// Un canal es como una salida virtual que
después conectamos a un pin real.
// Canal PWM elegido (podemos usar 0, 1,
2, etc.)
// Aquí usamos el canal 0 porque es
suficiente para un solo ventilador.
const int CANAL_PWM = 0;
// Frecuencia del PWM: cuántas veces por
segundo se repite la señal.
// 5000 Hz significa 5000 veces por
segundo.
// Esto hace que el control sea suave y
evita ruidos molestos en algunos motores.
const int FRECUENCIA_PWM = 5000;
// Resolución del PWM: cuántos niveles de
velocidad existen.
// Con 8 bits tenemos valores de 0 a 255.
// 0
= apagado
// 255 = máxima velocidad
const int RESOLUCION_PWM = 8;
// ================= AJUSTES DEL SISTEMA
(CONTROL) =================
//
// SETPOINT es la temperatura objetivo.
// Es el valor que queremos mantener
dentro del casco.
const float SETPOINT = 28.0;
// KP es la “fuerza” del control
proporcional.
// Entre más grande sea KP, el ventilador
reaccionará más fuerte
// cuando la temperatura se pase del
setpoint.
const float KP = 35.0;
// ================= REGLAS DEL MOTOR
(VENTILADOR) =================
//
// Algunos motores necesitan un impulso
inicial para arrancar.
// Si no se les da, pueden quedarse
vibrando sin girar.
const int PWM_EMPUJON = 160;
// Una vez que el ventilador está
encendido,
// no debe quedar con un PWM demasiado
bajo,
// porque podría volverse inestable o
frenarse.
const int PWM_MINIMO = 80;
// Tiempo del empujón en milisegundos.
// 250 ms = 0.25 segundos.
const int TIEMPO_EMPUJON = 250;
// ================= TIEMPO ENTRE
MEDICIONES =================
//
// Cada cuánto se repite el ciclo de
control.
// 1000 ms = 1 segundo.
// Esto significa que el sistema mide y
decide una vez por segundo.
const int TIEMPO_ENTRE_MEDICIONES = 1000;
// ================= VARIABLES (DATOS QUE
CAMBIAN) =================
//
// Estas variables cambian durante el
programa.
// Guardan lo que el sistema está midiendo
y calculando.
// Temperatura medida por el sensor en
este momento.
float temperaturaActual = 0.0;
// ERROR = temperaturaActual - SETPOINT
// Solo usamos error positivo (si hace más
calor del deseado).
float errorTemperatura = 0.0;
// PWM calculado por el control (lo que
“debería” aplicarse).
int pwmCalculado = 0;
// PWM que realmente quedó aplicado en el
ventilador en el ciclo anterior.
// Esto nos sirve para saber si estaba
apagado y necesita empujón.
int pwmAplicado = 0;
//
=================================================
// FUNCIONES DEL SISTEMA
// =================================================
//
-------------------------------------------------
// Función: medirTemperatura()
//
-------------------------------------------------
// Lee el valor actual del sensor SHT31.
// El sensor devuelve la temperatura en
grados Celsius.
// Ese valor se guarda en la variable
temperaturaActual.
//
-------------------------------------------------
void medirTemperatura() {
temperaturaActual = sensorTemperatura.readTemperature();
}
// -------------------------------------------------
// Función: calcularError()
//
-------------------------------------------------
// Calcula la diferencia entre la
temperatura actual
// y la temperatura deseada (SETPOINT).
//
// Fórmula:
// ERROR = Temperatura actual - SETPOINT
//
// Si el resultado es positivo:
//
→ La temperatura está por encima del objetivo.
//
→ Necesitamos enfriar.
//
// Si el resultado es negativo:
//
→ La temperatura está por debajo del objetivo.
//
→ No necesitamos enfriar.
// En ese caso, el error se convierte en
0.
//
-------------------------------------------------
void calcularError() {
errorTemperatura = temperaturaActual - SETPOINT;
if
(errorTemperatura < 0) {
errorTemperatura = 0;
}
}
//
-------------------------------------------------
// Función: calcularVelocidad()
//
-------------------------------------------------
// Convierte el error en velocidad del
ventilador.
//
// Se usa una regla proporcional:
//
// PWM = KP × ERROR
//
// Esto significa:
//
- Si el error es pequeño → velocidad baja.
//
- Si el error es grande → velocidad alta.
//
// El valor máximo permitido para PWM es
255.
// Si el cálculo supera ese valor,
// lo limitamos para proteger el sistema.
//
-------------------------------------------------
void calcularVelocidad() {
pwmCalculado = (int)(KP * errorTemperatura);
if
(pwmCalculado > 255) {
pwmCalculado = 255;
}
}
//
-------------------------------------------------
// Función: aplicarEmpujonSiNecesario()
//
-------------------------------------------------
// Algunos motores no arrancan con valores
bajos.
// Necesitan un impulso inicial.
//
// Esta función revisa:
//
// 1) Si el sistema ahora necesita que el
ventilador
//
esté encendido (pwmCalculado > 0).
//
// 2) Si antes estaba apagado (pwmAplicado
== 0).
//
// Si ambas condiciones se cumplen,
// se aplica un valor alto temporal
(PWM_EMPUJON)
// durante un tiempo corto.
//
// Esto garantiza que el motor arranque
correctamente.
//
-------------------------------------------------
void aplicarEmpujonSiNecesario() {
if
(pwmCalculado > 0) {
if (pwmAplicado == 0) {
ledcWrite(CANAL_PWM, PWM_EMPUJON);
delay(TIEMPO_EMPUJON);
}
}
}
//
-------------------------------------------------
// Función: asegurarVelocidadMinima()
//
-------------------------------------------------
// Una vez que el ventilador está
encendido,
// no puede trabajar con valores demasiado
bajos,
// porque podría detenerse.
//
// Si la velocidad calculada es menor que
// el valor mínimo estable (PWM_MINIMO),
// se ajusta automáticamente a ese mínimo.
//
// Esto mantiene el ventilador funcionando
// de forma continua y estable.
// -------------------------------------------------
void asegurarVelocidadMinima() {
if
(pwmCalculado > 0) {
if (pwmCalculado < PWM_MINIMO) {
pwmCalculado = PWM_MINIMO;
}
}
}
//
-------------------------------------------------
// Función: moverVentilador()
//
-------------------------------------------------
// Envía el valor final de PWM al
ventilador.
// Ese valor determina la velocidad real.
//
// También guarda ese valor en pwmAplicado
// para saber cuál fue la última velocidad
usada.
// Esto permite detectar cuándo el motor
estaba apagado.
//
-------------------------------------------------
void moverVentilador() {
ledcWrite(CANAL_PWM, pwmCalculado);
pwmAplicado = pwmCalculado;
}
// Muestra lo que está pensando el sistema
void mostrarDatos() {
Serial.println("=================================");
Serial.print("Temperatura actual: ");
Serial.print(temperaturaActual);
Serial.println(" C");
Serial.print("Setpoint: ");
Serial.print(SETPOINT);
Serial.println(" C");
Serial.print("Error: ");
Serial.print(errorTemperatura);
Serial.println(" C");
Serial.print("Velocidad PWM: ");
Serial.println(pwmAplicado);
}
//
=================================================
// INICIO DEL PROGRAMA
//
=================================================
void setup() {
//
Inicia la comunicación entre el ESP32 y el computador.
//
Esto nos permite ver información en el Monitor Serial.
Serial.begin(115200);
//
Inicia la comunicación I2C.
//
El pin 21 es para datos (SDA)
//
El pin 22 es para reloj (SCL)
//
Estos pines permiten que el sensor de temperatura
//
envíe información al microcontrolador.
Wire.begin(21, 22);
//
Inicia el sensor SHT31 en la dirección 0x44.
//
Esta dirección es como el "número de identificación"
//
del sensor dentro del bus I2C.
sensorTemperatura.begin(0x44);
//
Configuramos los pines que controlan el módulo TB6612
//
como pines de salida.
//
Un pin de salida puede enviar energía o señales.
pinMode(PIN_ACTIVAR_CONTROLADOR, OUTPUT);
pinMode(PIN_SENTIDO_1, OUTPUT);
pinMode(PIN_SENTIDO_2, OUTPUT);
//
Activamos el controlador del motor.
//
HIGH significa que enviamos 3.3V al pin.
//
Esto permite que el TB6612 funcione.
digitalWrite(PIN_ACTIVAR_CONTROLADOR, HIGH);
//
Definimos el sentido de giro del ventilador.
//
Con esta combinación:
//
PIN_SENTIDO_1 = HIGH
//
PIN_SENTIDO_2 = LOW
//
El ventilador girará en un solo sentido fijo.
digitalWrite(PIN_SENTIDO_1, HIGH);
digitalWrite(PIN_SENTIDO_2, LOW);
//
Configuramos el sistema PWM del ESP32.
// CANAL_PWM → Canal interno que generará la
señal.
// FRECUENCIA_PWM → Cuántas veces por segundo
cambia la señal.
// RESOLUCION_PWM → Define que el rango será
de 0 a 255.
ledcSetup(CANAL_PWM, FRECUENCIA_PWM, RESOLUCION_PWM);
//
Conectamos el canal PWM al pin físico del ventilador.
//
A partir de aquí, ese pin podrá variar su velocidad.
ledcAttachPin(PIN_PWM_VENTILADOR, CANAL_PWM);
//
Iniciamos el ventilador apagado.
//
Un valor de 0 significa que no enviamos potencia.
ledcWrite(CANAL_PWM, 0);
//
Mostramos un mensaje para confirmar
//
que el sistema inició correctamente.
Serial.println("CONTROL DE TEMPERATURA INICIADO");
}
//
=================================================
// CICLO PRINCIPAL (LAZO CERRADO)
//
=================================================
void loop() {
//
1️⃣ MEDIR
medirTemperatura();
//
2️⃣ COMPARAR
calcularError();
//
3️⃣ CALCULAR ACCIÓN
calcularVelocidad();
//
4️⃣ APLICAR REGLAS DEL MOTOR
aplicarEmpujonSiNecesario();
asegurarVelocidadMinima();
//
5️⃣ ACTUAR
moverVentilador();
//
6️⃣ MOSTRAR INFORMACIÓN
mostrarDatos();
//
7️⃣ ESPERAR Y REPETIR
delay(TIEMPO_ENTRE_MEDICIONES);
}
No hay comentarios:
Publicar un comentario