Manufatura inteligente

Contagem de Produção com IoT: Sensores, Contadores na Borda e Totais de Turno via MQTT

Conte peças boas e rejeitadas automaticamente com sensores fotoelétricos e um Raspberry Pi, preserve as contagens entre reinícios e publique totais de turno retidos via MQTT para que todas as telas mostrem o número certo.

Montagem de contagem de produção com IoT com um sensor fotoelétrico em uma esteira, um contador de borda Raspberry Pi e um painel de total do turno atualizado via 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

A contagem de produção com sensores IoT substitui planilhas de apontamento e estimativas de fim de turno por contagens de peças exatas e ao vivo. Neste tutorial você vai contar peças boas e rejeitadas com sensores fotoelétricos e um Raspberry Pi, fazer o contador sobreviver a reinícios e quedas de rede e publicar totais de turno retidos via MQTT, para que todo painel, tablet e relatório mostre o mesmo número.

Por que a contagem automática importa

Contagens escritas à mão chegam atrasadas, arredondadas e às vezes otimistas. Elas aparecem depois do turno, quando já não há o que fazer com um déficit. Um contador automático mostra a diferença para a meta enquanto ainda há tempo de reagir e fornece as entradas de qualidade e desempenho de que o OEE precisa. Também é um dos projetos IoT mais simples do chão de fábrica: um sensor, um dispositivo de borda, um topic.

Escolhendo o ponto de contagem

Ponto de contagem Prós Contras
Contador de peças do CLP ou bit de "peça concluída" Exato, já com debounce Exige acesso e alterações no CLP
Sensor fotoelétrico na saída da estação Retrofit sem mexer no CLP; funciona na maioria das peças Precisa lidar com espaçamentos, peças encostadas, superfícies reflexivas
Sensor indutivo Robusto para peças metálicas, ignora sujeira Alcance curto, apenas metal
Sensor na calha de rejeito ou caçamba de refugo Fornece a contagem de refugo para a taxa de qualidade Exige um segundo sensor
Estação de embalagem (caixas, depois multiplicar) Conta o que é realmente expedido Atrasado, esconde refugo entre a estação e a embalagem

Conte o mais perto possível do ponto em que a peça se torna "boa". Se a linha tiver uma estação de inspeção, conte as peças aprovadas depois dela e as rejeitadas no caminho de rejeito. A contagem de boas somada à de refugo dá a produção total.

Entre os sensores fotoelétricos, os do tipo barreira são os mais confiáveis em esteiras, porque peças encostadas ou brilhantes podem confundir sensores difusos. Monte o sensor de modo que cada peça interrompa o feixe exatamente uma vez, com um espaço entre as peças.

Ligações

Sensores industriais operam em 24 V e chaveiam saídas PNP ou NPN. Ligue-os ao Raspberry Pi por uma placa de entradas com optoacopladores; os pinos GPIO do Pi toleram apenas 3,3 V. Exemplo de atribuição:

Entrada GPIO (BCM) Sinal
Sensor de peça boa 17 Saída do receptor de barreira
Sensor de rejeito 27 Sensor da calha de rejeito
Reset de turno (opcional) 22 Chave com trava ou botão do supervisor

Design de topics para contagens e totais de turno

connectmq/plant1/packaging/line2/counter/count      every N seconds, not retained
connectmq/plant1/packaging/line2/counter/shift      retained shift totals
connectmq/plant1/packaging/line2/counter/status     retained online / offline

A mensagem shift é retida, então um dashboard aberto no meio do turno mostra imediatamente os totais atuais. Seu payload contém totais absolutos, não incrementos:

{
  "shift": "2026-10-16-A",
  "start": 1760594400,
  "good": 1843,
  "reject": 27,
  "target": 2400,
  "ts": 1760600000
}

Publicar totais absolutos é a decisão de projeto principal. Se uma mensagem for perdida ou entregue duas vezes, a próxima ainda contém o total correto; incrementos acumulariam erro.

O script de borda para contagem de produção com IoT

O script conta as bordas nas duas entradas, salva os totais em um pequeno arquivo a cada poucos segundos para que um reboot não os perca, detecta trocas de turno a partir de uma escala e publica os totais retidos. Instale as dependências em um ambiente virtual com pip install gpiozero lgpio paho-mqtt.

#!/usr/bin/env python3
"""Production counting IoT edge: sensors -> persistent counts -> retained MQTT totals."""
import json
import os
import threading
import time
from datetime import datetime, timedelta

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

BROKER = "broker.connectmq.com"
BASE = "connectmq/demo/pc-9d1x/line2/counter"
STATE_FILE = "/var/lib/pc-counter/state.json"
PUBLISH_EVERY = 5                      # segundos
SHIFTS = [("A", 6), ("B", 14), ("C", 22)]
TARGET_PER_SHIFT = 2400

lock = threading.Lock()


def current_shift(now=None):
    now = now or datetime.now()
    starts = []
    for name, hour in SHIFTS:
        start = now.replace(hour=hour, minute=0, second=0, microsecond=0)
        if start > now:
            start -= timedelta(days=1)
        starts.append((start, name))
    start, name = max(starts)
    return f"{start:%Y-%m-%d}-{name}", int(start.timestamp())


def load_state():
    shift_id, start = current_shift()
    try:
        with open(STATE_FILE) as f:
            state = json.load(f)
        if state.get("shift") == shift_id:
            return state
    except (FileNotFoundError, ValueError):
        pass
    return {"shift": shift_id, "start": start, "good": 0, "reject": 0}


def save_state(state):
    tmp = STATE_FILE + ".tmp"
    with open(tmp, "w") as f:
        json.dump(state, f)
    os.replace(tmp, STATE_FILE)        # atômico no mesmo sistema de arquivos


state = load_state()


def count(field):
    def handler():
        with lock:
            state[field] += 1
    return handler


good_in = DigitalInputDevice(17, pull_up=True, bounce_time=0.01)
reject_in = DigitalInputDevice(27, pull_up=True, bounce_time=0.01)
good_in.when_activated = count("good")
reject_in.when_activated = count("reject")


def on_connect(client, userdata, flags, reason_code, properties):
    print("Connected:", reason_code)
    client.publish(f"{BASE}/status", "online", qos=1, retain=True)


client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="pc-9d1x-line2")
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()

os.makedirs(os.path.dirname(STATE_FILE), exist_ok=True)

while True:
    time.sleep(PUBLISH_EVERY)
    shift_id, start = current_shift()
    with lock:
        if shift_id != state["shift"]:
            final = dict(state, ts=int(time.time()), final=True)
            client.publish(f"{BASE}/shift-closed", json.dumps(final), qos=1)
            state.update(shift=shift_id, start=start, good=0, reject=0)
        snapshot = dict(state, target=TARGET_PER_SHIFT, ts=int(time.time()))
        save_state(state)
    client.publish(f"{BASE}/shift", json.dumps(snapshot), qos=1, retain=True)
    client.publish(f"{BASE}/count", json.dumps(snapshot), qos=0)

Pontos que merecem destaque:

  • Gravação atômica: escrever em um arquivo temporário e renomeá-lo significa que uma queda de energia durante a gravação não corrompe o arquivo de estado.
  • Troca de turno na borda: o próprio dispositivo fecha o turno e publica um registro final em shift-closed, então o total fica correto mesmo que nenhum servidor esteja ouvindo naquele momento. Um historiador assinado com sessão persistente o recebe depois.
  • Debounce: bounce_time filtra ruído elétrico; peças que passam mais rápido que a janela de debounce seriam subcontadas, então defina-o a partir da sua taxa máxima de peças.

Crie /var/lib/pc-counter com permissões para o usuário do serviço e rode o script sob o systemd.

Acompanhando as contagens

mosquitto_sub -h broker.connectmq.com -p 1883 -i pc-view-$RANDOM \
  -t "connectmq/demo/pc-9d1x/line2/counter/#" -v

O total retido do turno e o status chegam primeiro, depois as atualizações a cada cinco segundos. No servidor MQTT público qualquer pessoa pode ler esses topics, o que não é problema em um teste de bancada passando a mão por uma barreira de luz, mas não serve para uma linha real. Em produção, adicione client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD") e client.tls_set(), use o client ID emitido e conecte na porta 8883.

Validando o contador

