Medir la temperatura de la Raspberry Pi para activar el ventilador y recibir una alerta por Telegram

Uno de los usos que le doy a mi Raspberry Pi es la de servidor Plex para disfrutar de mis series y películas desde cualquier sitio y compartirlas con mis amigos (os explicaré cómo hacerlo próximamente). Esta Raspberry la tengo montada con un kit de refrigeración que se compone de varios disipadores, una carcasa y un ventilador (como éste). La tengo así para evitar que su temperatura pase de unos niveles seguros y que se dañe o su tiempo de vida se vea reducido. Sin embargo, de un tiempo a esta parte el ventilador empezó a hacer demasiado ruido y, teniendo en cuenta que el uso que le estoy dando no es como para que su temperatura ascienda demasiado, me planteé la idea de cómo medir la temperatura de la Raspberry Pi para activar el ventilador y, de paso, recibir una alerta por Telegram. De esta forma, el ventilador funciona únicamente cuando es necesario y estoy informado de que la temperatura ha subido. Te explico paso a paso todo lo necesario para que puedas hacer lo mismo en tu Raspberry Pi, pero antes veamos unos conceptos básicos previos.

¿Qué son los pines GPIO?

Tal y como explican en Programo Ergo Sum, GPIO (General Purpose Input Output) es un sistema de entrada y salida de propósito general que consta de una serie de pines o conexiones que se pueden usar como entradas o salidas para múltiples usos. Son esos pinchitos que están en uno de los laterales de tu Raspberry Pi. Cada uno de ellos tiene una función específica:

Estos pines se pueden organizar de la siguiente forma:

  • Amarillo (2): Alimentación a 3.3V.
  • Rojo (2): Alimentación a 5V.
  • Naranja (26): Configurables como entrada/salida a un valor máximo de 3.3V.
  • Gris (2): Reservados.
  • Negro (8): GND o masa.
  • Azul (2): Comunicación mediante el protocolo I2C para comunicarse con periféricos que siguen este protocolo.
  • Verde (2): Destinados a conexión para UART para puerto serie convencional.
  • Morado (5): Comunicación mediante el protocolo SPI para comunicarse con periféricos que siguen este protocolo.

Existen 2 formas de numerar los pines de la Raspberry Pi, en modo GPIO o en modo BCM.

  • Modo GPIO: los pines se numeran de forma física por el lugar que ocupan en la placa (representados por el color gris en la imagen anterior) comenzando a contar desde arriba a la izquierda y finalizamos abajo a la derecha.
  • Modo BCM: los pines se numeran por la correspondencia en la CPU de la Raspberry Pi. Puedes ver la nomenclatura BCM en los rectángulos de color naranja, morado, azul o verde de la imagen anterior.

Pasos previos

Conectar ventilador al GPIO de la Raspberry Pi

Mi recomendación es que lo primero que hagáis sea conectar el ventilador al GPIO. Antes incluso de encender la Raspberry. De esta forma nos aseguramos de no quemarla si nos equivocamos al conectar el ventilador en un momento dado, teniendo tiempo de corregir nuestro error antes de quemar la placa.

Hasta ahora yo tenía mi ventilador conectado a uno de los pines rojos (al 4 según la nomenclatura GPIO, para ser más exactos). Esto hacía que el ventilador estuviera recibiendo 5V constantemente y, por tanto, siempre en funcionamiento a la máxima potencia. Para mi solución lo que tenemos que hacer es conectarlo a uno de los pines naranja. En concreto al GPIO 4 según la nomenclatura BCM o al pin 7 según la nomenclatura GPIO. A este pin conectamos el cable rojo (o positivo) del  ventilador. El cable negro (o negativo) lo tenemos que conectar a cualquiera de los pines negros de la placa. En mi caso, la placa ha quedado así:

Acceso SSH a nuestra Raspberry Pi

