martes, 7 de abril de 2026

Sistema: Casco con Control Automático de Temperatura

 

/*

 * =========================================================

 * 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