Raspberry Pi

Raspberry Pi Sense HAT com MQTT: publique dados ambientais e da IMU e exiba mensagens na matriz de LED

Transforme um Raspberry Pi Sense HAT em um dispositivo MQTT bidirecional: publique leituras ambientais e de orientação em JSON e role na matriz de LED 8x8 mensagens enviadas por qualquer cliente MQTT.

Raspberry Pi com Sense HAT rolando uma mensagem na matriz de LED enquanto envia dados de sensores para a nuvem em um projeto raspberry pi sense hat mqtt
Rode isso no seu próprio broker MQTTTenha um broker MQTT privado e gerenciado no plano Free e comece com exemplos de código prontos.
Teste grátis Exemplos de código Sem cartão de crédito

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:

  1. Coloque um termômetro confiável ao lado do Pi e deixe ambos estabilizarem por 20 minutos.
  2. Compare a referência com temperature_raw e cpu_temp das mensagens MQTT.
  3. Ajuste CPU_FACTOR até que temperature coincida com a referência.
  4. 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:

  1. Alarme de inclinação: faça um segundo script assinar o topic imu e 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.
  2. Painel de status remoto: publique no topic display mensagens 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.
  3. Joystick como controle remoto: assine o topic joystick no Node-RED e associe cada direção a uma cena, um relé ou uma página de dashboard.
  4. 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 env e consulte os alertas disparados no log de alertas.
  5. 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.

Artigos relacionados

Registro de Acessos Raspberry Pi RFID MQTT com o Leitor RC522

Ligue um leitor RFID RC522 a um Raspberry Pi, leia tags em Python, confira-as em uma lista de permissões local e publique cada tentativa de acesso como um evento MQTT que loggers, dashboards e ferramentas de alerta podem consumir.

8 min de leitura

Confiabilidade do Raspberry Pi: Rodando um Pi 24/7 como Gateway IoT

Um guia prático para manter um gateway MQTT com Raspberry Pi rodando por meses: desgaste do armazenamento, sistemas de arquivos somente leitura, alimentação, refrigeração, watchdogs de hardware e software e monitoramento remoto de saúde.

9 min de leitura

Pico W vs Pico 2 W para MQTT: Desempenho, Memória e TLS do RP2040 vs RP2350

O Pico 2 W mantém o formato e o chip Wi-Fi do Pico W, mas troca o RP2040 pelo RP2350, mais rápido. Esta comparação mostra o que isso significa para dispositivos MQTT: CPU, memória, TLS, recursos de segurança, suporte de software e qual placa comprar para cada projeto.

9 min de leitura

Todos os artigos →

Seu broker MQTT privado está a poucos cliques de distância

Crie uma conta, receba as credenciais do seu broker e conecte seu primeiro dispositivo — sem servidores para instalar, atualizar ou escalar.