Você está na página 1de 20

O protocolo Modbus em detalhes

Visão geral

O Modbus é um protocolo industrial desenvolvido em 1979 para possibilitar a comunicação


entre dispositivos de automação. Originalmente implementado como um protocolo de nível de
aplicação destinado a transferir dados por uma camada serial, o Modbus foi ampliado para incluir
implementações em comunicações seriais, TCP/IP e UDP (user datagram protocol). Este
documento oferece uma visão detalhada da implementação do protocolo.

O que é o protocolo Modbus?

O Modbus é um protocolo de requisição-resposta que utiliza um relacionamento mestre-


escravo. Em um relacionamento mestre-escravo, a comunicação sempre ocorre em pares — um
dispositivo deve iniciar a requisição e então aguardar por uma resposta — e o dispositivo iniciador
(o mestre) é responsável por iniciar cada interação. Tipicamente, o mestre é uma interface
homem-máquina (IHM) ou sistema SCADA (Supervisory Control and Data Acquisition) e o
escravo é um sensor, controlador lógico programável (CLP) ou controlador programável para
automação (CPA). O conteúdo dessas requisições e respostas e as camadas de rede pelas quais
essas mensagens são enviadas são definidos pelas diferentes camadas do protocolo.

Figura 1. Relacionamento de rede tipo mestre-escravo

Camadas do protocolo Modbus

Em sua implementação inicial, o Modbus era um protocolo simples, criado no topo da


comunicação serial; dessa forma, não podia ser dividido em camadas. Ao longo do tempo, outras
unidades de dados de aplicação foram sendo introduzidas para alterar o formato dos pacotes
utilizados sobre o serial ou permitir o uso de TCP/IP e redes UDP (User Datagram Protocol). Isso
levou a uma separação entre o protocolo básico, que define a unidade de dados de protocolo
(PDU) e a camada de rede, que define a unidade de dados de aplicação (ADU).
Unidade de dados de protocolo

A PDU e seu código formam a base da especificação do protocolo de aplicação do


Modbus. Essa especificação define o formato da PDU, os diversos conceitos de dados usados
pelo protocolo, o uso de códigos de função para acessar esses dados e a implementação dos
diversos códigos de função e as restrições específicas de cada um deles.

A PDU do Modbus é formada por um código de função seguido por um conjunto de dados
associado. As dimensões e o conteúdo desses dados são definidos pelo código de função, mas
toda a PDU (código de função e dados) não pode ultrapassar 253 bytes. Cada código de função
tem um comportamento específico, que os escravos têm flexibilidade para implementar com base
no comportamento desejado da aplicação. A especificação de PDU define os conceitos básicos
para o acesso e manipulação dos dados; entretanto, um escravo pode tratar os dados de uma
maneira não definida explicitamente na especificação.
Acesso aos dados no Modbus e o modelo de dados do Modbus

Os dados que podem ser acessados pelo Modbus são armazenados, de forma geral, em
um dos quatro bancos de dados, ou faixas de endereço: coils, entradas discretas, registradores
holding e registradores de entrada. Como ocorre com muitas partes da especificação, esses
nomes podem variar, dependendo da indústria ou aplicação. Por exemplo, os registradores
holding podem ser denominados registradores de saída, e os coils podem ser referidos como
saídas digitais ou discretas. Esses bancos de dados definem o tipo e os direitos de acesso dos
dados contidos. Os dispositivos escravo têm acesso direto a esses dados, que são hospedados
localmente nos dispositivos. Os dados que podem ser acessados pelo Modbus são de forma
geral um subconjunto da memória principal do dispositivo. Por outro lado, os mestres Modbus

precisam solicitar acesso a esses dados, utilizando diversos códigos de função.

O comportamento de cada bloco é descrito no quadro abaixo

Esses blocos dão a você a capacidade de restringir ou permitir acesso a diferentes


elementos de dados e também fornecer mecanismos simplificados na camada de aplicação para
o acesso a diferentes tipos de dados. Os blocos são totalmente conceituais. Eles podem existir
como endereços de memória distintos em um dado sistema, mas também podem se sobrepor
entre si. Por exemplo, o coil 1 pode existir na mesma posição de memória que o primeiro bit da
palavra representada pelo registrador holding 1. O esquema de endereçamento é totalmente
definido pelo dispositivo escravo, e a interpretação de cada bloco de memória é uma parte
importante do modelo de dados do dispositivo.
Endereçamento do modelo de dados

