Modbus é um protocolo de comunicação amplamente utilizado e um padrão de rede industrial de código aberto. Desenvolvido em 1979 pela Modicon (agora Schneider Electric), o Modbus tornou-se um padrão nas indústrias de automação e sistemas de controle industrial (ICS).
O protocolo de comunicação é conhecido por sua simplicidade e recurso de solução de problemas fácil de seguir. Ele usa um modelo de comunicação mestre-escravo ou cliente-servidor, onde um dispositivo mestre ou cliente inicia solicitações para ler ou gravar dados em dispositivos escravos ou servidores.
O protocolo padrão é independente de hardware, o que significa que pode ser implementado em vários dispositivos e plataformas, incluindo diferentes tipos de microcontroladores (incluindo Arduino) e sistemas operacionais. Modbus suporta vários tipos de dados, incluindo entradas discretas, bobinas (saídas digitais), registros de entrada e registros de retenção (dados analógicos). Ele lida com dados analógicos e digitais.
O Modbus tem sido usado de forma confiável em ambientes industriais há décadas para automação, gerenciamento de energia, automação predial, sistemas SCADA, monitoramento agrícola, sistemas de controle de bombas e motores e muito mais. As unidades terminais remotas (RTUs) costumam usá-lo para transmitir dados para um centro de controle central. O Modbus também pode ser facilmente adaptado para requisitos específicos de aplicação ao usar outros protocolos industriais ou padrões de comunicação.
Uma vantagem de usar Modbus no Arduino é sua capacidade de lidar com comunicações de dados complexas em longas distâncias. Por exemplo, o Arduino pode se comunicar com software/aplicativos, interfaces homem-máquina, dispositivos periféricos ou microcontroladores. O Modbus é adequado para aplicações de automação de pequeno e médio porte e ideal para projetos com foco em custos.
Os protocolos Modbus têm três tipos: Modbus ASCII, Modbus RTU e Modbus TCP. Neste artigo, transformaremos o Arduino em um dispositivo Modbus usando Modbus ASCII/RTU e Modbus TCP. Para isso, configuraremos a comunicação entre duas placas Arduino no Modbus.
O que é Modbus?
Modbus é um protocolo popular de comunicação serial aberta e de baixa velocidade, comumente usado na indústria de automação e mantido pela organização Modbus. Serve como um elo entre PLCs e dispositivos de automação inteligentes.
Com a ajuda do protocolo serial, que é baseado em uma configuração mestre-escravo, um cliente Modbus pode estabelecer contato com até 247 servidores Modbus. As portas padrão RS-485 ou RS-232 facilitam a interface física. O barramento inclui um par trançado de cabos, isolados ou não, com ambas as extremidades terminadas em 150 ohms. O cabo pode ser rapidamente conectado aos dispositivos usando conectores RJ-45, terminais de parafuso ou conectores D-shell de 9 pinos.
O cliente Modbus é geralmente um computador supervisor dentro de uma interface homem-máquina (IHM) ou um sistema de controle supervisório e aquisição de dados (SCADA). As unidades terminais remotas (RTU) — como módulos de sensores, controladores lógicos programáveis (PLC) ou controladores de automação programáveis (PAC) — são os servidores Modbus. Para saber mais sobre o protocolo Modbus, confira esse link.
Por que Modbus?
Modbus é um protocolo versátil e confiável. Atualmente é o dispositivo mais utilizado para automação industrial. É o padrão de comunicação para conectar e controlar dispositivos como CLPs, sensores, atuadores e IHMs. Ele também pode coletar dados de medidores de energia, monitorar o consumo de energia e controlar sistemas HVAC (aquecimento, ventilação e ar condicionado). Também pode integrar vários subsistemas prediais, incluindo iluminação, HVAC, segurança e controle de acesso.
O Modus é ideal para aplicações de monitoramento remoto e telemetria, incluindo monitoramento de condições ambientais, níveis de água ou status de equipamentos em locais remotos. Como o protocolo pode lidar com dados analógicos e digitais com eficiência, ele também é ideal para aquisição de dados de sensores e instrumentos em configurações de laboratório, pesquisa e teste.
O protocolo é frequentemente usado como protocolo de comunicação em sistemas SCADA para coletar dados de dispositivos de campo remotos.
O Modbus é versátil e confiável para praticamente qualquer tipo de aplicação de automação, seja ela pequena ou média. Permite comunicação half e full-duplex em longas distâncias. O Modbus RTU pode se estender até 1.200 metros (no RS-485), enquanto o Modbus TCP não tem limite de alcance. O Modbus também permite a comunicação bidirecional entre dispositivos e conecta-se a vários dispositivos em uma rede.
Quando usar Modbus com Arduino?
Se o Arduino precisar fazer interface com um PLC, IHM ou dispositivo periférico, o Modbus é a escolha óbvia. Ele permite que o Arduino se comunique com qualquer microcontrolador ou dispositivo em um alcance estendido.
Aplicações de automação residencial ou de escritório podem se beneficiar do protocolo, pois o protocolo permite que mestre e escravo se comuniquem em ambas as direções.
Protocolos de comunicação típicos como UART, I2C e SPI disponíveis em microcontroladores (incluindo Arduino) têm suas próprias limitações. Quando uma rede se torna muito complexa e vários dispositivos precisam se comunicar bidirecionalmente, o Modbus é o protocolo de comunicação ideal para lidar com essa complexidade sem tornar o circuito ou o código complicados.
Para redes de sensores no Arduino, o Modbus garante novamente uma comunicação confiável, de longo alcance, centralizada e bem gerenciada.
Como funciona o Modbus?
Uma rede Modbus pode ter um ou mais dispositivos mestres e vários dispositivos escravos. O dispositivo mestre é chamado de cliente Modbus e os escravos são servidores Modbus.
Nas versões seriais do Modbus, um dispositivo mestre pode comunicar-se com até 247 dispositivos. A versão Ethernet permite que um mestre se comunique com centenas de dispositivos em um único segmento de rede Ethernet.
A comunicação é baseada em um método de solicitação-resposta. O mestre envia uma solicitação a um ou mais dispositivos escravos, especificando o tipo de operação (leitura ou escrita) e o endereço dos dados que deseja acessar. Os tipos de dados que podem ser lidos ou gravados incluem entradas discretas (dados binários), bobinas (saídas binárias), registros de entrada (dados analógicos) e registros de retenção (dados analógicos).
Cada ponto de dados em uma rede Modbus possui um endereço exclusivo. O mestre especifica o endereço dos dados que deseja acessar na solicitação quando se comunica com um escravo. Por exemplo, um dispositivo Modbus pode ter entradas discretas começando no endereço 1, bobinas começando no endereço 10001, registradores de entrada começando no endereço 30001 e registradores de retenção começando no endereço 40001.
Para uma solicitação Modbus, o tipo de operação é especificado por um código de função. Os códigos de função comuns incluem F01 (Ler entradas discretas), F02 (Ler bobinas), F03 (Ler registros de entrada analógica), F04 (Ler registros de retenção de saída analógica), F05 (Escrever bobina única), F06 (Escrever registro de retenção único), F15 (Escrever Múltiplas Bobinas) e F16 (Escrever Múltiplos Registros de Retenção). Quando um dispositivo escravo recebe uma solicitação válida, ele processa a solicitação e envia uma resposta de volta ao mestre. A resposta contém os dados solicitados ou uma confirmação de uma operação de gravação bem-sucedida. O mestre normalmente pesquisa dispositivos escravos em intervalos regulares para coletar dados ou emitir comandos.
Existem mecanismos de verificação de erros como CRC ou LRC para garantir a integridade dos dados durante a transmissão. A resposta fornece códigos de erro para indicar problemas como solicitações inválidas ou problemas de comunicação. Para saber mais sobre o funcionamento do Modbus, confira esse link.
Modbus RTU/ASCII e Modbus TCP
Existem três tipos populares de Modbus: Modbus RTU, Modbus ASCII e Modbus TCP. Embora Modbus RTU e Modbus ASCII sejam versões de protocolo diferentes, ambos são usados em ambientes de comunicação serial, como RS-232, RS-422 e RS-485.
Modbus RTU é mais comumente associado ao RS-485 devido à sua natureza binária. Muitos dispositivos suportam Modbus ASCII e Modbus RTU. Modbus ASCII e Modbus RTU podem ser implementados com o mesmo hardware no Arduino. No entanto, é importante distinguir entre eles.
- Modbus RTU representa dados em formato binário como valores binários brutos de 8 bits, enquanto para Modbus ASCII, os dados são transmitidos como caracteres ASCII, onde dois caracteres ASCII representam cada byte.
- Os quadros Modbus RTU consistem em dados binários com bits de início e parada para sincronização, enquanto os quadros Modbus ASCII começam com um caractere de dois pontos (“:”) e terminam com uma sequência de retorno de carro e alimentação de linha (“\r\n”).
- O Modbus RTU usa verificação de redundância cíclica (CRC) para detecção de erros no quadro de dados, enquanto o Modbus ASCII usa LRC (verificação de redundância longitudinal) para detecção de erros. O Modbus RTU é comumente usado em aplicações industriais, especialmente em ambientes que exigem comunicação de alta velocidade.
- O Modbus ASCII é preferido onde a comunicação legível ou a solução de problemas são essenciais. Um microcontrolador deve usar Modbus RTU ao se comunicar com módulos sensores. Mas ao se comunicar com dispositivos IHM, o Modbus ASCII é uma solução melhor.
- O Modbus TCP opera em redes Ethernet usando o conjunto de protocolos TCP/IP. Modbus RTU/ASCII são mais adequados para redes seriais ponto a ponto ou multidrop. O Modbus TCP foi projetado para redes locais (LANs) baseadas em Ethernet e pode se comunicar em distâncias mais longas usando equipamento de rede padrão.
- O Modbus TCP usa frames Ethernet padrão, que diferem dos frames de dados do Modbus RTU/ASCII. Ele depende de TCP/IP para transporte confiável de dados. Modbus RTU/ASCII requerem topologias de rede ponto a ponto ou multidrop. O Modbus TCP é bastante flexível e permite topologias de rede como configurações em estrela, barramento ou anel.
- Modbus RTU/ASCII suporta apenas transações únicas. Quando um mestre envia uma solicitação via Modbus RTU/ASCII, ele deve aguardar uma resposta Modbus ou tempo limite antes de enviar outra solicitação. No entanto, o Modbus TCP suporta múltiplas transações, portanto um mestre pode enviar diversas solicitações no Modbus TCP e não precisa esperar por uma resposta ou tempo limite do Modbus. A resposta a uma solicitação é identificada por um ID de transação, onde o ID da transação permanece o mesmo para a solicitação e a resposta.
- Embora o Modbus RTU/ASCII seja comumente usado em sistemas de controle e automação industrial onde a comunicação serial é predominante, o Modbus TCP é mais adequado para redes industriais modernas e automação predial.
Transformando Arduino em um dispositivo Modbus
Se o Arduino precisar se comunicar com um dispositivo PLC ou IHM, é necessário primeiro transformar o Arduino em um dispositivo Modbus. O Arduino pode ser facilmente configurado para participar de redes Modbus RTU/ASCII/TCP. Para fazer isso, são necessários componentes de hardware e software.
Para implementar Modbus RTU/ASCII, o Arduino deve se comunicar pelas portas RS-485, RS-422 ou RS-232. A RS-485 é a porta mais popular para uso. Isso requer a interface do Arduino com um conversor RS-485 para TTL. A biblioteca Arduino Modbus também é necessária.
Para implementar o Modbus TCP, o Arduino deve se comunicar pela pilha TCP/IP. Isso requer um escudo Ethernet sobre Arduino. É necessária a biblioteca Arduino Modbus, que pode ser baixada neste Link do Github.
Conversor RS485 para TTL
Para converter o Arduino em uma rede Modbus RTU/ASCII como mestre ou escravo, é necessário um transceptor RS485 ou um conversor RS485 para TTL. Um desses transceptores baseado no chip MAX485 está na imagem abaixo.
Em um Modbus, um '0' binário é representado por um nível de tensão de +2 a +6V. O binário '1' é representado por um nível de tensão de -2 a -6V. O Arduino opera em níveis lógicos TTL, portanto, é necessário um conversor lógico conforme mostrado acima.
Um transceptor RS485 possui o seguinte diagrama de pinos.
A configuração de pinos do transceptor RS-485 é descrita na tabela abaixo.
Para usar o módulo como transmissor, conecte os pinos RE e DE em 5V e conecte o pino DI ao pino TX do Arduino. Os dados são enviados do pino TX do Arduino para o pino DI do módulo, que é então enviado através do AB.
Para usar o módulo como receptor, conecte os pinos RE e DE ao terra e conecte o pino RO ao pino RX do Arduino. Os dados recebidos pelo AB são enviados para o pino RO, que está conectado ao pino RX do Arduino — assim, os dados são lidos pelo Arduino.
Biblioteca Arduino Modbus
ArduinoModbus é uma biblioteca gratuita e de código aberto para placas Arduino se comunicarem com dispositivos Modbus por meio de conexões seriais (RS485) e de rede (TCP). É baseado na biblioteca libmodbus, mas foi modificado para usar as APIs Arduino Serial/RS485 e Client. É uma API fácil de usar para enviar e receber mensagens Modbus, lidar com enquadramentos Modbus e verificação de erros. Ele também suporta todos os códigos de função Modbus.
A biblioteca é compatível com as arquiteturas megaavr, samd, mbed_nano, mbed_portenta e mbed_opta e pode ser usada em Arduino Uno, Arduino Nano, Arduino Mega, Arduino Due, Arduino MKR Zero, Arduino MKR 1000, Arduino MKR WiFi 1010, Arduino MKR WAN 1310, Arduino MKR FOX 1200, Arduino MKR GSM 1400, Arduino MKR NB 1500, Arduino Portenta H7, Arduino Nano 33 IoT e Arduino Nano RP2040 Connect.
Também pode ser usado em outras placas compatíveis com Arduino, como Genuino M100 e Adafruit Feather M0. A biblioteca pode ser instalada através do gerenciador de biblioteca do Arduino IDE ou baixada neste link do Github.
A biblioteca fornece o seguinte método para configurar o Arduino como cliente Modbus RTU.
modbusRTUClient.begin :
A função inicia o cliente Modbus RTU com os parâmetros especificados. A função retorna '1' em caso de sucesso e '0' em caso de falha. Possui a sintaxe abaixo.
ModbusRTUClient.begin(taxa de transmissão);
ModbusRTUClient.begin(taxa de transmissão, configuração);
A biblioteca fornece os seguintes métodos para configurar o Arduino como um cliente Modbus TCP.
ModbusTCPClient : O método cria um cliente Modbus TCP usando o cliente fornecido para o transporte. O método possui a seguinte sintaxe:
ModbusTCPCliente(cliente);
modbusTCPClient.begin : O método inicia o cliente Modbus TCP com os parâmetros especificados. Tem esta sintaxe:
modbusTCPClient.begin(ip,porta);
modbusTCPClient.connected : O método retorna o status da conexão. Tem esta sintaxe:
modbusTCPClient.connected ;
modbusTCPClient.stop : O método desconecta o servidor. Tem esta sintaxe:
modbusTCPClient.stop ;
A biblioteca fornece o seguinte método para configurar o Arduino como um servidor Modbus RTU.
modbusRTUServer.begin : O método inicia o servidor Modbus RTU com os parâmetros especificados. A função retorna '1' para sucesso ou '0' para falha. Possui a seguinte sintaxe:
ModbusRTUServer.begin(id, taxa de transmissão);
ModbusRTUServer.begin(id, taxa de transmissão, configuração);
A biblioteca fornece os seguintes métodos para configurar o Arduino como um servidor Modbus TCP.
ModbusTCPServer : O método cria um servidor Modbus TCP. Possui a seguinte sintaxe.
ModbusTCPServer ;
modbusTCPServer.begin : O método inicia o servidor Modbus. Pode exigir que o ID do escravo seja passado como argumento. Se nenhum ID for fornecido, o padrão é 0xFF (TCP). Tem esta sintaxe:
modbusTCPserver.begin ;
modbusTCPserver.begin(id);
modbusTCPServer.accept : O método aceita uma conexão de cliente. Tem esta sintaxe:
modbusTCPserver.accept(cliente);
A biblioteca fornece os seguintes métodos para operar como cliente Modbus.
client.coilRead : O método executa uma operação “Read Coils” para o endereço especificado para uma única bobina. Leva ID e/ou endereço do escravo como argumentos. Tem esta sintaxe:
int coilRead (endereço interno);
int coilRead(int id, int endereço);
client.discreteInputRead : O método executa uma operação de “Ler entradas discretas” para o endereço especificado para uma única entrada discreta. Leva ID e/ou endereço do escravo como argumentos. Tem esta sintaxe:
int discreteInputRead(endereço int);
int discreteInputRead(int id, endereço interno);
client.holdingRegisterRead : O método executa uma operação “Ler registros retidos” para um único registro retido. Leva ID e/ou endereço do escravo como argumentos. Tem esta sintaxe:
longa holdingRegisterRead (endereço int);
long holdingRegisterRead (int id, int endereço);
client.inputRegisterRead : O método executa uma operação de “Ler registros de entrada” para um único registro de entrada. Leva ID e/ou endereço do escravo como argumentos. Tem esta sintaxe:
entradaRegisterRead longa (endereço int);
inputRegisterRead longo (int id, endereço interno);
client.coilWrite : O método executa uma operação “Write Single Coil” para o endereço e valor especificados. É necessário o id do escravo alvo, o endereço da operação e o valor da bobina para escrever como argumentos. Tem esta sintaxe:
int coilWrite(endereço int, valor uint8_t);
int coilWrite(int id, endereço int, valor uint8_t);
client.holdingRegisterWrite : O método executa uma operação “Write Single Holding Register” para o endereço e valor especificados. É necessário o ID do escravo alvo, o endereço da operação e o valor do registrador de retenção para escrever como argumentos. Tem esta sintaxe:
int holdingRegisterWrite(endereço int, valor uint16_t);
int holdingRegisterWrite(int id, endereço int, valor uint16_t);
client.registerMaskWrite : O método executa uma operação “Mask Write Registers” para o endereço especificado, máscara AND e máscara OR. Ele leva o ID do escravo de destino, o endereço da operação, a máscara AND para usar na operação e a máscara OR para usar na operação como argumentos. Tem esta sintaxe:
int RegisterMaskWrite(endereço int, uint16_t eMask, uint16_t ouMask);
int RegisterMaskWrite(int id, endereço int, uint16_t andMask, uint16_t orMask);
client.beginTransmission : O método inicia o processo de gravação de múltiplas bobinas ou retenção de registros. Leva o ID do escravo alvo, o tipo de gravação a ser realizada (COILS ou HOLDING_REGISTERS), o endereço da operação e a quantidade de valores a serem escritos como argumentos. Tem esta sintaxe:
int startTransmission(tipo int, endereço int, int nb);
int startTransmission(int id, int tipo, int endereço, int nb);
client.write : O método define os valores de uma operação de gravação iniciada por beginTransmission . É preciso valor para escrever como um argumento. O método retorna '1' em caso de sucesso ou '0' em caso de falha. Tem esta sintaxe:
gravação int (valor int não assinado);
client.endTransmission : O método encerra o processo de gravação de múltiplas bobinas ou retenção de registros. Ele retorna '1' em caso de sucesso ou '0' em caso de falha. Tem esta sintaxe:
int endTransmission ;
client.requestFrom : O método lê múltiplas bobinas, entradas discretas, registros de retenção ou valores de registro de entrada. Ele usa available e read para processar os valores lidos. Ele leva o ID do escravo alvo, o tipo de leitura a ser executada (COILS, DISCRETE_INPUTS, HOLDING_REGISTERS ou INPUT_REGISTERS), o endereço inicial a ser usado para operação e o número de valores a serem lidos como argumentos. Tem esta sintaxe:
int requestFrom(tipo int, endereço int, int nb);
int requestFrom(int id, int tipo, int endereço,int nb);
client.available : O método consulta o número de valores disponíveis para leitura após chamar requestFrom . Possui a seguinte sintaxe.
int disponível ;
client.read : O método lê um valor após chamar requestFrom . Ele retorna -1 em caso de falha e um valor em caso de sucesso. Tem esta sintaxe:
leitura longa ;
client.lastError : O método lê o motivo do último erro como uma string. Tem esta sintaxe:
const char* últimoErro ;
client.end : O método interrompe o cliente e realiza a limpeza. Tem esta sintaxe:
final vazio ;
A biblioteca fornece os seguintes métodos para operar como um servidor Modbus.
modbusServer.configureCoils : O método configura as bobinas do servidor. É necessário o endereço inicial das bobinas e o número de bobinas para configurar como argumentos. Possui a seguinte sintaxe:
int configureCoils(int startAddress, int nb);
modbusServer.configureDiscreteInputs : O método configura as entradas discretas do servidor. Ele retorna '0' em caso de sucesso ou '1' em caso de falha. É necessário o início do endereço das entradas discretas e o número de entradas discretas para configurar como argumentos. Tem esta sintaxe:
int configureDiscreteInputs(int startAddress, int nb);
modbusServer.configureHoldingRegisters : O método configura os registros de retenção do servidor. É necessário o início do endereço dos registradores de retenção e o número de registradores de retenção para configurar como argumentos. Tem esta sintaxe:
int configureHoldingRegisters(int startAddress, int nb);
modbusServer.configureInputRegisters : O método configura os registros de entrada do servidor. É necessário o início do endereço dos registradores de entrada e o número de registradores de entrada para configurar como argumentos. Tem esta sintaxe:
int configureInputRegisters(int startAddress, int nb);
modbusServer.coilRead : O método executa uma operação “Read Coils” para o endereço especificado para uma única bobina. É necessário o ID do escravo alvo e/ou endereço para usar na operação como argumentos. Tem esta sintaxe:
int coilRead (endereço interno);
int coilRead(int id, int endereço);
modbusServer.discreteInputRead : O método executa uma operação de “Ler entradas discretas” para o endereço especificado para uma única entrada discreta. É necessário o ID do escravo alvo e/ou endereço para usar na operação como argumentos. Tem esta sintaxe:
int discreteInputRead(endereço int);
int discreteInputRead(int id, endereço interno);
modbusServer.holdingRegisterRead : O método executa uma operação “Ler registros retidos” para um único registro retido. Leva o ID do escravo alvo e o início do endereço para usar na operação como argumentos. Tem esta sintaxe:
longa holdingRegisterRead (endereço int);
long holdingRegisterRead (int id, int endereço);
modbusServer.inputRegisterRead : O método executa uma operação de “Ler registros de entrada” para um único registro de entrada. É necessário o ID do escravo alvo e o endereço para usar na operação como argumentos. Tem esta sintaxe:
entradaRegisterRead longa (endereço int);
inputRegisterRead longo (int id, endereço interno);
modbusServer.coilWrite : O método executa uma operação “Write Single Coil” para o endereço e valor especificados. É necessário o ID do escravo alvo, o endereço a ser usado para operação e o valor da bobina para escrever como argumentos. Tem esta sintaxe:
int coilWrite(endereço int, valor uint8_t);
int coilWrite(int id, endereço int, valor uint8_t);
modbusServer.holdingRegisterWrite : O método executa uma operação “Write Single Holding Register” para o endereço e valor especificados. É necessário o ID do escravo alvo, o endereço a ser usado para operação e o valor do registrador de retenção para escrever como argumentos. Tem esta sintaxe:
int holdingRegisterWrite(endereço int, valor uint16_t);
int holdingRegisterWrite(int id, endereço int, valor uint16_t);
modbusServer.registerMaskWrite : O método executa uma operação “Mask Write Registers” para o endereço especificado, máscara AND e máscara OR. Ele leva o ID do escravo de destino, o endereço a ser usado para operação, a máscara AND a ser usada para operação e a máscara OR AND a ser usada para operação como argumentos. Tem esta sintaxe:
int RegisterMaskWrite(endereço int, uint16_t eMask, uint16_t ouMask);
int registerMaskWrite(int id, endereço int, uint16_t andMask, uint16_t orMask);
modbusServer.discreteInputWrite : O método grava o valor da entrada discreta do servidor para o endereço e valor especificados. É necessário um endereço para usar na operação e um valor discreto para escrever como argumentos. Tem esta sintaxe:
int discreteInputWrite(endereço int, valor uint8_t);
modbusServer.writeDiscreteInputs : O método grava valores nas entradas discretas do servidor para o endereço e valores especificados. É necessário o endereço a ser usado para operação, a matriz de valores de entrada discreta a serem escritos e o número de entradas discretas a serem escritas como argumentos. Tem esta sintaxe:
int writeDiscreteInputs(endereço int, valores uint8_t , int nb);
modbusServer.inputRegisterWrite : O método grava o valor do registro de entrada do servidor para o endereço e valor especificados. É necessário o endereço a ser usado para operação e o valor do registro de entrada para escrever como argumentos. Tem esta sintaxe:
int inputRegisterWrite (endereço int, valor uint16_t);
modbusServer.writeInputRegisters : O método grava valores nos registros de entrada do servidor para o endereço e valores especificados. É necessário o endereço a ser usado para operação, a matriz dos valores dos registradores de entrada a serem gravados e o número de registradores de entrada a serem gravados como argumentos. Tem esta sintaxe:
int writeInputRegisters(endereço int, valores uint16_t , int nb);
modbusServer.poll : O método pesquisa solicitações. Possui a seguinte sintaxe:
enquete de vazio virtual = 0;
modbusServer.end : O método para o servidor. Possui a seguinte sintaxe:
final vazio ;
Exemplo de Arduino Modbus RTU
Para configurar a comunicação entre duas placas Arduino usando Modbus RTU e a biblioteca Arduino Modbus, primeiro conecte as duas placas Arduino usando um transceptor RS485. Você precisará de um par de transceptores RS485 – um para configurar um Arduino como cliente Modbus e outro para configurar outro Arduino como servidor Modbus.
- Para configurar a primeira placa Arduino como transmissor Modbus, conecte os pinos RE e DE do módulo em 5V e conecte o pino DI do módulo ao pino TX do Arduino.
- Para configurar a outra placa Arduino como receptor Modbus, conecte os pinos RE e DE do módulo ao terra e conecte o pino RO do módulo ao pino RX do Arduino.
- Em seguida, conecte os pinos 5V e terra de ambos os módulos com a saída 5V e GND do(s) respectivo(s) Arduino(s). Em seguida, conecte os pinos de dados B e dados A de um módulo aos pinos de dados B e dados A do outro módulo.
As conexões do circuito são mostradas abaixo.
Carregue o seguinte esboço para o Arduino configurado como transmissor Modbus.
#incluir “ArduinoModbus.h”
Mestre ArduinoModbus;
configuração vazia {
Serial.begin(9600);
master.begin ;
}
loop vazio {
// Envia uma solicitação de leitura Modbus para o endereço escravo 1 e lê 10 registros começando no endereço de registro 0
resposta interna = master.read(1, 0, 10);
//Verifica a resposta
if (resposta == 0) {
// A solicitação foi bem-sucedida, obtém os valores lidos do buffer de resposta
valores uint16_t(10);
master.getResponseBuffer(valores, 10);
// Faça algo com os valores lidos
Serial.println(“Ler valores:”);
for (int i = 0; i < 10; i++) {
Serial.print(valores(i));
Serial.print(” “);
}
Serial.println ;
}
outro {
//A solicitação falhou
Serial.println(“Falha na solicitação de leitura”);
}
//Aguarde 1 segundo antes de enviar a próxima solicitação
atraso(1000);
}
Carregue o seguinte esboço para o Arduino configurado como receptor Modbus.
#incluir “ArduinoModbus.h”
Escravo ArduinoModbus(1);
configuração vazia {
//Configura a comunicação serial
Serial.begin(9600);
// Inicializa o escravo Modbus
escravo.begin ;
}
loop vazio {
// Verifica solicitações Modbus recebidas
solicitação int = escravo.disponível ;
//Se houver uma solicitação, processe-a
if (solicitação > 0) {
// Obtém o tipo de solicitação
tipo de byte = escravo.getRequestType(solicitação);
// Se a solicitação for uma solicitação de leitura, envia os valores lidos para o mestre
if (tipo == MODBUS_READ) {
// Obtém o endereço do registro e o número de registros para ler
endereço da palavra = escravo.getRequestAddress (solicitação);
contagem de bytes = escravo.getRequestCount (solicitação);
//Lê os registradores da memória do Arduino
valores uint16_t (contagem);
for (int i = 0; i < contagem; i++) {
valores (i) = escravo.readRegister (endereço + i);
}
// Envia os valores lidos para o mestre
slave.sendResponse(solicitação, valores, contagem);
}
}
}
Você pode observar os valores transmitidos entre dois Arduino(s) no Serial Monitor do Arduino IDE conectando qualquer um dos Arduino a um computador.
Exemplo de Arduino Modbus TCP
Para configurar a comunicação entre as duas placas Arduino usando o Modbus TCP e a biblioteca Arduino Modbus, instale escudos Ethernet nas duas placas e conecte ambos os Arduinos à mesma rede através dos cabos Ethernet ou de uma conexão WiFi.
Carregue o seguinte esboço para o Arduino configurado como um transmissor Modbus.
#incluir “ArduinoModbus.h”
Mestre ArduinoModbus;
configuração vazia {
//Configura a comunicação serial
Serial.begin(9600);
// Conecte-se à placa Arduino escrava no endereço IP da sua rede
master.connect(“IP_ADDRESS”);
}
loop vazio {
// Envia uma solicitação de leitura Modbus para o endereço escravo 1 e lê 10 registros começando no endereço de registro 0
resposta interna = master.read(1, 0, 10);
//Verifica a resposta
if (resposta == 0) {
//A solicitação foi bem sucedida
// Obtém os valores lidos do buffer de resposta
valores uint16_t(10);
master.getResponseBuffer(valores, 10);
// Faça algo com os valores lidos
Serial.println(“Ler valores:”);
for (int i = 0; i < 10; i++) {
Serial.print(valores(i));
Serial.print(” “);
}
Serial.println ;
} outro {
//A solicitação falhou
Serial.println(“Falha na solicitação de leitura”);
}
//Aguarde 1 segundo antes de enviar a próxima solicitação
atraso(1000);
}
Carregue o seguinte esboço para o Arduino configurado como um receptor Modbus.
#incluir “ArduinoModbus.h”
Escravo ArduinoModbus(1);
configuração vazia {
//Configura a comunicação serial
Serial.begin(9600);
//Inicia o servidor Modbus
escravo.beginServer ;
}
loop vazio {
// Verifica solicitações Modbus recebidas
solicitação int = escravo.disponível ;
//Se houver uma solicitação, processe-a
if (solicitação > 0) {
// Obtém o tipo de solicitação
tipo de byte = escravo.getRequestType(solicitação);
// Se a solicitação for uma solicitação de leitura, envia os valores lidos para o mestre
if (tipo == MODBUS_READ) {
// Obtém o endereço do registro e o número de registros para ler
endereço da palavra = escravo.getRequestAddress (solicitação);
contagem de bytes = escravo.getRequestCount (solicitação);
//Lê os registradores da memória do Arduino
valores uint16_t (contagem);
for (int i = 0; i < contagem; i++) {
valores (i) = escravo.readRegister (endereço + i);
}
// Envia os valores lidos para o mestre
slave.sendResponse(solicitação, valores, contagem);
}
}
}
Você pode observar os valores transmitidos entre as duas placas Arduino no Serial Monitor do Arduino IDE conectando qualquer uma das placas a um computador.