Raspberry Pi

Controle de Relé no Raspberry Pi via MQTT: Acione uma Placa Multicanal de Qualquer Lugar

Ligue uma placa de relés de 4 canais a um Raspberry Pi, controle cada canal por topics MQTT com Python e gpiozero e use retained messages para que cada relé volte ao estado certo depois de um reboot ou de uma queda de energia.

Raspberry Pi ligado a uma placa de relés de quatro canais com LEDs indicadores, controlada por mensagens MQTT na nuvem em um projeto de relé raspberry pi 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 controlador de relé Raspberry Pi MQTT permite acionar lâmpadas, bombas, ventiladores ou contatores a partir de um celular, de um dashboard ou de um script de automação, sem abrir portas no seu roteador. Neste tutorial você vai ligar uma placa de relés multicanal, escrever um serviço Python que associa topics MQTT a canais de relé e usar retained messages para que cada relé volte ao estado correto depois de um reboot.

O que você precisa

Item Observações
Raspberry Pi (3B+, 4, 5 ou Zero 2 W) Raspberry Pi OS Bookworm, conectado à rede
Placa de relés de 2, 4 ou 8 canais Bobina de 5 V com optoacopladores, entradas compatíveis com 3,3 V
Jumpers fêmea-fêmea Um por canal, mais alimentação e terra
Python 3 com gpiozero e paho-mqtt 2.x Instalados em um ambiente virtual
Um broker MQTT broker.connectmq.com para testes, credenciais privadas para produção

Uma observação de segurança antes de tudo: placas de relés acionam o que quer que você ligue a elas. Se você controlar tensão de rede, a fiação precisa ser feita dentro de um quadro adequado, por um profissional qualificado, com o relé dimensionado para a carga. Para aprender, acione uma fita de LED de 12 V ou um pequeno ventilador CC.

Ligando a placa de relés

A maioria dos módulos de relé para hobby tem um conector identificado como VCC, GND e IN1 a IN4. Ligue assim:

Pino do relé Pino do Raspberry Pi
VCC 5 V (pino físico 2)
GND GND (pino físico 6)
IN1 GPIO17 (pino físico 11)
IN2 GPIO27 (pino físico 13)
IN3 GPIO22 (pino físico 15)
IN4 GPIO23 (pino físico 16)

Muitas dessas placas são ativas em nível baixo: levar uma entrada ao terra energiza a bobina. É por isso que o código abaixo usa active_high=False. Se a sua placa liga quando você espera que desligue, inverta essa flag.

Placas com um jumper JD-VCC permitem alimentar as bobinas com uma fonte de 5 V separada, para isolamento total. Remova o jumper, alimente o JD-VCC pela fonte externa, mantenha o VCC nos 3,3 V ou 5 V do Pi conforme a documentação da placa e compartilhe o terra apenas se o manual exigir.

Mais um detalhe de hardware importa para a confiabilidade. Antes de o seu script iniciar, os pinos GPIO são entradas com resistores de pull padrão, então uma placa ativa em nível baixo pode acionar por um instante no boot. Teste o que os seus relés fazem durante um ciclo de energia. Se um acionamento indevido puder causar dano, escolha pinos cujo pull padrão corresponda ao nível "desligado" ou adicione resistores de pull externos.

Definindo o contrato de topics

Uma estrutura de topics limpa torna o controlador de relés fácil de usar a partir de qualquer cliente, seja o Node-RED, o Home Assistant ou um script:

Topic Direção Payload Retained
connectmq/demo/a91c4e/relays/<n>/set Controlador para o Pi ON, OFF (ou TOGGLE, não retained) Sim para ON/OFF
connectmq/demo/a91c4e/relays/<n>/state Pi para todos ON ou OFF Sim
connectmq/demo/a91c4e/relays/status Pi (e last will) online ou offline Sim

Substitua a91c4e por uma string aleatória sua. Em um broker público compartilhado, todos os topics podem ser lidos por todos, então um prefixo único mantém o seu tráfego de teste separado. Se quiser relembrar por que topics set e state separados são uma boa prática, o guia GPIO do Raspberry Pi via MQTT explica em detalhes o padrão de comando e estado.

Como os estados retained sobrevivem a um reboot

As retained messages são a chave para um controlador de relés que se comporta bem depois de uma queda de energia. O broker guarda a última mensagem retained de cada topic e a entrega imediatamente a qualquer novo assinante. Isso traz dois comportamentos úteis:

  1. Quando o seu dashboard publica ON em relays/1/set com a flag retain, o broker a guarda. Depois que o Pi reinicia e assina relays/+/set, ele recebe o estado desejado de cada canal e o restaura.
  2. Quando o Pi publica relays/1/state com retain, qualquer dashboard aberto mais tarde vê o estado real na hora, em vez de esperar pela próxima mudança.