A especificação define que cada bloco contém um espaço de endereçamento de até


65.536 (216) elementos. Com a definição da PDU, o Modbus define o endereço de cada elemento
de dados na faixa de 0 a 65.535. Entretanto, cada elemento de dados é numerado de 1 a n, onde
n tem o valor máximo de 65.536. Assim, o coil 1 está no endereço 0 do bloco de coils, enquanto
que o registrador holding 54 está no endereço 53 da seção de memória reservada pelo escravo
para os registradores holding.

Não é obrigatório implementar as faixas completas permitidas pela especificação no dispositivo.


Por exemplo, pode ser escolhido para um dado dispositivo não implementar coils, entradas
discretas ou registradores de entrada e, em vez disso, utilizar registradores holding de 150 a 175
e 200 a 225. Isso é perfeitamente aceitável; nesse caso, tentativas de acesso inválidas seriam
tratadas por exceções.

Faixas de endereçamento de dados

Embora a especificação defina que diferentes tipos de dados devem existir em blocos diferentes e
atribua uma faixa de endereços local para cada tipo, isso não implica que haverá
necessariamente um esquema de endereçamento intuitivo ou facilmente compreensível para a
documentação da memória que pode ser acessada pelo Modbus para um determinado
dispositivo. Para simplificar a discussão sobre as posições dos blocos de memória, foi introduzido
um esquema de numeração que inclui prefixos ao endereço dos dados em questão.

Por exemplo, em vez de se referir a um item como registrador holding 14 no endereço 13, o
manual do dispositivo pode se referir a um item de dados no endereço 4.014, 40.014 ou 400.014.
Em todos esses casos, o primeiro número especificado é 4, que representa os registradores
holding; os demais números especificam um endereço. A diferença entre 4XXX, 4XXXX e
4XXXXX depende do espaço de endereços utilizado pelo dispositivo. Se todos os 65.536
registradores estiverem em uso, utilizaremos a notação 4XXXXX, pois ela permite o uso da faixa
de 400.001 a 465.536. Se apenas alguns registradores forem usados, uma prática comum é usar
a faixa de 4.001 a 4.999.
Nesse esquema de endereçamento, cada tipo de dados recebe um prefixo, como mostrado no
quadro abaixo

Coils utilizam o prefixo 0. Isso significa que a referência 4001 pode se referir ao registrador
holding 1 ou ao coil 4001. Por esse motivo, é recomendado que todas as implementações novas
utilizem o endereçamento de 6 dígitos com zeros na frente. Essa informação deverá ser anotada
na documentação. Dessa forma, o registrador holding 1 é referenciado como 400.001 e o coil
4001 é referenciado como 004.001

Valores iniciais dos endereços de dados

A diferença entre endereços de memória e números de referência inclui uma complicação


adicional, representada pela indexação selecionada por uma determinada aplicação. Como
mencionado anteriormente, o registrador holding 1 está localizado no endereço 0. Tipicamente, os
números de referência são indexados em 1; nesse caso, o valor inicial de uma faixa será 1.
Dessa forma, a tradução literal de 400.001 é registrador holding 00001, que está no endereço 0.
Algumas implementações escolhem iniciar suas faixas em zero; dessa forma, 400.000 indica
registrador holding no endereço zero. O quadro 3 demonstra esse conceito.

Faixas indexadas em 1 são muito usadas e altamente recomendadas. De qualquer forma, o valor
inicial de cada faixa sempre deverá ser indicado na documentação.
Tipos de dados para grandes valores

O padrão Modbus oferece um modelo de dados relativamente simples, que não inclui
outros tipos de dados além do valor do bit e palavra não sinalizada. Esses valores podem ser
suficientes para alguns sistemas, nos quais os valores de bit correspondem a solenóides e relés e
os valores das palavras correspondem a valores ADC sem escala, mas não para sistemas
avançados. Como resultado, muitas implementações do Modbus incluem tipos de dados que vão
além das fronteiras do registrador. O módulo LabVIEW Datalogging and Supervisory Control
(DSC) e o KEPServerEX definem alguns tipos de referência. Por exemplo, as strings
armazenadas em um registrador holding seguem o formato padrão (400.001), mas são seguidas
por um decimal, o comprimento e o byte que ordena a string (400.001.2H, uma string de 2
caracteres no registrador holding 1, onde o byte em nível alto corresponde ao primeiro caractere
da string). Isso é necessário porque cada requisição tem tamanho finito; dessa forma, o mestre
Modbus precisa saber exatamente onde a string começa e termina, em vez de procurar por um
comprimento fixo ou delimitador, como o NULL.

