O monitoramento de status de máquinas responde à pergunta mais básica do chão de fábrica, "ela está rodando agora?", para todas as máquinas de uma vez. Neste tutorial você vai definir um modelo de estados simples, derivar operando, ociosa e parada a partir de sinais da torre de sinalização ou do CLP em um Raspberry Pi e publicar o estado como retained messages MQTT, para que qualquer dashboard mostre o status atual no instante em que se conecta.
Por que começar pelo status da máquina
O estado da máquina é a base de quase todo KPI de produção. A disponibilidade no OEE, a análise de paradas, as estatísticas de tempo de ciclo e a energia por hora ociosa dependem de saber quando uma máquina estava operando e quando não estava. Também é o dado mais barato de obter: muitas máquinas já mostram seu estado em uma torre de sinalização, e quase todo CLP tem um bit de "ciclo ativo" e um de "falha".
A dificuldade não está no sinal, mas na consistência. Se uma máquina informa "auto", outra "RUN" e uma terceira apenas uma lâmpada verde, compará-las é penoso. É por isso que o modelo de estados vem primeiro.
Um modelo de estados prático
Mantenha o número de estados pequeno e as definições sem ambiguidade. Este modelo de cinco estados cobre a maior parte da manufatura discreta:
| Estado | Definição | Sinal típico |
|---|---|---|
| running | A máquina está produzindo; um ciclo terminou dentro do tempo esperado | Pulso de ciclo, luz verde, "em ciclo" no CLP |
| idle | A máquina está saudável e disponível, mas não produz (aguardando material, operador, processo anterior) | Sem falha, sem ciclo recente |
| down | A máquina não consegue produzir por causa de uma falha ou alarme | Luz vermelha, bit de falha do CLP |
| setup | Troca planejada, troca de ferramenta ou manutenção | Apontamento do operador, modo do CLP, estado da ordem no MES |
| offline | Nenhum dado do dispositivo de borda | Last Will do MQTT |
Duas regras fazem o modelo funcionar:
- Prioridade: se várias condições forem verdadeiras, vence a de maior prioridade. Uma ordem sensata é offline, down, setup, running, idle.
- Debounce com tempo: uma máquina que completa um ciclo a cada 40 segundos não deve piscar para ociosa entre os ciclos. Considere-a operando até que nenhum ciclo seja visto por, digamos, o dobro do tempo de ciclo nominal.
Os motivos de parada e de ociosidade (falta de material, quebra de ferramenta, bloqueio da qualidade) são outra dimensão. Registre-os depois em um campo reason, em vez de multiplicar os estados.
Projeto de topics com retained messages
Cada máquina recebe um topic state que guarda seu estado atual como mensagem retida. O broker armazena a última retained message por topic e a envia imediatamente a cada novo assinante. Um dashboard aberto às 10h15 não precisa esperar a próxima mudança; ele vê "parada desde 09h52" na hora. Leia retained messages no MQTT para conhecer o mecanismo completo.
connectmq/plant1/machining/line1/cnc-01/state retained current state
connectmq/plant1/machining/line1/cnc-01/events not retained, one message per transition
connectmq/plant1/machining/line1/cnc-01/status retained online / offline (Last Will)
Payload de estado:
{
"state": "down",
"since": 1760599920,
"previous": "running",
"reason": null,
"source": "edge-cnc-01"
}
Incluir since permite que um dashboard mostre a duração sem nenhum banco de histórico. O topic events é o que um historiador assina para relatórios de paradas e disponibilidade.
Ligando os sinais
Em máquinas sem acesso de rede ao CLP, capte a torre de sinalização ou saídas livres do CLP por meio de módulos de entrada com optoacoplador de 24 V ligados ao GPIO do Raspberry Pi. Nunca conecte sinais de 24 V diretamente ao Pi; os pinos GPIO dele suportam apenas 3,3 V. Trabalhos elétricos em painéis de máquinas devem ser feitos por pessoal qualificado.
| Sinal | GPIO (BCM) | Significado quando ativo |
|---|---|---|
| Pulso de ciclo completo ou luz verde | 17 | Um ciclo terminou / máquina em ciclo |
| Luz vermelha ou saída de falha | 27 | Máquina em falha |
| Chave de setup ou luz amarela | 22 | Setup ou troca planejada |
Onde o CLP é acessível pela rede, leia os mesmos bits via Modbus TCP, OPC UA ou S7; só a função de entrada muda.
O script de borda de monitoramento de status de máquinas
Instale as bibliotecas em um ambiente virtual (pip install gpiozero lgpio paho-mqtt). O script abaixo avalia as entradas duas vezes por segundo, aplica as regras de prioridade e de tempo e publica apenas nas transições.
#!/usr/bin/env python3
"""Machine status monitoring edge script: GPIO signals -> retained MQTT state."""
import json
import time
import paho.mqtt.client as mqtt
from gpiozero import DigitalInputDevice
BROKER = "broker.connectmq.com"
MACHINE = "cnc-01"
BASE = f"connectmq/demo/msm-5t2r/line1/{MACHINE}"
NOMINAL_CYCLE_S = 40
RUN_TIMEOUT_S = 2 * NOMINAL_CYCLE_S
cycle_in = DigitalInputDevice(17, pull_up=True, bounce_time=0.02)
fault_in = DigitalInputDevice(27, pull_up=True, bounce_time=0.05)
setup_in = DigitalInputDevice(22, pull_up=True, bounce_time=0.05)
last_cycle = 0.0
state, since = None, 0
def on_cycle():
global last_cycle
last_cycle = time.time()
cycle_in.when_activated = on_cycle
def derive_state(now):
if fault_in.is_active:
return "down"
if setup_in.is_active:
return "setup"
if cycle_in.is_active or now - last_cycle < RUN_TIMEOUT_S:
return "running"
return "idle"
def on_connect(client, userdata, flags, reason_code, properties):
print("Connected:", reason_code)
client.publish(f"{BASE}/status", "online", qos=1, retain=True)
if state is not None: # restaura após reconectar
publish_state(client, state, state, since, event=False)
def publish_state(client, new, previous, ts, event=True):
payload = {"state": new, "since": ts, "previous": previous,
"reason": None, "source": f"edge-{MACHINE}"}
client.publish(f"{BASE}/state", json.dumps(payload), qos=1, retain=True)
if event:
client.publish(f"{BASE}/events", json.dumps(payload), qos=1)
print(payload)
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id=f"msm-5t2r-{MACHINE}")
client.will_set(f"{BASE}/status", "offline", qos=1, retain=True)
client.on_connect = on_connect
client.connect(BROKER, 1883, keepalive=30)
client.loop_start()
while True:
now = time.time()
new = derive_state(now)
if new != state:
previous, state, since = state, new, int(now)
publish_state(client, state, previous, since)
time.sleep(0.5)
Algumas escolhas de projeto que vale destacar:
- O Last Will em
statustransforma um script travado, uma rede perdida ou uma queda de energia em um estado "offline" visível, em vez de um "running" congelado. - Ao reconectar, o script republica o estado retido, para que o broker sempre guarde a verdade mais recente, mesmo que uma transição tenha ocorrido enquanto a conexão estava caída.
- As entradas usam
pull_up=Trueporque os módulos com optoacoplador típicos puxam a linha para nível baixo quando ativos. Inverta se o seu módulo se comportar de outra forma.
Rode o script como serviço systemd para que ele inicie no boot. Para um broker de produção, adicione client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD") e client.tls_set(), use o client ID emitido para você e conecte-se à porta 8883.
Visualizando o painel de status
Qualquer cliente MQTT agora consegue mostrar o status ao vivo. Em um terminal:
mosquitto_sub -h broker.connectmq.com -p 1883 -i msm-board-$RANDOM \
-t "connectmq/demo/msm-5t2r/line1/+/state" -v
Os estados retidos aparecem imediatamente, uma linha por máquina. Em um dashboard no navegador, o MQTT.js se conecta via WebSocket seguro e faz o mesmo:
import mqtt from "mqtt";
const client = mqtt.connect("wss://broker.connectmq.com:8084/mqtt", {
clientId: "msm-board-" + Math.random().toString(16).slice(2, 8),
protocolVersion: 5,
});
const board = {};
client.on("connect", () => client.subscribe("connectmq/demo/msm-5t2r/line1/+/state"));
client.on("message", (topic, payload) => {
const machine = topic.split("/").at(-2);
board[machine] = JSON.parse(payload.toString());
const lines = Object.entries(board).map(([m, s]) => {
const minutes = Math.round((Date.now() / 1000 - s.since) / 60);
return `${m}: ${s.state} for ${minutes} min`;
});
console.clear();
console.log(lines.join("\n"));
});
Lembre-se de que os topics no servidor MQTT público ficam visíveis para todos; nomes e estados de máquinas de uma planta real devem ficar em um broker privado.
Do status às métricas
Quando o fluxo events existe, o restante do monitoramento da linha se apoia nele:
- Disponibilidade: tempo operando dividido pelo tempo planejado de produção, a partir do histórico de eventos.
- Registro de paradas: cada transição de operando para parada abre um registro de parada; os operadores adicionam os motivos em um tablet.
- Tempo de ciclo: a mesma entrada de ciclo, com timestamp, gera a duração ciclo a ciclo, tema do monitoramento do tempo de ciclo.
- Contagem de peças: um contador no mesmo pulso alimenta a contagem de produção com sensores IoT.
- Escalonamento: uma máquina parada por mais tempo que um limite dispara um chamado em um sistema de andon digital.
Com o tempo, esse fluxo de estados também é a base natural para um gêmeo digital da linha.
Solução de problemas
| Sintoma | Causa | Correção |
|---|---|---|
| O estado alterna entre operando e ociosa | Tempo limite de operação menor que a variação real do ciclo | Aumente RUN_TIMEOUT_S |
| O dashboard mostra "running" desatualizado após uma queda de energia | Sem Last Will, ou o dashboard ignora status |
Use Last Will e mostre offline com prioridade |
| Máquinas antigas continuam aparecendo no painel | Retained messages permanecem após a desativação | Publique uma retained message vazia para limpar o topic |
| Entrada de falha sempre ativa | Lógica invertida do módulo com optoacoplador | Altere pull_up ou use active_state |
Rodando em escala
Dezenas de máquinas, cada uma com um estado retido e um cliente de borda que precisa reconectar com confiabilidade, é exatamente a carga de trabalho para a qual um broker MQTT gerenciado foi feito. A ConnectMQ também expõe o estado de conexão por cliente em $SYS/broker/connection/{clientId}/state, o que ajuda a identificar dispositivos de borda que caem com frequência. O guia de manufatura inteligente mostra como o estado da máquina se encaixa em um roteiro completo de monitoramento.
Comece com a ConnectMQ
A ConnectMQ oferece um broker MQTT 5 protegido por TLS, com retained messages, explorador de topics ao vivo e visão de dispositivos ISA-95 que agrupa as máquinas por área e linha. Crie um broker Serverless gratuito, sem cartão de crédito, e leve seu monitoramento de status de máquinas do servidor de testes para a produção.
Perguntas frequentes
Por que usar retained messages para o status da máquina?
Uma retained message é entregue imediatamente a cada novo assinante, então dashboards, tablets e serviços sempre começam com o estado atual de cada máquina, em vez de esperar a próxima mudança.
Como detectar que o dispositivo de borda de uma máquina está offline?
Defina uma mensagem Last Will em um topic de status retido quando o cliente se conectar. Se o dispositivo se desconectar inesperadamente, o broker publica o Will, e os dashboards podem exibir a máquina como offline.
Posso obter o estado da máquina direto do CLP em vez da torre de sinalização?
Sim. Leia os bits de ciclo e de falha do CLP via Modbus TCP, OPC UA ou um protocolo do fabricante e alimente a mesma lógica de estados. Os sinais do CLP costumam ser mais precisos que a torre de sinalização.
Quantos estados um modelo de status de máquina deve ter?
O mínimo possível que ainda responda às suas perguntas. Operando, ociosa, parada, setup e offline cobrem a maioria das necessidades; use códigos de motivo para os detalhes, em vez de acrescentar estados.



