Objetivo y caso de uso
Qué construirás: Construirás un perro guardián térmico para rack de servidores (server-rack-thermal-watchdog) que monitorea la temperatura ambiente y enciende automáticamente un ventilador de extracción de enfriamiento cuando se alcanza un umbral térmico crítico (p. ej., >40°C).
Por qué es importante / Casos de uso
- Prevención del estrangulamiento térmico: Mantiene frescos los laboratorios domésticos densos y los gabinetes de red, asegurando que los servidores mantengan velocidades de reloj máximas sin degradación del rendimiento.
- Reducción de ruido y eficiencia energética: Elimina el ruido continuo del ventilador (0dB en reposo) y reduce el consumo de energía al activar dinámicamente la refrigeración solo cuando el rack lo demanda, extendiendo la vida útil de los rodamientos del ventilador.
- Automatización fundamental: Introduce la histéresis (p. ej., ENCENDER a 40°C y APAGAR a 35°C), un principio crucial de los sistemas de control que evita la conmutación rápida del relé y el desgaste del hardware cerca del umbral.
Resultado esperado
- Un demonio ligero en Python que se ejecuta continuamente en segundo plano en una Raspberry Pi 5 con una sobrecarga mínima (<1% de uso de CPU).
- Control de ventilador automatizado y confiable impulsado por GPIO que ejecuta un bucle de histéresis térmica estable.
Audiencia: Entusiastas de laboratorios domésticos y administradores de sistemas; Nivel: Principiante a Intermedio
Arquitectura/flujo: El sensor de temperatura (I2C/1-Wire) lee los datos ambientales → El demonio de Python evalúa los umbrales → El GPIO de la Raspberry Pi activa el relé/PWM → El ventilador de extracción se activa/desactiva.
Nota educativa de validación
Antes de publicar este caso, el contenido pasó la puerta automática de validación de Prometeo con estado PASS. El validador comprobó los bloques de código, la estructura del artículo, los comandos copiables y la coherencia con el catálogo de dispositivos soportados.
Evidencia de validación publicada
- Resultado automático: PASS.
- Estructura parseada: 3 apartados, 3 tablas y 2 bloques de código detectados antes de publicar.
- Código comprobado: 1 Python/py_compile, 1 bloques de configuración/servicio.
- Catálogo soportado: el texto se contrastó contra los perfiles de dispositivo validables de Prometeo y los stacks no soportados bloquean la publicación.
- Hallazgos del informe: sin hallazgos bloqueantes.
Esta validación confirma compatibilidad sintáctica y de herramientas para el material publicado, pero no sustituye la prueba física sobre tu hardware, cableado y entorno exactos.
Nota educativa de seguridad
Este proyecto es un prototipo educativo de bajo voltaje, no un producto certificado. Antes de encender la configuración, verifique la distribución de pines de su Raspberry Pi exacta, nunca conecte 5 V a los pines GPIO de 3.3 V, desconecte la alimentación antes de cambiar el cableado y use interfaces o fuentes externas adecuadas para sensores, relés, motores o cargas.
Diagrama de bloques conceptual
Vista de alto nivel: qué entra, qué procesa cada bloque y qué sale del sistema.
Arquitectura funcional
Flujo conceptual de señales y responsabilidades entre bloques del dispositivo.
Requisitos previos
- Sistema operativo: Raspberry Pi OS Bookworm (64 bits) instalado y actualizado.
- Entorno de software: Python 3.11, gestor de paquetes estándar
apty conocimientos básicos de la terminal de Linux. - Interfaz de hardware: I2C debe estar habilitado en la Raspberry Pi (a través de
sudo raspi-config-> Interface Options -> I2C). - Herramientas: Un destornillador pequeño de punta plana para los terminales del relé, cables puente (hembra a hembra y macho a hembra) y una protoboard para la distribución de energía.
Materiales
Para garantizar la compatibilidad y la seguridad, este tutorial utiliza exactamente el siguiente modelo de dispositivo y componentes:
* Raspberry Pi 5 + sensor ambiental BME280 + módulo de relé de 5 V + ventilador de 80 mm
* Fuente de alimentación para el ventilador: Un adaptador de corriente CC de 5 V o 12 V independiente que coincida con la clasificación de voltaje de su ventilador de 80 mm específico.
* Fuente de alimentación para Raspberry Pi: Fuente de alimentación USB-C oficial de 27 W para la Raspberry Pi 5.
Configuración/Conexión
La configuración del hardware se divide en dos circuitos distintos: el lado lógico de bajo voltaje (sensor y control de relé) y el lado de potencia conmutada (el ventilador).
1. Cableado del sensor BME280 (I2C)
El BME280 se comunica con la Raspberry Pi a través del protocolo I2C.
| Pin del BME280 | Pin de la Raspberry Pi 5 | Número de pin físico |
|---|---|---|
| VCC / VIN | Alimentación 3.3V | Pin 1 |
| GND | Tierra | Pin 9 |
| SDA | GPIO 2 (SDA) | Pin 3 |
| SCL | GPIO 3 (SCL) | Pin 5 |
2. Cableado del módulo de relé de 5 V (Lado lógico)
El módulo de relé utiliza una señal lógica de 5 V para energizar un electroimán interno, que mueve físicamente un interruptor.
| Pin del módulo de relé | Pin de la Raspberry Pi 5 | Número de pin físico |
|---|---|---|
| VCC / DC+ | Alimentación 5V | Pin 2 |
| GND / DC- | Tierra | Pin 6 |
| IN / SIG | GPIO 17 | Pin 11 |
3. Cableado del ventilador de 80 mm (Lado de potencia conmutada)
Elección de diseño: Cableamos el ventilador al terminal Normalmente Abierto (NO). Esto significa que si la Pi está apagada o el script no se está ejecutando, el ventilador permanece apagado. Para un verdadero mecanismo de seguridad a prueba de fallos donde el ventilador funciona si el controlador muere, usaría el terminal Normalmente Cerrado (NC).
- Conecte el cable de Tierra (Negativo) de la fuente de alimentación externa de su ventilador directamente al cable de Tierra (Negativo) del ventilador de 80 mm.
- Conecte el cable Positivo de la fuente de alimentación externa de su ventilador al terminal de tornillo COM (Común) en el módulo de relé.
- Conecte el cable Positivo del ventilador de 80 mm al terminal de tornillo NO (Normalmente Abierto) en el módulo de relé.
Nota: Asegúrese de que las tierras de la Raspberry Pi y la fuente de alimentación externa del ventilador NO estén unidas si son sistemas completamente aislados, ya que el relé proporciona aislamiento mecánico. Si alimenta un ventilador de 5 V directamente desde el riel de 5 V de la Pi (no recomendado para ventiladores grandes debido a los picos de corriente), la tierra se comparte de forma natural.
Código validado
El siguiente script de Python utiliza un patrón de adaptador. Si se ejecuta en una computadora estándar o en una Raspberry Pi que carece de las bibliotecas físicas del sensor, recurre elegantemente a un modo «simulado» (mock). El modo simulado simula el aumento y la caída de la temperatura para validar la lógica de histéresis sin hardware físico.
thermal_watchdog.py
Vista pública parcial del archivo validado. El código completo se muestra a miembros y en PDF/Print.
#!/usr/bin/env python3
"""
Server Rack Thermal Watchdog
Monitors ambient temperature and controls a cooling fan via a relay.
Implements hysteresis to prevent relay chatter.
"""
import time
import logging
import sys
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[logging.StreamHandler(sys.stdout)]
)
# ---------------------------------------------------------
# Hardware Abstraction Layer
# ---------------------------------------------------------
try:
import smbus2
import bme280
from gpiozero import OutputDevice
HARDWARE_AVAILABLE = True
logging.info("Hardware libraries detected. Running in PHYSICAL mode.")
except ImportError:
HARDWARE_AVAILABLE = False
logging.warning("Hardware libraries missing. Running in MOCK mode.")
class BME280Adapter:
"""Adapter for the BME280 I2C sensor."""
def __init__(self, port=1, address=0x76):
self.mock_temp = 25.0
self.mock_direction = 1.0 # 1.0 for heating, -1.0 for cooling
if HARDWARE_AVAILABLE:
try:
self.bus = smbus2.SMBus(port)
self.address = address
# Load calibration parameters
self.calibration_params = bme280.load_calibration_params(self.bus, self.address)
self.is_mock = False
except Exception as e:
logging.error(f"Failed to initialize physical BME280: {e}. Falling back to mock.")
self.is_mock = True
else:
self.is_mock = True
def read_temperature(self) -> float:
"""Returns temperature in Celsius."""
if not self.is_mock:
try:
data = bme280.sample(self.bus, self.address, self.calibration_params)
return data.temperature
except Exception as e:
logging.error(f"Sensor read error: {e}")
return 999.0 # Fail-safe high temperature to trigger cooling
else:
# Simulate temperature rising to 32C then falling to 24C
self.mock_temp += (0.5 * self.mock_direction)
if self.mock_temp >= 32.0:
self.mock_direction = -1.0
elif self.mock_temp <= 24.0:
self.mock_direction = 1.0
return self.mock_temp
# ...#!/usr/bin/env python3
"""
Server Rack Thermal Watchdog
Monitors ambient temperature and controls a cooling fan via a relay.
Implements hysteresis to prevent relay chatter.
"""
import time
import logging
import sys
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[logging.StreamHandler(sys.stdout)]
)
# ---------------------------------------------------------
# Hardware Abstraction Layer
# ---------------------------------------------------------
try:
import smbus2
import bme280
from gpiozero import OutputDevice
HARDWARE_AVAILABLE = True
logging.info("Hardware libraries detected. Running in PHYSICAL mode.")
except ImportError:
HARDWARE_AVAILABLE = False
logging.warning("Hardware libraries missing. Running in MOCK mode.")
class BME280Adapter:
"""Adapter for the BME280 I2C sensor."""
def __init__(self, port=1, address=0x76):
self.mock_temp = 25.0
self.mock_direction = 1.0 # 1.0 for heating, -1.0 for cooling
if HARDWARE_AVAILABLE:
try:
self.bus = smbus2.SMBus(port)
self.address = address
# Load calibration parameters
self.calibration_params = bme280.load_calibration_params(self.bus, self.address)
self.is_mock = False
except Exception as e:
logging.error(f"Failed to initialize physical BME280: {e}. Falling back to mock.")
self.is_mock = True
else:
self.is_mock = True
def read_temperature(self) -> float:
"""Returns temperature in Celsius."""
if not self.is_mock:
try:
data = bme280.sample(self.bus, self.address, self.calibration_params)
return data.temperature
except Exception as e:
logging.error(f"Sensor read error: {e}")
return 999.0 # Fail-safe high temperature to trigger cooling
else:
# Simulate temperature rising to 32C then falling to 24C
self.mock_temp += (0.5 * self.mock_direction)
if self.mock_temp >= 32.0:
self.mock_direction = -1.0
elif self.mock_temp <= 24.0:
self.mock_direction = 1.0
return self.mock_temp
class RelayAdapter:
"""Adapter for the GPIO Relay module."""
def __init__(self, pin=17):
self.state = False
if HARDWARE_AVAILABLE:
try:
# active_high=True means setting to True outputs 3.3V
self.relay = OutputDevice(pin, active_high=True, initial_value=False)
self.is_mock = False
except Exception as e:
logging.error(f"Failed to initialize physical relay on GPIO {pin}: {e}")
self.is_mock = True
else:
self.is_mock = True
def turn_on(self):
if not self.state:
logging.info("ACTION: Energizing relay (Fan ON)")
self.state = True
if not self.is_mock:
self.relay.on()
def turn_off(self):
if self.state:
logging.info("ACTION: De-energizing relay (Fan OFF)")
self.state = False
if not self.is_mock:
self.relay.off()
# ---------------------------------------------------------
# Main Watchdog Logic
# ---------------------------------------------------------
def main():
# Configuration thresholds
TEMP_THRESHOLD_ON = 30.0 # Turn on fan above 30.0 C
TEMP_THRESHOLD_OFF = 27.0 # Turn off fan below 27.0 C
POLL_INTERVAL = 2.0 # Seconds between readings
logging.info(f"Starting Server Rack Thermal Watchdog.")
logging.info(f"Thresholds -> ON: >{TEMP_THRESHOLD_ON}°C, OFF: <{TEMP_THRESHOLD_OFF}°C")
sensor = BME280Adapter(port=1, address=0x76)
fan_relay = RelayAdapter(pin=17)
try:
while True:
current_temp = sensor.read_temperature()
logging.info(f"Current Temperature: {current_temp:.2f}°C")
# Hysteresis Logic
if current_temp > TEMP_THRESHOLD_ON:
fan_relay.turn_on()
elif current_temp < TEMP_THRESHOLD_OFF:
fan_relay.turn_off()
# If temperature is between OFF and ON thresholds, do nothing (maintain current state)
time.sleep(POLL_INTERVAL)
except KeyboardInterrupt:
logging.info("Watchdog terminated by user. Shutting down safely.")
finally:
# Ensure fan is turned off on script exit (optional, depends on fail-safe preference)
fan_relay.turn_off()
logging.info("Cleanup complete.")
if __name__ == "__main__":
main()
thermal-watchdog.service
Para garantizar que el script se ejecute automáticamente cuando la Raspberry Pi arranque, definimos un servicio systemd. Guarde esto como thermal-watchdog.service.
[Unit]
Description=Server Rack Thermal Watchdog Service
After=network.target
[Service]
Type=simple
# Adjust the path to match where you cloned/saved the script and venv
ExecStart=/home/pi/watchdog/venv/bin/python /home/pi/watchdog/thermal_watchdog.py
WorkingDirectory=/home/pi/watchdog
StandardOutput=journal
StandardError=journal
Restart=always
RestartSec=5
User=pi
[Install]
WantedBy=multi-user.target
Comandos de Compilación/Flasheo/Ejecución
Raspberry Pi OS Bookworm utiliza PEP 668, que restringe las instalaciones globales de pip. Por lo tanto, utilizamos un entorno virtual de Python.
| Comando | Descripción |
|---|---|
sudo apt-get update && sudo apt-get install -y python3-venv i2c-tools | Instala herramientas de entorno virtual y utilidades de depuración de I2C. |
mkdir -p ~/watchdog && cd ~/watchdog | Crea el directorio del proyecto y navega hacia él. |
python3 -m venv venv | Crea un entorno virtual de Python aislado llamado venv. |
source venv/bin/activate | Activa el entorno virtual. |
pip install smbus2 RPi.bme280 gpiozero | Instala las bibliotecas de interfaz de hardware requeridas. |
python3 thermal_watchdog.py | Ejecuta el script del perro guardián directamente en la terminal. |
Flujo de trabajo de instalación del servicio:
1. Copie el archivo de servicio: sudo cp thermal-watchdog.service /etc/systemd/system/
2. Recargue el demonio de systemd: sudo systemctl daemon-reload
3. Habilite el servicio para que se inicie en el arranque: sudo systemctl enable thermal-watchdog.service
4. Inicie el servicio inmediatamente: sudo systemctl start thermal-watchdog.service
5. Vea los registros en vivo: journalctl -u thermal-watchdog.service -f
Validación paso a paso
Utilice los siguientes puntos de control para asegurarse de que su perro guardián térmico para rack de servidores funcione correctamente.
- Detección del bus I2C
- Acción: Ejecute
i2cdetect -y 1en la terminal. - Observación: Aparece una cuadrícula de números.
- Condición de aprobación: El número
76(o77) aparece en la cuadrícula, lo que confirma que la Raspberry Pi 5 se comunica correctamente con el sensor BME280.
- Acción: Ejecute
- Ejecución de prueba / Validación simulada
- Acción: Ejecute el script en una PC o en la Pi antes de instalar
smbus2/gpiozero. - Observación: La consola registra «Hardware libraries missing. Running in MOCK mode.» seguido de temperaturas que aumentan desde 25.0°C.
- Condición de aprobación: Cuando la temperatura simulada alcanza los 30.5°C, el registro muestra «ACTION: Energizing relay (Fan ON)». Cuando cae por debajo de 27.0°C, registra «ACTION: De-energizing relay (Fan OFF)».
- Acción: Ejecute el script en una PC o en la Pi antes de instalar
- Validación del sensor físico
- Acción: Ejecute el script en la Pi con el entorno virtual activado y el hardware conectado.
- Observación: La consola registra la temperatura ambiente actual.
- Condición de aprobación: La lectura de temperatura es estable y coincide con la temperatura ambiente aproximada de la habitación.
- Prueba de activación de histéresis
- Acción: Pellizque suavemente el sensor BME280 entre sus dedos para elevar su temperatura artificialmente.
- Observación: La temperatura registrada aumenta.
- Condición de aprobación: A medida que la temperatura cruza los 30.0°C, el relé físico produce un sonido de «clic» distintivo, un LED integrado en el módulo de relé se ilumina
Encuentra este producto y/o libros sobre este tema en Amazon
Como afiliado de Amazon, gano con las compras que cumplan los requisitos. Si compras a través de este enlace, ayudas a mantener este proyecto.