Acesso a bit

Além de permitir acesso a dados que vão além das fronteira do registrador, alguns mestres
Modbus permitem o uso de referências a bits individuais dentro de um registrador. Com isso, os
dispositivos podem combinar dados de todos os tipos em uma mesma faixa de memória sem ter
de separar dados binários no coil e faixas de entrada discretas. Normalmente, esse recurso é
indicado pelo uso de um ponto decimal e o índice de bit ou número, dependendo da
implementação. Ou seja, o primeiro bit do primeiro registrador pode ser 400.001.00 ou
400.001.01. É recomendado que toda documentação especifique o esquema de indexação
utilizado.
Configuração endian dos dados

Os dados de múltiplos registros, como valores de ponto flutuante de precisão única, podem
ser facilmente transferidos ao Modbus, com a separação dos dados em dois registradores. Como
isso não é definido pelo padrão, a ordem de bit (endian) utilizada nessa separação também não
está definida. Cada palavra não sinalizada deve ser enviada na ordem de bit usada pela rede (big
endian) para satisfazer o padrão, mas muitos dispositivos invertem a ordem de bytes no caso de
dados formados por vários bytes. A figura 2 mostra um exemplo incomum, mas válido, dessa
implantação.

É de responsabilidade do mestre entender como o escravo está armazenando informações


na memória e decodificá-las adequadamente. É recomendável que a documentação informe a
ordem da palavra usada pelo sistema. A ordem endian pode também ser entendida como uma
opção de configuração do sistema, com funções de codificação e decodificação, se for necessário
ter flexibilidade na implementação.
Strings

Strings podem ser armazenadas facilmente em registradores Modbus. Por simplicidade,


algumas implementações requerem que os comprimentos de string sejam múltiplos de 2 e que
qualquer espaço adicional seja preenchido por valores nulos. A ordem dos bytes também é uma
variável nas interações das strings. O formato das strings pode ou não incluir um NULL como
valor final. Como exemplo dessa variabilidade, alguns dispositivos podem armazenar dados como
mostrado na figura abaixo

Códigos de função

Ao contrário do modelo de dados, que pode variar significativamente de um dispositivo a


outro, os códigos de função e seus dados são definidos explicitamente pela norma. Cada função
segue um padrão. Em primeiro lugar, o escravo valida entradas como, por exemplo, código de
função, endereço dos dados e faixa de dados. Em seguida, ele executa a ação requisitada e
envia a resposta apropriada ao código. Se qualquer etapa desse processo falhar, uma exceção
será enviada de volta ao requisitante. O transporte de dados dessas solicitações é a PDU.
A PDU do Modbus

A PDU é formada por um código de função de 1 byte seguido por até 252 bytes de dados de
função.

O código de função é o primeiro item a ser validado. Se o código de função não for
reconhecido pelo dispositivo que recebe a requisição, ele responderá com uma exceção. Se o
código de função for aceito, o dispositivo escravo começará a decompor os dados conforme a
definição da função.

Como o tamanho do pacote é limitado a 254 bytes, os dispositivos são limitados com relação à
quantidade de dados que pode ser transferida. Os códigos de função mais comuns podem
transferir entre 240 e 250 bytes de dados do modelo de dados do escravo, dependendo do
código.
Execução da função pelo escravo

Conforme definido pelo modelo de dados, diferentes funções são definidas para acessar
diferentes blocos conceituais de dados. Uma implementação muito usada faz os códigos
acessarem posições estáticas de memória, mas outros comportamentos podem ser usados. Por
exemplo, código de função 1 (ler coils) e 3 (ler registradores holding) podem acessar a mesma
posição física na memória. Por outro lado, o código de função 3 (ler registradores holding) e 16
(escrever em registradores holding) podem acessar posições de memória completamente
diferentes. Dessa forma, a execução de cada código de função é melhor considerada como parte
da definição do modelo de dados do escravo.

