IoT industrial

Beckhoff TwinCAT MQTT: Publicando Dados Estruturados do CLP em um Broker

Use as funções IoT do TwinCAT 3 para publicar dados estruturados do CLP em JSON, verificá-los no servidor MQTT público e depois conectar-se a um broker privado com TLS, credenciais e Last Will.

PC industrial Beckhoff rodando TwinCAT 3 e publicando dados da máquina em um broker na nuvem, ilustrando o Beckhoff TwinCAT 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

O suporte a Beckhoff TwinCAT MQTT permite que um PC industrial Beckhoff publique dados da máquina diretamente do runtime do CLP, sem um gateway separado no painel. Neste tutorial você vai usar as funções IoT do TwinCAT 3 para se conectar a um broker MQTT, serializar um tipo de dado estruturado em JSON, publicá-lo na mudança e por temporizador e, por fim, proteger a conexão com TLS e credenciais. O mesmo padrão escala de uma única bancada de testes a uma frota de máquinas.

Opções de MQTT no TwinCAT comparadas

A Beckhoff oferece mais de um caminho para o MQTT, e escolher o certo desde o início evita retrabalho.

Opção O que é Quem configura Ideal para
TF6701 IoT Communication Biblioteca de CLP (Tc3_IotBase) com um bloco de função cliente MQTT Programador de CLP, em texto estruturado Controle total sobre topics, payloads e temporização
TF6720 IoT Data Agent Gateway baseado em configuração que mapeia símbolos ADS para MQTT Interface gráfica do configurador, sem código no CLP Publicar símbolos existentes sem alterar o programa do CLP
Gateway ADS externo Seu próprio serviço que lê símbolos via ADS e publica MQTT Equipe de software Pipelines personalizados, muitos controladores, formatos não padrão

Este tutorial usa o TF6701 porque é a escolha mais comum de fabricantes de máquinas que querem que o comportamento MQTT faça parte do projeto de CLP versionado. Tanto o TF6701 quanto o TF6720 são funções TwinCAT licenciadas; uma licença de teste de 7 dias basta para acompanhar.

Pré-requisitos

  • TwinCAT 3.1 XAE (Visual Studio ou TwinCAT XAE Shell) e um alvo: um IPC Beckhoff ou o seu PC de engenharia em modo run para testes.
  • A função TF6701 instalada no alvo e uma licença de teste ou completa ativada.
  • Acesso de rede de saída do alvo ao broker na porta TCP 1883 para testes e 8883 para TLS.
  • Bibliotecas de CLP Tc3_IotBase e Tc3_JsonXml adicionadas às referências do projeto.
  • Clientes mosquitto em um PC para verificação.

Passo 1: defina um tipo de dado estruturado

Publicar uma estrutura em vez de variáveis soltas mantém os valores relacionados juntos e os timestamps consistentes. Adicione um DUT:

TYPE ST_PressData :
STRUCT
    rForce_kN       : REAL;
    rTemperature_C  : REAL;
    nCycleCount     : UDINT;
    bRunning        : BOOL;
    sState          : STRING(20);
END_STRUCT
END_TYPE

Passo 2: conecte com FB_IotMqttClient

O FB_IotMqttClient da Tc3_IotBase é configurado por propriedades e acionado chamando seu método Execute a cada ciclo. Chame-o a partir de uma task com ciclo de 10 ms ou mais rápido; o cliente cuida da própria comunicação em segundo plano, mas só avança quando Execute é chamado.

PROGRAM MAIN
VAR
    fbMqttClient   : FB_IotMqttClient;
    bSetParameter  : BOOL := TRUE;
    bConnect       : BOOL := TRUE;

    fbJson         : FB_JsonSaxWriter;
    stPress        : ST_PressData;
    stLastPress    : ST_PressData;

    sTopicData     : STRING(255) := 'connectmq/demo/t3w9p1/plant1/stamping/cell4/press1/telemetry';
    sPayload       : STRING(1023);
    fbHeartbeat    : TON;
    bPublish       : BOOL;
END_VAR

// --- Configuração única do cliente ---
IF bSetParameter THEN
    bSetParameter := FALSE;
    fbMqttClient.sHostName  := 'broker.connectmq.com';
    fbMqttClient.nHostPort  := 1883;
    fbMqttClient.sClientId  := 'twincat-demo-t3w9p1';   // não vazio e único
    fbMqttClient.nKeepAlive := 30;
END_IF

// --- Mantém a conexão ativa a cada ciclo ---
fbMqttClient.Execute(bConnect);