Há uma armadilha: nunca use retain com TOGGLE. Um toggle retained seria reproduzido a cada reconexão e inverteria o relé toda vez. Por isso, o script abaixo ignora toggles retained. Para entender melhor o mecanismo, leia nosso artigo sobre retained messages no MQTT.

Script Raspberry Pi relé MQTT em Python

Crie uma pasta de projeto e um ambiente virtual:

sudo apt update
sudo apt install -y python3-venv python3-lgpio
mkdir -p ~/relay-mqtt && cd ~/relay-mqtt
python3 -m venv --system-site-packages .venv
source .venv/bin/activate
pip install "paho-mqtt>=2.0" gpiozero

A flag --system-site-packages permite que o ambiente virtual use o backend lgpio, de que o gpiozero precisa no Raspberry Pi 5 e que também funciona nos modelos mais antigos. Salve o seguinte como relay_mqtt.py:

#!/usr/bin/env python3
"""Control a multi-channel relay board from MQTT topics."""
import os
import signal
import sys
import uuid

import paho.mqtt.client as mqtt
from gpiozero import OutputDevice

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"rpi-relay-{uuid.uuid4().hex[:8]}")
PREFIX = os.getenv("MQTT_PREFIX", "connectmq/demo/a91c4e/relays")

RELAY_PINS = {1: 17, 2: 27, 3: 22, 4: 23}
ACTIVE_HIGH = False  # a maioria das placas optoacopladas para hobby é ativa em nível baixo

relays = {
    n: OutputDevice(pin, active_high=ACTIVE_HIGH, initial_value=False)
    for n, pin in RELAY_PINS.items()
}


def publish_state(client, n):
    state = "ON" if relays[n].value else "OFF"
    client.publish(f"{PREFIX}/{n}/state", state, qos=1, retain=True)


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}/+/set", qos=1)
    for n in relays:
        publish_state(client, n)


def on_message(client, userdata, msg):
    try:
        n = int(msg.topic.split("/")[-2])
    except ValueError:
        return
    if n not in relays:
        print(f"Ignoring unknown channel {n}")
        return

    command = msg.payload.decode(errors="ignore").strip().upper()
    if command in ("ON", "1", "TRUE"):
        relays[n].on()
    elif command in ("OFF", "0", "FALSE"):
        relays[n].off()
    elif command == "TOGGLE":
        if msg.retain:
            print(f"Ignoring retained TOGGLE on channel {n}")
            return
        relays[n].toggle()
    else:
        print(f"Unknown command {command!r} for channel {n}")
        return
    print(f"Relay {n} -> {'ON' if relays[n].value else 'OFF'}")
    publish_state(client, n)


def on_disconnect(client, userdata, flags, reason_code, properties):
    print(f"Disconnected: {reason_code}; paho will reconnect")


client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=CLIENT_ID)
client.on_connect = on_connect
client.on_message = on_message
client.on_disconnect = on_disconnect
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()


def shutdown(signum, frame):
    for relay in relays.values():
        relay.off()
    client.publish(f"{PREFIX}/status", "offline", qos=1, retain=True)
    client.disconnect()
    sys.exit(0)


signal.signal(signal.SIGTERM, shutdown)
signal.signal(signal.SIGINT, shutdown)

client.connect(BROKER, PORT, keepalive=30)
client.loop_forever(retry_first_connection=True)

Rode com python relay_mqtt.py. O script desliga todos os relés em um encerramento limpo; se você preferir manter as cargas ligadas quando o serviço parar, remova o loop em shutdown.

Testando a partir do seu notebook

Abra um segundo terminal em qualquer máquina com os clientes Mosquitto instalados e acompanhe os topics de estado:

mosquitto_sub -h broker.connectmq.com -p 1883 -i laptop-a91c4e \
  -t 'connectmq/demo/a91c4e/relays/#' -v

Depois ligue o canal 1 com um comando retained e alterne o canal 2:

mosquitto_pub -h broker.connectmq.com -p 1883 -i cmd-a91c4e \
  -t 'connectmq/demo/a91c4e/relays/1/set' -m 'ON' -q 1 -r

mosquitto_pub -h broker.connectmq.com -p 1883 -i cmd-a91c4e \
  -t 'connectmq/demo/a91c4e/relays/2/set' -m 'TOGGLE' -q 1