Independentemente do comportamento executado, todos os dispositivos escravo devem seguir


um diagrama de estados simples para cada requisição. A figura 5 mostra um exemplo baseado
no código 1, ler coils.
Cada escravo precisará validar o código de função, quantidade de entradas, endereço
inicial, faixa total e a execução da função pelo escravo que fará a leitura.

Embora sejam mostradas faixas de endereços estáticos no diagrama de estados acima, as


necessidades dos sistemas do mundo real podem causar alguma variação com relação aos
números definidos. Em alguns casos, os dispositivos escravo não conseguem transferir a
quantidade máxima de bytes definida pelo protocolo. Isso significa não permitir que um mestre
requisite 0x07D0 entradas se eles só podem responder com 0x0400. De maneira similar, um
modelo de dados de escravo pode definir a faixa de valores de coil aceitáveis como os endereços
de 0 a 500. Se um mestre fizer uma requisição de 125 endereços a partir do endereço 0, isso
estará OK, mas se fizer a mesma requisição a partir do endereço 400, o coil final estaria no
endereço 525, que está fora da faixa para esse dispositivo, o que resultaria na exceção 02,
conforme definido pelo diagrama de estados.

Códigos de função padrão

A definição de cada código de função padrão é fornecida na especificação. Mesmo para os


códigos de função mais comumente usados, é inevitável haver algum descasamento entre as
funções habilitadas no mestre e aquelas que podem ser tratadas pelo escravo. Para lidar com
isso, as versões mais recentes da especificação TCP do Modbus definiu três classes de
conformidade. O documento oficial Modbus Conformance Test Specification não faz referência a
essas classes; em vez disso, define conformidade para cada função. Entretanto, elas ainda
podem facilitar a compreensão. É recomendado que qualquer documentação siga a especificação
do teste e defina sua conformidade pelos códigos que pode utilizar, e não pelas classificações
usadas anteriormente.

Códigos da classe 0

Os códigos da classe 0 são considerados em geral o mínimo para um dispositivo Modbus


utilizável, pois dão a um mestre a capacidade de ler ou escrever no modelo de dados.
Códigos da classe 1

Os códigos de função da classe 1 compreendem outros códigos necessários para acessar todos
os tipos do modelo de dados. Na definição original, essa lista incluía o código de função 7 (ler
exceção). Entretanto, esse código é definido pela especificação atual como código somente
serial.

Códigos da classe 2

Os códigos de função da classe 2 são funções mais especializadas, implementadas com menor
frequência. Por exemplo, Read/Write Multiple Registers pode ajudar a reduzir a quantidade total
de ciclos de requisição-resposta, mas o comportamento ainda pode ser implementado com
códigos de classe 0.
Interface encapsulada do Modbus

O código de interface encapsulada do Modbus (MEI), função 43, é usado para encapsular
outros dados dentro de um pacote Modbus. Até o momento, há dois números de MEI disponíveis,
13 (CANopen) e 14 (Device Identification).

A função 43/14 (Device Identification) é útil por permitir a transferência de até 256 objetos
exclusivos. Alguns desses objetos são pré-definidos e reservados, como nome do fornecedor e
código do produto, mas aplicações podem definir outros objetos a serem transferidos como
conjuntos de dados genéricos.

Esse código não é implementado comumente.


Exceções

Os escravos usam exceções para indicar diversas condições problemáticas, de requisições mal
formadas a entradas incorretas. Entretanto, as exceções podem também ser geradas como
resposta no nível da aplicação a uma requisição inválida. Os escravos não respondem a
requisições emitidas com uma exceção. Nesses casos, o escravo ignora uma requisição
incompleta ou corrompida e começa a esperar pela chegada de uma nova mensagem.

Exceções são relatadas em um formato de pacote definido. Em primeiro lugar, um código de


função é enviado de volta ao mestre solicitante igual ao código de função original com exceção de
seu conjunto de bits mais significativo. Isso equivale a incluir 0x80 ao valor do código de função
original. Em vez dos dados normais associados à resposta a uma determinada função, as
respostas à exceção incluem um único código de exceção.

No padrão, os quatro códigos de exceção mais comuns são 01, 02, 03 e 04. Esses códigos são
mostrados no quadro 7, com os significados padrão para cada função.

Código de exceção Significado

01 O código de função recebido não é suportado. Para confirmar o código de