Ahora que ya tenemos nuestro ventilador conectado, ya podemos encender la Raspberry Pi. Mi consejo es que, por comodidad y facilidad, si para su uso no es necesario que tu Raspberry esté conectada a una pantalla, hagas las instalación de Raspbian sin entorno gráfico, tal y como expliqué en mi tutorial «Instalar Raspbian sin pantalla por SSH«. Si ya instalaste Raspbian con entorno gráfico y no quieres cambiarlo, también puedes seguir los pasos de mi otro tutorial «Controlar Raspberry por SSH«. Si por el contrario, tienes tu Raspberry Pi conectada a una pantalla, a un teclado y a un ratón, puedes seguir los pasos igualmente sin ningún problema.

Instalar librería GPIO para Python

Para que mi script Python funcione en tu Raspberry Pi posiblemente tengas que instalar previamente la librería GPIO para Python. Para ello, en una consola de nuestra Raspberry ejecutamos primero el siguiente comando para actualizar los paquetes de nuestro sistema Raspbian:

sudo apt-get update

Y luego el siguiente comando para instalar la librería GPIO para Python:

sudo apt-get install rpi.gpio

Con esto ya no deberíamos tener ningún problema al ejecutar el script.

Crear bot de Telegram

Otra de las cosas que vamos a necesitar para que nuestro script funcione es crear un bot de Telegram. Será el encargado de enviarnos las alertas de temperatura por Telegram. Si no sabes cómo crearlo, puedes ver cómo hacerlo en mi tutorial «Crear un bot de Telegram«.

Además de crear el bot, necesitamos crear un canal por el que recibir las alertas. Para ello, en Telegram pulsamos sobre el icono con tres líneas horizontales que hay arriba a la izquierda.

Y luego en «Crear canal».

Le damos un nombre a nuestro canal y pulsamos sobre el check que hay arriba a la derecha.

Indicamos que nuestro canal va a ser privado y volvemos a pulsar sobre el check de arriba a la derecha.

Y buscamos nuestro bot como si fuera un contacto más de nuestra lista. Cuando lo hayamos seleccionado, pulsamos sobre la flecha que hay abajo a la derecha

Y confirmamos la lista de suscriptores a nuestra canal pulsando una vez más sobre la flecha de abajo a la derecha.

Y ya tenemos nuestro canal de alertas de temperatura creado y nuestro bot preparado para avisarnos.

Ahora necesitamos averiguar el ID de nuestro canal. Para eso escribimos cualquier cosa y lo enviamos al canal.

Y cuando lo hayamos hecho, en nuestro ordenador abrimos nuestro explorador de Internet y accedemos a la siguiente URL:

https://api.telegram.org/bot[TOKEN]/getUpdates

Donde tenemos que sustituir «[TOKEN]» por el token de nuestro bot que obtuvimos al crearlo. En esta URL veremos algo así:

{"ok":true,"result":[{"update_id":861144864,
"channel_post":{"message_id":5,"chat":{"id":-1234567890123,"title":"Control de temperatura","type":"channel"},"date":1585684472,"text":"Hola"}}]}

De todo este texto lo que nos interesa es el valor correspondiente a «id», que en mi caso es «-1234567890123», incluyendo el guión. Este es el ID del canal, y tenemos que guardarlo para usarlo más adelante en nuestro script.

Código del script

Ahora que ya tenemos el ventilador conectado a la placa y la librería necesaria instalada, vamos a proceder con el script, que yo he llamado «check_temp.py». Al final del todo explicaré cómo descargar el script completo, pero primero vamos a ver todo paso a paso.

Para que nuestro script funcione necesitamos medir la temperatura de la CPU, medir la temperatura de la GPU, activar o desactivar un pin GPIO y enviar un mensaje a Telegram.

Obtener la temperatura de la CPU de la Raspberry Pi

Para obtener la temperatura de la CPU de la Raspberry Pi tenemos que ejecutar el siguiente comando:

cat /sys/class/thermal/thermal_zone0/temp

Este comando es el que usaremos en el script, y quedaría de la siguiente forma:

def cpu_temp():
	thermal_zone = subprocess.Popen(['cat', '/sys/class/thermal/thermal_zone0/temp'], stdout=subprocess.PIPE)
	out, err = thermal_zone.communicate()
	cpu_temp = int(out.decode())/1000
	return cpu_temp