Você deve ouvir os cliques e ver relays/1/state ON aparecer. Agora reinicie o Pi. Quando o script se reconectar, o canal 1 volta a ON porque o comando retained continua no broker, enquanto o canal 2 começa em OFF porque toggles nunca são retained. Para limpar um comando retained, publique uma mensagem retained vazia: mosquitto_pub ... -t '.../relays/1/set' -r -n.

Rode como serviço

Um controlador de relés precisa iniciar no boot e reiniciar depois de uma falha. Crie /etc/systemd/system/relay-mqtt.service:

[Unit]
Description=Relay MQTT controller
After=network-online.target
Wants=network-online.target

[Service]
User=pi
WorkingDirectory=/home/pi/relay-mqtt
Environment=MQTT_HOST=broker.connectmq.com
Environment=MQTT_PORT=8883
Environment=MQTT_USERNAME=YOUR_USERNAME
Environment=MQTT_PASSWORD=YOUR_PASSWORD
Environment=MQTT_CLIENT_ID=YOUR_CLIENT_ID
Environment=MQTT_PREFIX=home/garage/relays
ExecStart=/home/pi/relay-mqtt/.venv/bin/python relay_mqtt.py
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Ative com sudo systemctl daemon-reload && sudo systemctl enable --now relay-mqtt. A explicação completa sobre arquivos de serviço, logs e arquivos de ambiente está em como rodar um script Python MQTT na inicialização. Ajuste o nome de usuário se o seu não for pi.

Do servidor de testes para a produção

O servidor MQTT público é perfeito para a primeira hora, mas qualquer pessoa que adivinhe o seu topic poderia acionar os seus relés. Para qualquer coisa ligada a equipamentos reais, use um broker privado com autenticação e TLS. Com um broker MQTT gerenciado como o ConnectMQ, você cria um broker no portal, copia o usuário, a senha e o client ID gerados para o arquivo de serviço acima e define a porta como 8883. O client ID fica vinculado às credenciais emitidas, então outro dispositivo não consegue se passar pelo seu controlador. O script não muda em nada.

O portal ConnectMQ também ajuda durante o comissionamento: o cliente MQTT no navegador pode publicar ON e OFF em cada canal, e o explorador de topics ao vivo mostra os valores retained de estado e status em um relance. Se você quiser uma alternativa de hardware ao Pi para a mesma tarefa, compare com o projeto relé com ESP32 via MQTT.

Solução de problemas

  1. Os relés ligam no início e desligam quando você manda ligar: a sua placa é ativa em nível alto; defina ACTIVE_HIGH = True.
  2. Os LEDs da placa acendem, mas o relé não estala: a alimentação das bobinas está fraca; alimente o JD-VCC com uma fonte de 5 V separada.
  3. Connection refused: Not authorized: confira usuário, senha e client ID, ou remova-os ao usar o broker público anônimo.
  4. O relé restaura um estado antigo após o reboot: há um comando retained antigo no broker; limpe-o com uma publicação retained vazia.
  5. Erros GPIO busy: outro script ou serviço está usando os mesmos pinos; pare-o antes de iniciar este.

Comece com o ConnectMQ

Pronto para controlar equipamentos reais? Cadastre-se no plano Serverless gratuito, sem cartão de crédito, crie um broker e aponte o seu serviço de relés para ele via TLS. Você tem MQTT 3.1.1 e 5.0, retained messages e um portal para acompanhar cada acionamento. Novo nos conceitos? O tutorial MQTT com Raspberry Pi cobre os fundamentos, e nossa visão geral de um broker MQTT na nuvem explica quando a hospedagem vale mais do que rodar o Mosquitto no Pi.

Perguntas frequentes

Por que meu relé muda de estado depois que o Raspberry Pi reinicia?

Ele está reproduzindo um comando retained do broker, o que normalmente é o que você quer. Se o estado estiver errado, publique o valor correto com retain ou limpe o topic com uma mensagem retained vazia.

Posso usar QoS 1 para os comandos do relé?

Sim, e deve. O QoS 1 garante que o comando chegue pelo menos uma vez e, como ON e OFF são idempotentes, uma entrega duplicada não causa dano.

Quantos relés um Raspberry Pi consegue controlar?

Tantos quantos pinos GPIO livres você tiver, normalmente até oito em uma placa para hobby. Para mais canais, use um expansor de GPIO I2C como o MCP23017 e mantenha a mesma estrutura de topics.

É seguro controlar equipamentos da rede elétrica dessa forma?

Somente com relés dimensionados para a carga, um quadro adequado e fiação feita conforme as normas elétricas locais. Sempre use conexões TLS autenticadas para qualquer coisa que acione equipamentos reais.

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.