função original, subtraia 0x80 do valor retornado.

02 A requisição tentou acessar um endereço inválido. No padrão, isso pode


acontecer somente se o endereço inicial e a quantidade de valores
requisitada ultrapassar 216. Entretanto, alguns dispositivos podem limitar
ainda mais esse espaço de endereços em seus modelos de dados.

03 A requisição tem dados incorretos. Em alguns casos, isso significa que


houve algum descasamento entre parâmetros, por exemplo, entre o
número de registradores enviados e o campo "byte count". Mais
comumente, o mestre solicitou mais dados do que permitido pelo escravo
ou pelo protocolo. Por exemplo, um mestre pode ler apenas 125
registradores holding por vez, e dispositivos com recursos limitados podem
reduzir ainda mais esse número de registradores.

04 Ocorreu um erro não recuperável durante uma tentativa de processar a


requisição. Esse é um código de exceção geral, que indica que a
requisição era válida, mas o escravo não conseguiu executá-la.

Quadro 7. Códigos comuns de exceção do Modbus


O diagrama de estado para cada código de função deve cobrir pelo menos o código de exceção
01 e normalmente incluir os códigos 04, 02 e 03; quaisquer outros códigos de exceção definidos
são opcionais.

Unidade de dados de aplicação

Além das funções definidas no núcleo da PDU do protocolo Modbus, você pode usar
diversos protocolos de rede. Os protocolos mais usados são TCP/IP e serial, mas você também
pode usar outros, como o UDP. Para transmitir os dados necessários para o Modbus em todas
essas camadas, o Modbus inclui um conjunto de variantes de ADU feitas especificamente para
cada protocolo de rede.

Recursos comuns

O Modbus requer determinados recursos para fornecer comunicação confiável. O Unit ID


ou Address é usado em todos os formatos de ADU para fornecer informações de roteamento à
camada de aplicação. Cada ADU é fornecida com uma PDU completa, incluindo o código de
função e os dados associados a uma determinada requisição. Para aumentar a confiabilidade,
todas as mensagens contêm informações de verificação de erro. Além disso, todas as ADUs
possuem um mecanismo que determina o início e o fim do quadro da requisição, mas os
implementa de formas diferentes.

Formatos padrão

Os três formatos padrão para as ADUs são TCP, RTU (unidade de terminal remoto) e
ASCII. As ADUs dos tipos RTU e ASCII são tradicionalmente utilizadas por uma linha serial,
enquanto que o TCP é usado em redes TCP/IP ou UDP/IP modernas.

TCP/IP

As ADUs do tipo TCP são formadas pelo cabeçalho do Modbus Application Protocol (MBAP)
concatenado com a PDU do Modbus. O MBAP é um cabeçalho de uso geral, que depende de
uma camada de rede confiável. O formato dessa ADU, incluindo o header, é mostrado na figura 6.

A ADU do tipo TCP/IP

Os campos de dados do cabeçalho indicam seu uso. Em primeiro lugar, ele contém um
identificador de transações. Esse é um recurso valioso em uma rede que pode ter várias
requisições em processamento simultaneamente. Com isso, por exemplo, um mestre pode enviar
requisições 1, 2 e 3. Em algum ponto posteriormente, um escravo pode responder na ordem 2, 1,
3. Nesse caso, o mestre pode combinar as requisições com suas respostas e interpretar os dados
corretamente. Esse é um recurso útil para redes Ethernet.

O identificador do protocolo normalmente é zero, mas você pode usá-lo para expandir o
comportamento do protocolo. O campo Length é usado pelo protocolo para delinear o
comprimento do restante do pacote. A posição desse elemento também indica a dependência
desse formato do cabeçalho em uma camada de rede confiável. Como os pacotes TCP possuem
verificação de erro incorporada e garantem a coerência e entrega dos dados, o comprimento do
pacote pode estar localizado em qualquer parte do cabeçalho. Em uma rede inerentemente
menos confiável, como uma rede serial, um pacote pode ser perdido. Nesse caso, mesmo que
um feixe de dados lido pela aplicação incluísse informações válidas de transação e protocolo, a
informação corrompida de comprimento tornaria o cabeçalho inválido. O TCP oferece um
razoável grau de proteção contra essa situação.

O campo Unit ID normalmente não é utilizado para dispositivos TCP/IP. Entretanto, o