Obtener la temperatura de la GPU de la Raspberry Pi

Para obtener la temperatura de la GPU de la Raspberry Pi tenemos que ejecutar el siguiente comando:

/opt/vc/bin/vcgencmd measure_temp

Igual que con la temperatura de la CPU, este comando es el que usaremos en el script y quedaría así:

def gpu_temp():
	measure_temp = subprocess.Popen([', que '], stdout=subprocess.PIPE)
	out, err = measure_temp.communicate()
	gpu_temp = out.decode().split('=')[1].split('\'')[0]
	return gpu_temp

Enviar mensaje a Telegram

Y para alertarnos del estado de la temperatura de nuestra Raspberry vamos a enviar un mensaje a nuestro canal de Telegram usando esta otra función de Python:

def send_warning(message):
	dir = os.path.dirname(os.path.abspath(__file__))
	filename = os.path.join(dir,'keys.json')
	f = open(filename, 'r')
	content = f.read()
	f.close()
	data = json.loads(content)
	url = 'https://api.telegram.org/bot{0}/sendMessage'.format(data['token'])
	data = {'chat_id': data['channel_id'], 'text': message}
	r = requests.post(url, data)

Este método necesita para funcionar el token de nuestro bot de Telegram y el ID del canal al que debe de enviar el aviso. Sin embargo, aún no le hemos indicado a nuestro script cuál es el token de nuestro bot de Telegram ni el ID del canal al que debe de enviar el aviso. Para que el método tenga estos datos, debemos de crear un fichero llamado ‘keys.json’ en el mismo directorio que nuestro script. Este fichero debe tener el token del bot y el ID del canal estructurados de la siguiente forma:

{"token": "[TOKEN]", "channel_id": "[ID_CANAL]"}

Donde [TOKEN] se corresponde con el token de tu bot de Telegram y [ID_CANAL] con el ID de tu canal de Telegram para las alertas.

Definir pines GPIO en Python

Y por último, tenemos que definir en nuestro script el pin GPIO que vamos a usar para activar el ventilador. Para eso tenemos que agregar las siguientes líneas al código:

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(7,GPIO.OUT)

Con este código desactivamos los posibles mensajes de aviso que nos pueda devolver la librería, indicamos que se va a usar la nomenclatura GPIO (GPIO.BOARD) para indicar el pin a usar, y establecemos el pin 7 como salida (GPIO.OUT).

Completar script

Una vez tenemos definidas todas las funciones que vamos a usar y hemos definido el pin que vamos a usar solamente nos queda importar en nuestro script las librerías que necesitamos para que todo funcione y definir una función principal que será la que ejecute todo el código. Al final, el código completo quedaría así:

#!/usr/bin/env python3
import subprocess
import os
import json
import requests
import RPi.GPIO as GPIO

def cpu_temp():
	thermal_zone = subprocess.Popen(['cat', '/sys/class/thermal/thermal_zone0/temp'], stdout=subprocess.PIPE)
	out, err = thermal_zone.communicate()
	cpu_temp = int(out.decode())/1000
	return cpu_temp

def gpu_temp():
	measure_temp = subprocess.Popen([', que '], stdout=subprocess.PIPE)
	out, err = measure_temp.communicate()
	gpu_temp = out.decode().split('=')[1].split('\'')[0]
	return gpu_temp

def send_warning(message):
	dir = os.path.dirname(os.path.abspath(__file__))
	filename = os.path.join(dir,'keys.json')
	f = open(filename, 'r')
	content = f.read()
	f.close()
	data = json.loads(content)
	url = 'https://api.telegram.org/bot{0}/sendMessage'.format(data['token'])
	data = {'chat_id': data['channel_id'], 'text': message}
	r = requests.post(url, data)

def check_temp():
	cpu = cpu_temp()
	gpu = gpu_temp()
	if (float(cpu) > 45 or float(gpu) > 45) and not GPIO.input(7):
		GPIO.output(7, True)
		send_warning("CPU: "+str(cpu)+"º\nGPU: "+str(gpu)+"º")
	elif float(cpu) <= 40 and float(gpu) <= 40 and GPIO.input(7):
		GPIO.output(7, False)
		send_warning("CPU: "+str(cpu)+"º\nGPU: "+str(gpu)+"º")

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(7,GPIO.OUT)
check_temp()

