Un proyecto Raspberry Pi Sense HAT MQTT es una de las formas más rápidas de construir un dispositivo IoT bidireccional de verdad: la placa ya incluye sensores de temperatura, humedad y presión, un acelerómetro, un giroscopio y un magnetómetro, un joystick y una matriz LED RGB de 8x8. En este tutorial publicarás datos ambientales e IMU como JSON en un broker MQTT y harás desfilar por la matriz LED cualquier mensaje enviado a la Pi, todo en un único script de Python.
Qué te ofrece el Sense HAT
| Sensor o salida | Llamada en Python | Unidades |
|---|---|---|
| Temperatura | sense.get_temperature() |
grados Celsius |
| Humedad relativa | sense.get_humidity() |
porcentaje |
| Presión | sense.get_pressure() |
milibares (hPa) |
| Orientación | sense.get_orientation() |
pitch, roll, yaw en grados |
| Aceleración | sense.get_accelerometer_raw() |
x, y, z en g |
| Joystick | sense.stick.get_events() |
dirección y acción |
| Matriz LED | sense.show_message(), sense.clear() |
RGB de 8x8 |
El HAT se conecta directamente al conector de 40 pines de cualquier Pi que lo tenga, incluidas la Pi 4 y la Pi 5. No hace falta cablear nada, lo que lo hace ideal para aulas, demos y prototipos rápidos. La documentación oficial del Sense HAT explica el hardware en profundidad.
Instalación del software
La librería del Sense HAT se distribuye como paquete Debian. Instálala a nivel de sistema y después crea un entorno virtual que pueda verla:
sudo apt update
sudo apt install -y sense-hat python3-venv
mkdir -p ~/sensehat-mqtt && cd ~/sensehat-mqtt
python3 -m venv --system-site-packages .venv
source .venv/bin/activate
pip install "paho-mqtt>=2.0"
Comprueba que se detecta el HAT antes de escribir código MQTT:
python -c "from sense_hat import SenseHat; s = SenseHat(); print(s.get_temperature(), s.get_humidity()); s.show_message('OK')"
Si ves dos números y "OK" desfila por la matriz, el hardware está listo. Si obtienes un error sobre el framebuffer o I2C, confirma que el HAT está bien encajado y que I2C está activado en sudo raspi-config, en Interface Options.
Estructura de topics
Mantén los topics del Sense HAT bajo un prefijo único para que nada choque con otros usuarios del servidor de pruebas compartido:
| Topic | Dirección | Frecuencia | Retained |
|---|---|---|---|
connectmq/demo/5d82be/sensehat/env |
La Pi publica | Cada 10 s | No |
connectmq/demo/5d82be/sensehat/imu |
La Pi publica | Cada 1 s | No |
connectmq/demo/5d82be/sensehat/joystick |
La Pi publica | Por evento | No |
connectmq/demo/5d82be/sensehat/display |
La Pi se suscribe | Bajo demanda | No |
connectmq/demo/5d82be/sensehat/status |
La Pi publica y last will | Al conectar | Sí |
Sustituye 5d82be por tu propia cadena aleatoria. El broker público permite 10 mensajes por segundo por cliente, así que un mensaje IMU por segundo más los eventos ambientales y del joystick ocasionales quedan holgadamente por debajo del límite.
El script Raspberry Pi Sense HAT MQTT
El punto de diseño importante es que show_message() bloquea mientras el texto se desplaza. Si la llamas desde el callback MQTT, el bucle de red se detiene y el cliente puede perder keepalives. El script de abajo mete los mensajes entrantes en una cola y deja que un hilo de visualización aparte los muestre, mientras el hilo principal lee los sensores y publica. Guárdalo como sensehat_mqtt.py:
#!/usr/bin/env python3
"""Publish Sense HAT data over MQTT and show incoming messages on the LED matrix."""
import json
import os
import queue
import threading
import time
import uuid
import paho.mqtt.client as mqtt
from sense_hat import SenseHat
BROKER = os.getenv("MQTT_HOST", "broker.connectmq.com")
PORT = int(os.getenv("MQTT_PORT", "1883"))
USERNAME = os.getenv("MQTT_USERNAME")
PASSWORD = os.getenv("MQTT_PASSWORD")
CLIENT_ID = os.getenv("MQTT_CLIENT_ID", f"sensehat-{uuid.uuid4().hex[:8]}")
PREFIX = os.getenv("MQTT_PREFIX", "connectmq/demo/5d82be/sensehat")
ENV_INTERVAL = 10
IMU_INTERVAL = 1
CPU_FACTOR = 2.0 # calibrar con un termómetro de referencia
sense = SenseHat()
sense.set_imu_config(True, True, True) # brújula, giroscopio, acelerómetro
sense.low_light = True
messages = queue.Queue(maxsize=20)
def cpu_temperature():
with open("/sys/class/thermal/thermal_zone0/temp") as f:
return int(f.read()) / 1000.0
def corrected_temperature():
raw = sense.get_temperature_from_humidity()
cpu = cpu_temperature()
# El HAT está encima de la CPU, así que sus sensores marcan de más. Esta
# heurística sencilla resta parte de la diferencia; ajusta CPU_FACTOR a tu caso.
return raw - (cpu - raw) / CPU_FACTOR, raw
def display_worker():
while True:
text, colour = messages.get()
try:
sense.show_message(text, scroll_speed=0.06, text_colour=colour)
finally:
sense.clear()
def on_connect(client, userdata, flags, reason_code, properties):
if reason_code.is_failure:
print(f"Connection refused: {reason_code}")
return
print(f"Connected as {CLIENT_ID}")
client.publish(f"{PREFIX}/status", "online", qos=1, retain=True)
client.subscribe(f"{PREFIX}/display", qos=1)
def on_message(client, userdata, msg):
raw = msg.payload.decode(errors="ignore").strip()
colour = [255, 255, 255]
text = raw
if raw.startswith("{"):
try:
data = json.loads(raw)
text = str(data.get("text", ""))
colour = data.get("colour", colour)
except json.JSONDecodeError:
pass
text = text[:80]
if text:
try:
messages.put_nowait((text, colour))
except queue.Full:
print("Display queue full, dropping message")
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
client.on_connect = on_connect
client.on_message = on_message
client.will_set(f"{PREFIX}/status", "offline", qos=1, retain=True)
client.reconnect_delay_set(min_delay=1, max_delay=60)
if USERNAME:
client.username_pw_set(USERNAME, PASSWORD)
if PORT == 8883:
client.tls_set()
threading.Thread(target=display_worker, daemon=True).start()
client.connect(BROKER, PORT, keepalive=30)
client.loop_start()
last_env = 0.0
last_imu = 0.0
try:
while True:
now = time.time()
# Consultar la orientación a menudo para que la fusión de sensores sea precisa.
orientation = sense.get_orientation()
if now - last_imu >= IMU_INTERVAL:
accel = sense.get_accelerometer_raw()
imu = {
"pitch": round(orientation["pitch"], 1),
"roll": round(orientation["roll"], 1),
"yaw": round(orientation["yaw"], 1),
"ax": round(accel["x"], 3),
"ay": round(accel["y"], 3),
"az": round(accel["z"], 3),
"ts": int(now),
}
client.publish(f"{PREFIX}/imu", json.dumps(imu), qos=0)
last_imu = now
if now - last_env >= ENV_INTERVAL:
temp, raw_temp = corrected_temperature()
env = {
"temperature": round(temp, 1),
"temperature_raw": round(raw_temp, 1),
"humidity": round(sense.get_humidity(), 1),
"pressure": round(sense.get_pressure(), 1),
"cpu_temp": round(cpu_temperature(), 1),
"ts": int(now),
}
client.publish(f"{PREFIX}/env", json.dumps(env), qos=1)
last_env = now
for event in sense.stick.get_events():
if event.action == "pressed":
payload = {"direction": event.direction, "ts": int(event.timestamp)}
client.publish(f"{PREFIX}/joystick", json.dumps(payload), qos=1)
time.sleep(0.05)
except KeyboardInterrupt:
pass
finally:
client.publish(f"{PREFIX}/status", "offline", qos=1, retain=True).wait_for_publish(2)
client.loop_stop()
client.disconnect()
sense.clear()
Ejecútalo con python sensehat_mqtt.py. El bucle principal consulta la orientación cada 50 ms porque la fusión de sensores del Sense HAT necesita lecturas frecuentes para mantener estables pitch, roll y yaw, pero solo publica una vez por segundo.
Enviar mensajes a la matriz LED
Desde cualquier equipo, suscríbete primero a los datos:
mosquitto_sub -h broker.connectmq.com -p 1883 -i viewer-5d82be \
-t 'connectmq/demo/5d82be/sensehat/#' -v
Después envía texto plano o un mensaje JSON con un color:
mosquitto_pub -h broker.connectmq.com -p 1883 -i sender-5d82be \
-t 'connectmq/demo/5d82be/sensehat/display' -m 'Hello from MQTT'
mosquitto_pub -h broker.connectmq.com -p 1883 -i sender-5d82be \
-t 'connectmq/demo/5d82be/sensehat/display' \
-m '{"text":"Door open","colour":[255,80,0]}'
El mensaje desfila en blanco o naranja mientras la temperatura y la orientación siguen llegando. Inclina la Pi y observa cómo cambian pitch y roll en la ventana del suscriptor; pulsa el joystick para ver llegar los eventos. El topic de visualización no es retained a propósito; de lo contrario, el último mensaje se repetiría cada vez que la Pi se reconecta.
Lecturas de temperatura fiables
El Sense HAT está justo encima del procesador, así que sus sensores de temperatura marcan varios grados de más, todavía más en una Pi 4 o Pi 5 con carga. El script publica tanto el valor en bruto como una estimación corregida. Para calibrar la corrección:
- Coloca un termómetro fiable junto a la Pi y deja que ambos se estabilicen durante 20 minutos.
- Compara la referencia con
temperature_rawycpu_tempde los mensajes MQTT. - Ajusta
CPU_FACTORhasta quetemperaturecoincida con la referencia. - Para mayor precisión, conecta el HAT mediante un cable plano de extensión de 40 pines para que quede alejado de la CPU.
Si necesitas una temperatura ambiente precisa en lugar de una demo, una sonda dedicada es la mejor herramienta. Nuestras guías de Raspberry Pi con DHT22 y MQTT y de la sonda 1-Wire DS18B20 muestran cómo publicar sensores externos con el mismo estilo de topics.
Visualizar los datos
Como todo viaja como JSON compacto por MQTT, cualquier suscriptor puede usarlo. Node-RED puede dibujar un indicador en vivo, Telegraf puede escribirlo en InfluxDB y Grafana puede graficar meses de histórico; la guía de Raspberry Pi con Grafana e InfluxDB construye esa pila. Para echar un vistazo rápido sin instalar nada, el cliente MQTT en el navegador y el explorador de topics en vivo del portal de ConnectMQ muestran cada mensaje env e imu en cuanto llega.
De la demo a un broker privado
El servidor MQTT público gratuito es legible por cualquiera, lo que está bien para un saludo en la matriz pero no para un sensor en tu casa o tu aula. ConnectMQ te ofrece un broker privado con credenciales generadas y TLS. Define cuatro variables de entorno y el script se conecta de forma segura:
export MQTT_HOST=broker.connectmq.com
export MQTT_PORT=8883
export MQTT_USERNAME=YOUR_USERNAME
export MQTT_PASSWORD=YOUR_PASSWORD
export MQTT_CLIENT_ID=YOUR_CLIENT_ID
export MQTT_PREFIX=classroom/lab1/sensehat
python sensehat_mqtt.py
Para que el script siga funcionando tras un reinicio, envuélvelo en un servicio systemd como se muestra en el tutorial de MQTT con Raspberry Pi.
Ideas para ampliar el proyecto
Cuando el bucle básico funcione, el Sense HAT se convierte en un banco de pruebas práctico para patrones MQTT que reutilizarás en dispositivos reales:
- Alarma de inclinación: haz que un segundo script se suscriba al topic
imuy publique un aviso cuando pitch o roll superen un límite, un sustituto sencillo para vigilar una máquina que no debería moverse. - Tablero de estado remoto: publica cadenas de estado cortas desde un pipeline de CI, un flujo de domótica o un chequeo de salud de un servidor en el topic
displayy usa la matriz como notificador de escritorio. - Joystick como mando a distancia: suscríbete al topic
joystickdesde Node-RED y asigna cada dirección a una escena, un relé o una página de dashboard. - Alertas por umbral sin código: en un broker privado de ConnectMQ, define en el portal una regla de alerta sobre el valor de humedad del topic
envy revisa las alertas disparadas en el registro de alertas. - Varias aulas: da a cada Pi su propio nivel de prefijo, como
school/room12/sensehat, y suscríbete con un comodín+para comparar las aulas lado a lado.
Cada idea solo necesita un nuevo suscriptor o un nuevo topic. El script de la Pi sigue igual, que es justo el desacoplamiento que hace agradable trabajar con MQTT.
Solución de problemas
OSError: Cannot detect RPi-Sense FB device: no se detecta el HAT; vuelve a encajarlo con la Pi apagada.- El yaw deriva o salta: calibra el magnetómetro y mantén la Pi alejada de motores y altavoces; la orientación también necesita consultas frecuentes.
- Los mensajes desfilan pero los datos de los sensores se detienen: algo bloquea el bucle principal; nunca llames a
show_message()desde un callback. - La humedad marca 0: el sensor de humedad necesita un momento tras el arranque; descarta la primera lectura.
Empieza con ConnectMQ
Pasa tu Sense HAT del entorno público de pruebas a un broker privado en pocos minutos. Crea un broker Serverless gratuito, sin tarjeta de crédito, y conéctate por TLS con las credenciales generadas. Obtienes un broker MQTT gestionado compatible con MQTT 3.1.1 y 5.0, además de un portal desde el que puedes enviar mensajes a la matriz y ver cada lectura en vivo.
Preguntas frecuentes
¿Por qué la temperatura del Sense HAT es más alta que la de la habitación?
El calor del procesador de la Raspberry Pi calienta el HAT. Usa la corrección basada en la CPU de este tutorial, un cable plano de extensión o un sensor externo para obtener lecturas precisas.
¿Puedo publicar datos del Sense HAT más de una vez por segundo?
Sí, pero respeta los límites de tasa de tu broker; el servidor público de pruebas permite 10 mensajes por segundo por cliente. Para datos de movimiento de alta frecuencia, agrupa varias muestras en un solo mensaje JSON.
¿Funciona el Sense HAT en una Raspberry Pi 5?
Sí, usa el conector estándar de 40 pines y el paquete sense-hat de Raspberry Pi OS. Espera desfases de temperatura mayores porque la Pi 5 se calienta más.
¿Cómo envío texto en color a la matriz LED?
Publica un JSON como {"text":"Hi","colour":[0,255,0]} en el topic de visualización. El script lee el color como una lista RGB y usa blanco por defecto para el texto plano.