// --- Decide quando publicar: na mudança ou a cada 10 s ---
fbHeartbeat(IN := NOT fbHeartbeat.Q, PT := T#10S);
bPublish := fbHeartbeat.Q
            OR ABS(stPress.rForce_kN - stLastPress.rForce_kN) > 1.0
            OR stPress.bRunning <> stLastPress.bRunning
            OR stPress.sState <> stLastPress.sState;

// --- Serializa e publica ---
IF bPublish AND fbMqttClient.bConnected THEN
    fbJson.ResetDocument();
    fbJson.StartObject();
    fbJson.AddKey('force_kN');       fbJson.AddReal(stPress.rForce_kN);
    fbJson.AddKey('temperature_C');  fbJson.AddReal(stPress.rTemperature_C);
    fbJson.AddKey('cycle_count');    fbJson.AddUdint(stPress.nCycleCount);
    fbJson.AddKey('running');        fbJson.AddBool(stPress.bRunning);
    fbJson.AddKey('state');          fbJson.AddString(stPress.sState);
    fbJson.EndObject();
    fbJson.CopyDocument(sPayload, SIZEOF(sPayload));

    fbMqttClient.Publish(
        sTopic       := sTopicData,
        pPayload     := ADR(sPayload),
        nPayloadSize := LEN(sPayload),
        eQoS         := TcIotMqttQos.AtLeastOnceDelivery,
        bRetain      := FALSE,
        bQueue       := FALSE);

    stLastPress := stPress;
END_IF

Algumas observações sobre as escolhas acima:

  • CopyDocument em vez de GetDocument. GetDocument retorna uma string padrão de 255 caracteres, que trunca silenciosamente payloads maiores. Copiar para um buffer dimensionado evita isso.
  • Report by exception. A banda morta de força e as comparações de estado publicam mudanças reais imediatamente, enquanto o heartbeat de 10 segundos prova que a máquina está viva mesmo quando nada muda.
  • Tratamento de erros. Acompanhe fbMqttClient.hrErrorCode e fbMqttClient.eConnectionState na visão online durante o comissionamento. A maioria das falhas aparece primeiro ali.

Para estruturas maiores, a Tc3_JsonXml também oferece uma função auxiliar que serializa um tipo de dado inteiro, incluindo atributos como unidades, em uma única chamada. A saída SAX escrita à mão, como acima, dá controle exato sobre os nomes das chaves, o que importa quando outras equipes consomem os dados.

Passo 3: verifique no servidor MQTT público

Ative a configuração, inicie o CLP e assine a partir de um PC:

mosquitto_sub -h broker.connectmq.com -p 1883 -i twincat-watch-t3w9p1 \
  -t 'connectmq/demo/t3w9p1/#' -v

Saída esperada:

connectmq/demo/t3w9p1/plant1/stamping/cell4/press1/telemetry {"force_kN":412.5,"temperature_C":38.2,"cycle_count":10233,"running":true,"state":"AUTO"}

Force um valor na visão online e a mudança aparece instantaneamente. O servidor MQTT público (gratuito) em broker.connectmq.com, anônimo e feito para testes e protótipos, é perfeito para esse tipo de colocação em operação, mas é público, então use um prefixo de topic aleatório e nada confidencial.

Passo 4: proteja a conexão Beckhoff TwinCAT MQTT

Máquinas em produção nunca devem publicar via TCP sem criptografia na internet. Crie um broker privado no portal do ConnectMQ, anote o usuário, a senha e o client ID gerados e então:

  1. Baixe o certificado ISRG Root X1 (a raiz do Let's Encrypt, usado pelo broker do ConnectMQ) e copie-o para o alvo, por exemplo para uma pasta Certificates no diretório de boot ou de configuração do TwinCAT.
  2. Amplie a configuração única:
fbMqttClient.sHostName     := 'YOUR_BROKER_HOST';
fbMqttClient.nHostPort     := 8883;
fbMqttClient.sClientId     := 'YOUR_CLIENT_ID';
fbMqttClient.sUserName     := 'YOUR_USERNAME';
fbMqttClient.sUserPassword := 'YOUR_PASSWORD';
fbMqttClient.stTLS.sCA     := 'C:\TwinCAT\3.1\Config\Certificates\isrgrootx1.pem';
  1. Configure um Last Will pela estrutura de will do cliente, por exemplo uma mensagem retida offline em plant1/stamping/cell4/press1/status, e publique um online retido no mesmo topic depois de conectar. Assim os consumidores conseguem distinguir uma máquina parada de uma conexão perdida.
  2. Remova o prefixo de demonstração e use a hierarquia de topics ISA-95 da sua planta.

Mantenha as credenciais fora do controle de versão: carregue-as de um arquivo no alvo ou de uma variável persistente definida durante o comissionamento, em vez de deixá-las fixas em um projeto que é compartilhado.

Projetando topics para uma frota de máquinas

Fabricantes de máquinas, como um fabricante de prensas em Joinville que atende clientes em todo o Brasil, muitas vezes entregam o mesmo projeto TwinCAT a dezenas de clientes, então topics fixos no código viram rapidamente um problema de manutenção. Alguns hábitos ajudam:

  • Transforme o prefixo do topic em parâmetro. Armazene os nomes de empresa, site, área, linha e máquina em variáveis persistentes definidas no comissionamento e monte a string do topic na inicialização.
  • Separe dados, status e eventos. Use .../telemetry para valores periódicos, .../status para informações retidas de online e estado e .../events para alarmes ou conclusões de lotes. Os consumidores assinam apenas o que precisam.
  • Versione o payload. Uma chave "schema": 1 custa poucos bytes e permite que o código consumidor lide com uma atualização de firmware que adiciona ou renomeia campos.
  • Mantenha os payloads pequenos. Publique os valores que as pessoas realmente usam. Dumps de diagnóstico podem ir para um topic separado, sob demanda.

Essas convenções também tornam os dados fáceis de navegar: um broker que reconhece caminhos no estilo ISA-95 pode apresentar cada máquina em uma árvore de site e linha sem configuração extra, e a mesma árvore serve de base para um gêmeo digital da linha.

Checklist de comissionamento

Verificação Por que importa
Relógio do alvo sincronizado via NTP O TLS rejeita certificados quando o relógio está muito errado
DNS configurado no IPC O hostname do broker precisa ser resolvido
Client ID único por máquina Duplicados desconectam um ao outro repetidamente
Buffer de payload dimensionado para o maior JSON Evita truncamento silencioso
Heartbeat mais report by exception Pouco tráfego com prova de vida
Topic de status retido com Last Will Detecção confiável de online e offline
Licença do TF6701 ativada A licença de teste expira após 7 dias

Solução de problemas

  • hrErrorCode mostra recusa de conexão. Credenciais ou client ID errados; em brokers que vinculam client IDs a credenciais, ambos precisam corresponder ao que foi emitido.
  • Erros de TLS após reinicialização. O caminho do certificado está errado no alvo, ou o arquivo da CA não foi copiado junto com o projeto de boot.
  • Nada é publicado apesar de bConnected. bPublish nunca fica verdadeiro, ou Publish é chamado antes de o payload ser montado.
  • As mensagens chegam em rajadas. bQueue := TRUE com uma taxa de chamada de Execute lenta; chame Execute a cada ciclo a partir de uma task rápida.

Onde isso se encaixa

Publicar a partir do IPC é uma das várias arquiteturas para extrair dados de máquinas; compare-a com as arquiteturas baseadas em gateway e em SCADA em conectividade de CLP para a nuvem. Se você trabalha com controladores de marcas variadas, o tutorial CODESYS MQTT usa um padrão de executar e publicar muito parecido. E quando muitas máquinas publicam em uma única hierarquia, o guia de IoT industrial com MQTT explica como modelá-la como um Unified Namespace que qualquer aplicação pode consumir pelo broker MQTT.

Conecte suas máquinas Beckhoff ao ConnectMQ

Rodar seu próprio broker ao lado de cada máquina significa certificados, atualizações e monitoramento em cada site. Um broker MQTT gerenciado elimina esse trabalho. Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito, e veja seus dados TwinCAT chegarem ao explorador de topics ao vivo em minutos.

Perguntas frequentes

Qual licença do TwinCAT preciso para MQTT?

A abordagem com biblioteca de CLP exige o TF6701 TwinCAT 3 IoT Communication. A alternativa baseada em configuração é o TF6720 IoT Data Agent. Ambos oferecem licença de teste de 7 dias.

O TwinCAT MQTT suporta TLS?

Sim. Defina o caminho do certificado da CA na estrutura TLS do cliente, conecte-se à porta 8883 e adicione as credenciais. Certificados de cliente também são suportados, caso o seu broker os exija.

O TwinCAT pode assinar topics MQTT?

Sim. O FB_IotMqttClient suporta assinaturas com uma fila de mensagens que você lê no CLP. Valide cada valor recebido antes que ele chegue à lógica de controle.

Por que meu payload JSON é cortado em 255 caracteres?

GetDocument retorna uma string de comprimento padrão. Use CopyDocument para um buffer maior, como mostrado acima.

Artigos relacionados

Cliente MQTT no CODESYS: Publicando Variáveis do CLP em um Broker

Configure a biblioteca IIoT MQTT Client do CODESYS para publicar variáveis do CLP em JSON, verifique-as no servidor MQTT público broker.connectmq.com e depois migre para um broker privado com credenciais e TLS.

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.