print ("CPU: "+str(cpu_temp())+"º")
print ("GPU: "+str(gpu_temp())+"º")

Como podéis comprobar en el código, yo lo tengo programado para que active el ventilador y me avise por Telegram cuando la temperatura de la CPU o la temperatura de la GPU pasen de 45º y desactive el ventilador y me avise por Telegram cuando la temperatura baje de 40º. De esta forma no solamente sabré cuándo la temperatura se está elevando, sino también cuándo vuelve a estar otra vez en sus valores correctos.

También puedes descargarte el código completo ejecutando el siguiente comando:

git clone https://github.com/manucabello/raspberry-check-temperature.git

Y te descargarás el script listo para usar desde mi perfil de Git. Tú solamente te tendrás que preocupar de añadir el fichero ‘keys.json’ que he explicado más arriba para que el script tenga el token del bot y el ID del canal de Telegram.

Ahora, si queremos probar que el script funciona correctamente debemos ejecutar el siguiente comando:

python3 check_temp.py

Y como resultado verás en la consola algo así:

Y, si la temperatura es superior a 45º, recibiremos un mensaje de Telegram en nuestro canal informando de ello. En ese caso también veremos cómo el ventilador empieza a funcionar.

Programar script para que se ejecute automáticamente con cron

Hasta ahora tenemos el ventilador conectado al GPIO de la Raspberry, el bot y el canal de Telegram preparados y el script descargado. Pero solamente podemos hacerlo funcionar de forma manual ejecutando el comando. Lo ideal es que la Raspberry haga esta comprobación automáticamente cada cierto tiempo. Para ello vamos a usar cron. De esta herramienta ya hablé en mi tutorial «Comprobar automáticamente la dirección IP pública de nuestra Raspberry Pi«, así que aquí voy a poner únicamente la línea que he añadido a mi crontab para que el script se ejecute automáticamente. Si tenéis alguna duda sobre el funcionamiento de cron, en ese tutorial queda muy bien explicado.

Ejecutando el comando:

sudo crontab -e

Accedo al crontab del usuario administrador. Es importante ejecutar el comando con sudo para que todo funcione bien. Al final del crontab añado la siguiente línea:

* * * * * sudo python3 /home/pi/check-temperature/check_temp.py

Y por último ejecuto el siguiente comando para actualizar el cron:

sudo service cron restart

¡Y listo! ¡Ya tenemos nuestro controlador de temperatura que nos activa el ventilador automáticamente y nos avisa por Telegram gracias a nuestro nuevo bot!

Como siempre, cualquier sugerencia o consulta podéis hacérmela llegar enviando un correo electrónico a sugerencias@manusoft.es o dejando un comentario en la entrada. ¡Muchas gracias por visitar ManuSoft.es!

Publicado en Raspberry Pi y etiquetado , , , , , .

2 Comentarios

  1. Tengo una Raspberry Pi 4B y he encontrado tu tutorial que me vendrá perfecto para reducir el ruido del ventilador sobretodo de noche, pero no me funciona. No me pone en marcha el ventilador de la PI.

    Si ejecuto tras clonar el programa y rellenar el keys.json, python3 check_temp.py me sale por ejemplo:
    CPU: 55.504º
    GPU: 55.0º

    Teóricamente debería ponerse en marcha, pero no… Tampoco me envía el mensaje a Telegram (token y chat cogidos de una automatización de Home-Assistant que está funcionando) aunque no me importa demasiado eso.

    Gracias por tu ayuda y por compartir tus conocimientos.

    Un saludo

    Comentarte que no tengo ni idea de programación y que simplemente soy un sigue guías, pero, ¿alguna idea?

  2. Hola!
    Me pasa lo mismo que a Javier. Llega a ejecutarse y muestra la temperatura, pero el ventilador no funciona.
    Muchas gracias.
    Un saludo.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *