Modbus TCP
Registradores e coils Modbus sobre TCP/IP, com endereçamento tipado, controle de ordem de bytes e uma varredura de rede limitada.
O driver Modbus TCP lê e escreve registradores e coils Modbus sobre TCP/IP: CLPs, medidores, gateways e qualquer servidor que fale Modbus/TCP. O endereçamento é totalmente tipado: você escolhe uma classe de registrador e um número de registrador em base 0, e a aplicação monta a requisição do barramento; não há endereço em texto livre para errar.
Dispositivo
| Campo | Significado | Padrão |
|---|---|---|
| Host ou IP | Nome DNS, endereço IPv4 ou IPv6 do servidor ou gateway Modbus. | vazio: o dispositivo não é conectado até um ser informado |
| Porta | Porta TCP, de 1 a 65535. Um campo vazio mostra 502 em cinza e o dispositivo é chamado nela, que é também como se lê um dispositivo salvo com 0. | 502 |
| Unit ID | O unit id (escravo) Modbus levado em toda requisição, o que um gateway usa para rotear até o dispositivo atrás dele. De 0 a 255. | 1 |
| Enquadramento | Como cada requisição trafega pela conexão: MBAP, o cabeçalho do Modbus TCP na frente de cada requisição, ou RTU, o quadro RTU com o CRC enviado como está, para um conversor serial-Ethernet em modo transparente (veja RTU sobre TCP). Host, porta, Unit ID e tags são os mesmos nos dois casos. | MBAP |
| Intervalo mínimo entre transações (ms) | Ritmo de compatibilidade: o silêncio mínimo depois que uma transação termina, antes de a próxima começar, de 0 a 1000. Zero não acrescenta atraso artificial. | 0 |
| Intervalo de leitura (ms) | Taxa de leitura padrão para as tags que não a sobrepõem. | 1000 |
O Base URI mostrado no cabeçalho do painel é
modbus+tcp://host:port/unitID, mais ?minimumTransactionIntervalMs=n quando o
intervalo está definido.
Dispositivos que compartilham host e porta também compartilham uma única porteira de transações: requisições ao mesmo endpoint nunca se sobrepõem, e o maior intervalo mínimo entre transações configurado entre os dispositivos habilitados naquele endpoint ritma todos eles. O painel avisa quando outro dispositivo eleva o intervalo efetivo acima do que está configurado aqui. O intervalo governa apenas o tráfego que esta aplicação emite: ele é um recurso de compatibilidade para um servidor ou gateway lento, não um conserto para falhas de rede.
Conectar espera no máximo 5 segundos; uma resposta é esperada por no máximo 10 segundos; não há novas tentativas no nível do protocolo. O laço de tentativas em segundo plano é dono da reconexão, então um dispositivo desligado não custa nada além de uma leitura de qualidade ruim.
RTU sobre TCP
Um conversor serial-Ethernet em modo transparente não fala Modbus TCP por conta própria: o que chega ao seu socket sai como está pelo barramento serial, e o que o barramento responde volta. Um dispositivo atrás de um conversor é um dispositivo Modbus TCP com o Enquadramento em RTU: a estação envia o quadro RTU (o Unit ID, a requisição e o CRC) sem cabeçalho MBAP, e só aceita uma resposta cujo CRC confere. O Base URI passa a levar framing=rtu na consulta, por exemplo modbus+tcp://192.168.0.20:502/1?framing=rtu; um dispositivo em MBAP mantém o endereço que sempre teve. Todo o resto desta página continua valendo: as classes de registrador, os códigos de função, a fila de escritas, os timeouts e o intervalo entre transações.
- O Unit ID é o endereço do dispositivo no barramento serial atrás do conversor, de 1 a 247.
- Os dispositivos atrás de um conversor compartilham o host e a porta dele e, com eles, a porteira de transações: uma requisição por vez, que é também tudo o que um barramento serial leva. Se o conversor precisar de uma pausa entre quadros, aumente o Intervalo mínimo entre transações (ms).
- As configurações seriais do próprio conversor (velocidade em baud, formato) são feitas no conversor; a estação nunca as vê.
- Um quadro RTU não leva número de transação, então antes de cada requisição a estação descarta o que o conversor já tiver enviado: uma resposta que chega depois do timeout da sua requisição nunca é tomada pela da seguinte.
Endereçamento da tag
| Campo | Significado | Padrão |
|---|---|---|
| Classe do registrador | Qual entidade Modbus a tag endereça: Bobina (0xxxx), Entrada discreta (1xxxx), Registrador de entrada (3xxxx) ou Registrador de retenção (4xxxx). Cada uma leva o primeiro dígito que o endereço do manual tem para ela, então um manual que imprime só 30001 aponta para os registradores de entrada. | Derivada do tipo e do acesso: tags booleanas recebem uma entrada discreta (somente leitura) ou uma bobina (gravável); todo outro tipo recebe um registrador de entrada (somente leitura) ou um registrador de retenção (gravável). |
| Número do registrador (começando em 0) | O endereço bruto do protocolo. Este é o endereço em base 0 no barramento, não a notação do manual: o holding register 40001 é o registrador número 0. Digitar 30001 aqui não escolhe a classe, porque há equipamentos com registradores acima de 30000 de verdade: a classe é escolhida acima. O registrador viaja no barramento como um número de 16 bits, então o campo aceita de 0 a 65535 e recusa qualquer coisa mais larga onde é digitado. | 0 |
| Quantidade (registradores, vazio = automático) | Quantos registradores de 16 bits o valor ocupa. A caixa é desenhada só em tags String: todo outro tipo tem largura fixa, então não há o que sobrepor. | Por tipo: Boolean, Int16 e UInt16 1, Int32 e Float 2, String 4 |
| Byte mais significativo primeiro (MSB first, big-endian) | Qual byte de cada registrador de 16 bits vem primeiro no barramento; as palavras entre parênteses são as que os manuais imprimem. Em tags numéricas e numa tag booleana guardada num registrador de retenção ou de entrada; uma booleana numa bobina ou numa entrada discreta é um bit só, sem byte para ordenar, então ali a caixa não é desenhada. | ligado (o que a especificação Modbus pede) |
| Palavra mais significativa primeiro (palavra alta primeiro) | Qual registrador de um valor de dois registradores leva a metade alta. Só em tags Int32 e Float: um valor de um registrador só (Boolean, Int16, UInt16) não tem segundo registrador, então a caixa não é desenhada ali. Sob as duas caixas, Ordem dos bytes do valor nomeia o arranjo que elas formam nas letras de um manual (Ordem de bytes e de palavras). | ligado |
O cartão Origem termina com Endereço no manual, onde a tag fica na notação que o manual do equipamento imprime: o primeiro dígito da classe e depois o registrador contado a partir de 1. O registrador de entrada 0 lê 30001, um Float no registrador de retenção 100 lê de 40101 a 40102, e um registrador acima de 9998 ganha seis dígitos (o registrador de retenção 9999 lê 410000), então o painel se lê contra o manual linha por linha.
Tipos de valor e quantidades
Seis tipos de valor são oferecidos, e a largura de protocolo de cada um é fixa:
| Tipo de dado | Registradores | Forma no barramento |
|---|---|---|
| Boolean | 1 | Numa classe de registrador: qualquer registrador diferente de zero lê verdadeiro, e uma escrita envia 1 ou 0. Em Coil/DiscreteInput: o próprio bit. |
| Int16 | 1 | Inteiro de 16 bits com sinal, num único registrador, de -32768 a 32767. |
| UInt16 | 1 | Inteiro de 16 bits sem sinal, num único registrador, de 0 a 65535. O mesmo registrador lê 65535 como UInt16 e -1 como Int16: o sinal vem do tipo de dado escolhido, não do registrador. |
| Int32 | 2 | Inteiro de 32 bits com sinal, num par de registradores. |
| Float | 2 | Precisão simples IEEE 754, num par de registradores. |
| String | 1 ou mais (padrão 4) | Bytes UTF-8 empacotados dois por registrador. Uma leitura para no primeiro byte NUL; uma escrita precisa caber na quantidade declarada (2 bytes por registrador) e é preenchida com zeros. |
Uma tag String é lida e escrita na ordem em que o dispositivo guarda os bytes, e uma escrita sempre envia UTF-8. Bytes que não são UTF-8 válido, que é a cara de uma faixa que o dispositivo nunca inicializou ou de um texto escrito em outra codificação, leem como o caractere de substituição do Unicode em vez de falhar: a tag mostra algo visivelmente errado, e toda outra tag daquele dispositivo segue lendo.
A Quantidade (registradores, vazio = automático) é pedida só em tags String. As larguras de Boolean, Int16, UInt16, Int32 e Float são fixas, então a caixa não é desenhada nesses pontos, nem no painel da tag nem na grade de tags; a sobreposição existe para dimensionar tags String.
Ordem de bytes e de palavras
A caixa da ordem de bytes é desenhada em tags numéricas e numa booleana guardada em registrador; a da ordem de palavras, só nas de dois registradores (Int32, Float). Elas são perguntas
independentes: qual byte vem na frente dentro de cada registrador, e qual registrador vem
na frente num par. O Modbus não define nenhuma das duas para texto, então uma tag String
não as recebe: os bytes dela viajam na ordem em que o dispositivo os guarda. Para o valor
0x01020304, com A sendo o byte mais significativo, os quatro arranjos são:
| Byte mais significativo primeiro | Palavra mais significativa primeiro | Bytes no barramento |
|---|---|---|
| ligado | ligado | AB CD (o padrão da especificação) |
| ligado | desligado | CD AB (a troca clássica de palavras) |
| desligado | ligado | BA DC |
| desligado | desligado | DC BA |
Leituras e escritas aplicam as mesmas duas respostas na mesma ordem, então uma escrita deposita exatamente os bytes que uma leitura teria trazido de volta. Ordem dos bytes do valor, sob as caixas, diz o arranjo numa palavra (ABCD, CDAB, BADC ou DCBA), como um manual o nomeia.
Um valor Int16 ou UInt16 é um registrador só, então só a ordem de bytes se aplica a ele:
para 0x1234, byte mais significativo primeiro envia 12 34 e desligado envia 34 12.
Não há segundo registrador para posicionar, então a caixa da ordem de palavras não é
desenhada para ele.
Códigos de função
| Classe de registrador | Leitura | Escrita |
|---|---|---|
| Registrador de retenção (4xxxx) | 3 (Read Holding Registers) | 6 (registrador único) ou 16 (vários registradores) |
| Registrador de entrada (3xxxx) | 4 (Read Input Registers) | somente leitura; uma escrita é recusada |
| Bobina (0xxxx) | 1 (Read Coils) | 5 (Force Single Coil), um bit por vez |
| Entrada discreta (1xxxx) | 2 (Read Discrete Inputs) | somente leitura; uma escrita é recusada |
Uma escrita só retorna sucesso quando a resposta de protocolo do servidor confirma a aceitação; o valor cacheado só avança então.
Descoberta
A varredura é explícita e limitada: a aplicação nunca deduz nem varre a sua sub-rede local. O formulário de escopo recebe:
| Campo | Significado | Padrão |
|---|---|---|
| Host IPv4 ou CIDR | Um endereço (192.168.1.10) ou uma sub-rede não mais ampla que /24 (192.168.1.0/24). Os endereços de rede e de difusão são pulados. |
obrigatório |
| Porta | A porta a sondar. | 502 |
| Unit ids | Valores, listas separadas por vírgula ou faixas crescentes: 1, 1,5,9, 1, 3, 8-16 (de 0 a 255). |
1 |
| Enquadramento | O quadro em que cada sondagem é enviada. Um conversor em modo transparente só responde a quadros RTU, então varra-o em RTU. | MBAP |
| Intervalo mínimo entre transações (ms) | Ritmo entre sondagens concluídas no mesmo host, de 0 a 1000. | 0 |
A varredura envia cada sondagem no Enquadramento escolhido. Em RTU cada sondagem é o quadro RTU puro, e uma resposta só conta quando o Unit ID confere e o CRC é válido, então as unidades atrás de um conversor em modo transparente são encontradas como qualquer outra. Uma unidade encontrada mantém o enquadramento da varredura ao ser acrescentada.
Uma varredura pode enviar no máximo 256 sondagens (hosts × unit ids); um plano maior é recusado antes de qualquer soquete abrir. A única requisição enviada é a Read Basic Device Identification (função 43/14): a descoberta nunca lê registradores nem adivinha um mapa de registradores. Uma resposta de exceção Modbus totalmente válida prova que uma unidade está presente sem afirmar a identidade dela; alcançabilidade TCP, timeouts e quadros malformados não provam. Até quatro hosts são varridos em paralelo, sequencialmente dentro de cada host, com timeouts de 750 ms para conectar e para sondar.
Os resultados carregam o endpoint completo e um nome sugerido, montado a partir do fabricante e do código de produto quando o dispositivo os relata. Os candidatos têm zero tags: os registradores são configurados depois do Adicionar. Uma unidade já configurada é marcada como tal e oferece Abrir em vez de criar uma duplicata.
Limites que vale conhecer
- Outras larguras de inteiro (SByte, Byte, UInt32, Int64, UInt64) e Double não são oferecidos: o codec do barramento vai e volta exatamente com os seis tipos acima.
- Uma requisição fica pendente por endpoint de cada vez; muitos dispositivos atrás de um gateway compartilham essa serialização por projeto.
- As escritas endereçam um coil ou uma sequência de registradores por vez; não há escrita de vários coils.