Modbus é um protocolo tão utilizado que muitos gateways diferentes foram desenvolvidos, o que
converte o protocolo Modbus em outro protocolo. Em sua destinação original, o gateway Modbus
de TCP/IP para serial poderia ser usado para permitir a conexão entre novas redes TCP/IP e
redes seriais mais antigas. Em um ambiente como esse, a Unit ID é usada para determinar o
endereço do dispositivo escravo para o qual a PDU é realmente destinada.

Para finalizar, a ADU contém uma PDU. O comprimento dessa PDU é ainda limitado a 253 bytes
no protocolo padrão.

RTU

A ADU da RTU parece ser muito mais simples, como mostrado na figura 7.

Figura 7. ADU da RTU

Diferentemente da ADU mais complexa do TCP/IP, essa ADU contém apenas duas partes de
informação além da PDU base. Em primeiro lugar, um endereço é usado para definir a qual
escravo a PDU é destinada. Na maior parte das redes, o endereço 0 é o endereço de "difusão".
Isso significa que se um mestre enviar um comando ao endereço 0, todos os escravos deverão
processar a requisição, mas nenhum deles deverá responder. Além desse endereço, um CRC é
usado para garantir a integridade dos dados.
Entretanto, nas implementações mais modernas a realidade está muito longe de ser simples. O
pacote é delimitado por um par de intervalos de silêncio — ou seja, períodos nos quais não há
comunicação no barramento. Para a taxa de bauds de 9.600, esse intervalo é de
aproximadamente 4 ms. O padrão define um intervalo de silêncio mínimo, independente da taxa
de bauds, um pouco menor que 2 ms.

Em primeiro lugar, isso traz uma desvantagem ao desempenho, pois o dispositivo precisa esperar
o término desse tempo de guarda antes de processar o pacote. Um problema maior, entretanto,
foi o surgimento de outras tecnologias utilizadas em transferências seriais e taxas de baud muito
maiores do que as existentes quando o padrão foi lançado. Ao utilizar um cabo de conversão
USB-serial, por exemplo, você não tem controle sobre o empacotamento e transferência dos
dados. Testes mostram que usar um cabo USB-serial com o driver NI-VISA introduz grandes
lacunas de tamanho variável no feixe de dados, e essas lacunas — períodos de silêncio —
confundem o código que segue a especificação, fazendo-o acreditar que a mensagem foi
concluída. Como a mensagem não está completa, isso normalmente leva a um CRC inválido e à
interpretação pelo dispositivo de que a ADU foi corrompida.

Além dos problemas com a transmissão, as modernas tecnologias de drivers abstraem


significativamente a comunicação serial e tipicamente requerem um mecanismo de polling do
código de aplicação. Por exemplo, nem o .NET Framework 4.5 SerialPort Classnem o NI-VISA
fornecem um mecanismo para detectar silêncio em uma linha serial além do polling em bytes na
porta. Isso resulta em uma escolha de baixo desempenho (se o polling for realizado lentamente
demais) ou alta utilização da CPU (se o polling for executado rapidamente demais).

Um método muito usado para tratar desses problemas é separar a camada de abstração entre a
PDU do Modbus e a camada de rede. Com isso, o código serial interroga o pacote da PDU do
Modbus para determinar o código de função. Em conjunto com outros dados no pacote, o
comprimento do pacote restante pode ser descoberto e utilizado para determinar o final do
pacote. Tendo essa informação, é possível usar um tempo de timeout muito maior, permitindo
lacunas na transmissão, e o polling da aplicação pode ocorrer muito mais lentamente. Esse
mecanismo é recomendado para novos desenvolvimentos. Caso o seu código não empregue
esse mecanismo, você poderá ter uma quantidade de pacotes "corrompidos" maior que a
esperada.
ASCII

A ADU do ASCII é mais complexa que a RTU mostrada na figura 8, mas também evita muitos dos
problemas do pacote de RTU. Entretanto, ela tem suas próprias desvantagens.

ADU do ASCII

Para resolver o problema da determinação do tamanho do pacote, a ADU do ASCII tem início e
fim únicos e bem definidos para cada pacote. Cada pacote é iniciado por ":" e é encerrado com os
caracteres CR (carriage return) e LF (line feed). Além disso, APIs seriais como NI-VISA e o .NET
Framework SerialPort Class podem facilmente ler dados em um buffer até que um caractere
específico — como CR/LR — seja recebido. Essas características tornam mais fácil processar a
transmissão de dados na linha serial de maneira eficiente nos modernos códigos das aplicações.