Antes que alguém confie nos números, verifique-os:

  1. Rode um lote conhecido (por exemplo 200 peças contadas à mão) e compare.
  2. Teste com peças encostadas umas nas outras e com a maior velocidade de linha realista.
  3. Verifique o comportamento em um reboot no meio de uma produção: a contagem precisa continuar, não recomeçar do zero.
  4. Desconecte a rede por alguns minutos: a contagem continua localmente, e o próximo total publicado inclui as peças feitas enquanto estava offline.
  5. Compare um turno completo com a contagem da embalagem ou do ERP; as diferenças devem ser explicáveis (refugo, retrabalho, WIP).

Problemas comuns

Problema Causa Correção
Contagens duplicadas Bordas ou furos da peça interrompem o feixe duas vezes Aumente o debounce, reposicione o sensor, use barreira
Contagens perdidas Peças encostadas, debounce longo demais Crie espaçamento na esteira, encurte o debounce, use o sinal do CLP
Contagem zerada após queda de energia Estado não persistido Persista em arquivo como mostrado, ou use o contador do CLP
Dashboards mostram o turno de ontem Mensagem retida de um dispositivo parado Monitore o status; mostre "offline" com destaque
Totais diferentes entre telas Telas calculam a partir de incrementos Exiba sempre o total absoluto retido

Exibindo as contagens na linha

A exibição mais eficaz é a mais simples: peças boas até agora, meta até agora (proporcional ao tempo decorrido do turno) e a diferença, em dígitos grandes visíveis do posto de trabalho. Um navegador em uma tela de parede pode assinar via WebSocket seguro o topic retido shift e calcular a meta proporcional a partir de start e target, sem precisar de servidor extra. Pinte a diferença de verde quando estiver adiantado e de vermelho quando estiver atrasado, e mostre a contagem de rejeitos ao lado, para que a velocidade nunca seja celebrada às custas da qualidade.

Durante o comissionamento, o explorador de topics ao vivo no portal ConnectMQ mostra o total retido e o status de cada contador, o que facilita conferir se todas as linhas estão publicando antes de as telas serem instaladas.

Usando as contagens

Contagens ao vivo versus meta são o painel motivacional mais simples em uma linha. Combinadas com o tempo de operação do monitoramento de status de máquinas e com os dados de ciclo do monitoramento de tempo de ciclo, elas alimentam diretamente o monitoramento de OEE em tempo real: contagem de boas sobre contagem total é a taxa de qualidade, e a contagem total contra o tempo de ciclo ideal dá o desempenho. As equipes de energia usam a mesma contagem de peças boas para calcular a energia por peça.

O broker é a fonte única de verdade para todos esses consumidores, e é por isso que vale entender o que um broker MQTT faz antes de escalar para muitas linhas. O guia de manufatura inteligente mostra onde a contagem se encaixa em um roadmap mais amplo, incluindo o gêmeo digital da linha.

Escale seus contadores no ConnectMQ

O ConnectMQ é um broker MQTT gerenciado com TLS, MQTT 5, retained messages, uma visão de dispositivos ISA-95 e alertas por limite, por exemplo quando a contagem good fica atrás do planejado. Crie um broker Serverless gratuito sem cartão de crédito e conecte seu primeiro contador em minutos.

Perguntas frequentes

Um contador de produção deve publicar incrementos ou totais?

Totais. Um total absoluto do turno em uma mensagem retida fica correto mesmo que mensagens sejam perdidas ou duplicadas, e novos subscribers veem o valor atual imediatamente.

O que acontece com as contagens se a rede cair?

O dispositivo de borda continua contando localmente e persiste os totais. Quando a conexão volta, a próxima mensagem publicada contém o total completo, incluindo as peças feitas durante a queda.

Qual é o melhor sensor para projetos de contagem de produção com IoT?

Sensores fotoelétricos do tipo barreira são a escolha geral mais confiável em esteiras. Sensores indutivos servem para peças metálicas, e um sinal de peça concluída do CLP é o melhor quando disponível.

Como contar o refugo separadamente?

Adicione um segundo sensor no caminho de rejeito ou use o sinal de rejeito da estação de inspeção, e publique as contagens de boas e de rejeitadas na mesma mensagem para que a taxa de qualidade seja sempre consistente.

Artigos relacionados

OEE vs TEEP vs OOE: qual indicador você deve usar?

OEE, OOE e TEEP compartilham os mesmos fatores de desempenho e qualidade, mas medem contra bases de tempo diferentes. Esta comparação resolve um único exemplo e lista os sinais MQTT de que cada indicador precisa.

8 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.