Um projeto Raspberry Pi Sense HAT MQTT é um dos caminhos mais rápidos para montar um dispositivo IoT bidirecional de verdade: a placa já traz sensores de temperatura, umidade e pressão, acelerômetro, giroscópio e magnetômetro, um joystick e uma matriz de LED RGB 8x8. Neste tutorial você vai publicar dados ambientais e da IMU em JSON para um broker MQTT e rolar na matriz de LED qualquer mensagem enviada ao Pi, tudo em um único script Python.
O que o Sense HAT oferece
| Sensor ou saída | Chamada Python | Unidades |
|---|---|---|
| Temperatura | sense.get_temperature() |
graus Celsius |
| Umidade relativa | sense.get_humidity() |
percentual |
| Pressão | sense.get_pressure() |
milibar (hPa) |
| Orientação | sense.get_orientation() |
pitch, roll e yaw em graus |
| Aceleração | sense.get_accelerometer_raw() |
x, y, z em g |
| Joystick | sense.stick.get_events() |
direção e ação |
| Matriz de LED | sense.show_message(), sense.clear() |
RGB 8x8 |
O HAT encaixa direto no conector de 40 pinos de qualquer Pi que tenha esse conector, incluindo o Pi 4 e o Pi 5. Não é preciso fazer nenhuma ligação, o que o torna ideal para salas de aula, demonstrações e protótipos rápidos. A documentação oficial do Sense HAT cobre o hardware em detalhes.
Instalando o software
A biblioteca do Sense HAT é distribuída como pacote Debian. Instale-a no sistema e depois crie um ambiente virtual que consiga enxergá-la:
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"
Confirme que o HAT foi detectado antes de escrever qualquer código MQTT:
python -c "from sense_hat import SenseHat; s = SenseHat(); print(s.get_temperature(), s.get_humidity()); s.show_message('OK')"
Se aparecerem dois números e "OK" rolar pela matriz, o hardware está pronto. Se surgir um erro de framebuffer ou I2C, verifique se o HAT está bem encaixado e se o I2C está habilitado em sudo raspi-config, em Interface Options.
Estrutura de topics
Mantenha os topics do Sense HAT sob um prefixo único para que nada colida com outros usuários do broker de testes compartilhado:
| Topic | Direção | Frequência | Retained |
|---|---|---|---|
connectmq/demo/5d82be/sensehat/env |
Pi publica | A cada 10 s | Não |
connectmq/demo/5d82be/sensehat/imu |
Pi publica | A cada 1 s | Não |
connectmq/demo/5d82be/sensehat/joystick |
Pi publica | Por evento | Não |
connectmq/demo/5d82be/sensehat/display |
Pi assina | Sob demanda | Não |
connectmq/demo/5d82be/sensehat/status |
Pi publica e last will | Ao conectar | Sim |
Substitua 5d82be por uma string aleatória sua. O broker público permite 10 mensagens por segundo por cliente, então uma mensagem da IMU por segundo mais eventos ocasionais de ambiente e joystick ficam com folga abaixo do limite.
O script Raspberry Pi Sense HAT MQTT
O ponto de projeto mais importante é que show_message() bloqueia enquanto o texto rola. Se você chamá-la a partir do callback MQTT, o loop de rede trava e o cliente pode perder keepalives. O script abaixo coloca as mensagens recebidas em uma fila e deixa uma thread de exibição separada rolá-las, enquanto a thread principal lê os sensores e publica. Salve-o 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 # calibre com um termômetro de referência
sense = SenseHat()
sense.set_imu_config(True, True, True) # bússola, giroscópio, 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()
# O HAT fica acima da CPU, então seus sensores leem valores altos. Esta
# heurística simples subtrai parte da diferença; ajuste CPU_FACTOR ao seu 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()
# Consulte a orientação com frequência para manter a fusão de sensores 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()
Execute com python sensehat_mqtt.py. O loop principal consulta a orientação a cada 50 ms porque a fusão de sensores do Sense HAT precisa de leituras frequentes para manter pitch, roll e yaw estáveis, mas publica apenas uma vez por segundo.
Enviando mensagens para a matriz de LED
Em qualquer máquina, primeiro assine os dados:
mosquitto_sub -h broker.connectmq.com -p 1883 -i viewer-5d82be \
-t 'connectmq/demo/5d82be/sensehat/#' -v
Depois envie texto simples ou uma mensagem JSON com uma cor:
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]}'
A mensagem rola em branco ou laranja enquanto temperatura e orientação continuam sendo transmitidas. Incline o Pi e veja pitch e roll mudarem na janela do assinante; pressione o joystick para ver os eventos chegarem. O topic de exibição propositalmente não é retained; caso contrário, a última mensagem seria reexibida toda vez que o Pi reconectasse.
Obtendo leituras de temperatura confiáveis
O Sense HAT fica logo acima do processador, então seus sensores de temperatura leem vários graus a mais, ainda mais em um Pi 4 ou Pi 5 sob carga. O script publica tanto o valor bruto quanto uma estimativa corrigida. Para calibrar a correção:
- Coloque um termômetro confiável ao lado do Pi e deixe ambos estabilizarem por 20 minutos.
- Compare a referência com
temperature_rawecpu_tempdas mensagens MQTT. - Ajuste
CPU_FACTORaté quetemperaturecoincida com a referência. - Para mais precisão, conecte o HAT por um cabo flat extensor de 40 pinos para que ele fique longe da CPU.
Se você precisa da temperatura ambiente precisa, e não apenas de uma demonstração, uma sonda dedicada é a ferramenta certa. Nossos guias sobre o Raspberry Pi com DHT22 e MQTT e a sonda 1-Wire DS18B20 mostram como publicar sensores externos com o mesmo estilo de topics.
Visualizando os dados
Como tudo trafega como JSON compacto via MQTT, qualquer assinante pode usar os dados. O Node-RED pode desenhar um medidor ao vivo, o Telegraf pode gravá-los no InfluxDB e o Grafana pode exibir meses de histórico; o guia Raspberry Pi com Grafana e InfluxDB monta essa stack. Para uma olhada rápida sem instalar nada, o cliente MQTT no navegador e o explorador de topics ao vivo do portal ConnectMQ mostram cada mensagem env e imu assim que chega.
Da demonstração ao broker privado
O servidor MQTT público pode ser lido por qualquer pessoa, o que serve para uma saudação rolando na tela, mas não para um sensor na sua casa ou sala de aula: use-o apenas para testes e protótipos. O ConnectMQ oferece um broker privado com credenciais geradas e TLS. Defina algumas variáveis de ambiente e o script se conecta com segurança:
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 manter o script rodando após uma reinicialização, coloque-o em um serviço systemd, como mostrado no tutorial de MQTT com Raspberry Pi.
Ideias para expandir o projeto
Depois que o loop básico funcionar, o Sense HAT vira uma bancada de testes prática para padrões MQTT que você vai reutilizar em dispositivos reais:
- Alarme de inclinação: faça um segundo script assinar o topic
imue publicar um aviso quando pitch ou roll ultrapassarem um limite, uma simulação simples do monitoramento de uma máquina que não deveria se mover. - Painel de status remoto: publique no topic
displaymensagens curtas de status vindas de um pipeline de CI, de um fluxo de automação residencial ou de uma verificação de saúde de servidor e use a matriz como notificador de mesa. - Joystick como controle remoto: assine o topic
joystickno Node-RED e associe cada direção a uma cena, um relé ou uma página de dashboard. - Alertas por limite sem código: em um broker ConnectMQ privado, configure no portal uma regra de alerta sobre o valor de umidade do topic
enve consulte os alertas disparados no log de alertas. - Várias salas de aula: dê a cada Pi seu próprio nível de prefixo, como
school/room12/sensehat, e assine com o curinga+para comparar as salas lado a lado.
Cada ideia exige apenas um novo assinante ou um novo topic. O script do Pi continua o mesmo, e é exatamente esse desacoplamento que torna o MQTT tão agradável de usar.
Solução de problemas
OSError: Cannot detect RPi-Sense FB device: o HAT não foi detectado; encaixe-o novamente com o Pi desligado.- O yaw deriva ou salta: calibre o magnetômetro e mantenha o Pi longe de motores e alto-falantes; a orientação também precisa de consultas frequentes.
- As mensagens rolam, mas os dados dos sensores param: algo está bloqueando o loop principal; nunca chame
show_message()a partir de um callback. - A umidade marca 0: o sensor de umidade precisa de um momento após a inicialização; descarte a primeira leitura.
Comece a usar o ConnectMQ
Leve seu Sense HAT do sandbox público para um broker privado em poucos minutos. Crie um broker Serverless gratuito, sem cartão de crédito, e conecte-se via TLS com as credenciais geradas. Você ganha um broker MQTT gerenciado com suporte a MQTT 3.1.1 e 5.0, além de um portal onde pode enviar mensagens para a matriz e acompanhar cada leitura ao vivo.
Perguntas frequentes
Por que a temperatura do Sense HAT é mais alta que a do ambiente?
O calor do processador do Raspberry Pi aquece o HAT. Use a correção baseada na CPU deste tutorial, um cabo flat extensor ou um sensor externo para leituras precisas.
Posso publicar dados do Sense HAT com frequência maior que uma vez por segundo?
Sim, mas respeite os limites de taxa do seu broker; o broker público de testes permite 10 mensagens por segundo por cliente. Para dados de movimento em alta frequência, agrupe várias amostras em uma única mensagem JSON.
O Sense HAT funciona no Raspberry Pi 5?
Sim, ele usa o conector padrão de 40 pinos e o pacote sense-hat do Raspberry Pi OS. Espere diferenças de temperatura maiores, porque o Pi 5 trabalha mais quente.
Como envio texto colorido para a matriz de LED?
Publique um JSON como {"text":"Hi","colour":[0,255,0]} no topic de exibição. O script lê a cor como uma lista RGB e usa branco como padrão para texto simples.