A desvantagem da ADU de ASCII é que todos os dados são transferidos como caracteres
hexadecimais codificados em ASCII. Isso significa que em vez de enviar um único byte para o
código de função 3, 0x03, ela envia os caracteres ASCII “0” e “3”, ou 0x30/0x33. Isso facilita a
leitura do protocolo por um ser humano, mas isso também significa ser necessário transferir o
dobro dos dados pela rede serial, além disso, as aplicações de envio e recepção devem ser
capazes de interpretar os valores ASCII.

Extensão do Modbus

O Modbus é um padrão relativamente simples e aberto, que pode ser modificado conforme
as necessidades de uma determinada aplicação. Esse é o protocolo mais usado na comunicação
entre uma IHM e CLP ou CPA, pois essa é uma situação na qual uma única organização controla
as duas pontas do protocolo. Os desenvolvedores de sensores, por exemplo, têm maior
probabilidade de aderir ao padrão escrito, porque eles tipicamente somente controlam a
implementação de seus escravos, e a interoperabilidade é desejável.

De forma geral, não é recomendável modificar o protocolo. Esta seção é simplesmente fornecida
como um reconhecimento dos mecanismos que outros já usaram para ajustar o comportamento
do protocolo.
Novos códigos de função

Alguns códigos de função estão definidos, mas o padrão Modbus permite que você
desenvolva outros códigos de função. Especificamente os códigos de função de 1 a 64, 73 a 99 e
de 111 a 127 são códigos públicos, reservados e com exclusividade garantida. Os códigos
restantes, de 65 a 72 e 100 a 110 são para uso definido pelo usuário. Com esses códigos
definidos pelo usuário, você pode usar qualquer estrutura de dados. Os dados podem até mesmo
ultrapassar o limite de 253 bytes para a PDU do Modbus, mas toda a aplicação deve ser validada
para garantir que as outras camadas trabalharão como esperado quando a PDU ultrapassar o
limite padrão. Os códigos de função acima de 127 são reservados para respostas a exceções.

Camadas de rede

O Modbus pode ser executado em muitas camadas de rede além de serial e TCP. Uma
implementação potencial é o UDP, por ser adequado ao estilo de comunicação do Modbus. O
Modbus é basicamente um protocolo baseado em mensagem; assim, a capacidade da UDP de
enviar um pacote bem definido de informação sem qualquer informação adicional no nível da
aplicação, como um caractere inicial ou comprimento, torna a implementação do Modbus
extremamente simples. Em vez de exigir uma ADU adicional ou reutilizar uma ADU existente, os
pacotes de PDU do Modbus podem ser enviados pelo uso de uma API de UDP e serem
recebidos totalmente formados na outra extremidade. Embora o TCP seja vantajoso para alguns
protocolos, devido ao seu sistema interno de acknowledgement, o Modbus realiza esse
acknowledgement na camada de aplicação. Entretanto, usar o UDP dessa maneira elimina o
campo de identificador de transação da ADU do TCP, o que impede a possibilidade de haver
diversas transações simultâneas. Assim, o mestre deve ser síncrono ou o pacote do UDP deve
ter um identificador que ajude o mestre a organizar requisições e respostas. Uma sugestão de
implementação seria usar a ADU do TCP/IP em uma camada de rede do UDP.
Modificações da ADU

Para finalizar, uma aplicação pode escolher modificar uma ADU ou usar partes não
utilizadas de uma ADU existente, como o TCP. Por exemplo, o TCP define um campo de 16 bits,
um protocolo de 16 bits e uma Unit ID de 8 bits. Dado que a maior PDU do Modbus tem 253
bytes, o maior byte do comprimento é sempre zero. Para Modbus/TCP, o campo de protocolo e a
Unit ID são sempre zero. Uma extensão simples do protocolo poderia enviar três pacotes
simultaneamente alterando o campo de protocolo para um número diferente de zero e usando os
dois bytes não utilizados (Unit ID e maior byte do campo de comprimento) para o envio dos
comprimentos das duas PDUs adicionais (veja a figura 9).

Exemplo de modificação da ADU do TC

Você também pode gostar