modbus — Protocolo escravo Modbus RTU

Este módulo fornece uma implementação em Python puro de um escravo Modbus RTU que se comunica por uma UART. Ele mantém um array interno de registradores de retenção (holding registers) e responde aos códigos de função Modbus padrão 0x03 (Read Holding Registers), 0x06 (Write Single Register) e 0x10 (Write Multiple Registers). O CRC-16 (polinômio Modbus) é calculado usando uma tabela de consulta.

Por exemplo:

from machine import UART
from modbus import ModbusRTU

uart = UART(1, 115200, timeout=10, timeout_char=10)
modbus = ModbusRTU(uart, slave_id=0x01, register_num=30)

while True:
    if modbus.any():
        modbus.handle(debug=False)

class ModbusRTU

Um escravo Modbus RTU que lê requisições de uma UART, atualiza seu array interno de registradores e escreve a resposta correspondente de volta na UART.

class modbus.ModbusRTU(uart: machine.UART, slave_id: int = 0x01, register_num: int = 30)

Constrói um escravo ModbusRTU.

  • uart é uma instância de UART (por exemplo, machine.UART ou pyb.UART) usada para enviar e receber quadros Modbus. A UART deve ser configurada com taxa de transmissão (baud rate), paridade e timeouts apropriados antes de ser passada.

  • slave_id é o endereço de escravo Modbus (1-247) ao qual esta instância responderá. Quadros endereçados a outros IDs de escravo são ignorados.

  • register_num é o número de registradores de retenção de 16 bits que respaldam este escravo. Os registradores são armazenados na lista REGISTER e inicializados em zero.

SLAVE_ID: int

O endereço de escravo Modbus ao qual esta instância responderá. Definido a partir do argumento slave_id do construtor.

uart: machine.UART

A instância de UART passada ao construtor, usada para toda a E/S.

register_num: int

O número de registradores de retenção de 16 bits, definido a partir do argumento register_num do construtor.

REGISTER: list[int]

Lista de comprimento register_num que mantém os valores atuais dos registradores de 16 bits. Leituras e escritas realizadas por requisições Modbus recebidas atualizam esta lista. O código da aplicação pode ler ou escrever diretamente nesta lista para trocar dados com o mestre Modbus.

CRC16_TABLE: list[int]

Tabela de consulta de 256 entradas pré-computada para o polinômio CRC-16 do Modbus, usada por crc16().

any() int

Retorna o número de bytes atualmente disponíveis no buffer de recepção da UART subjacente (delega para uart.any()). Use isto para verificar se há uma requisição recebida antes de chamar handle().

clear() None

Reinicia todas as entradas em REGISTER para 0.

crc16(data: bytes | bytearray) bytes

Calcula o CRC-16 Modbus de data usando CRC16_TABLE e o retorna como um objeto bytes little-endian de 2 bytes adequado para anexar a um quadro Modbus.

  • data é um bytes/bytearray (ou qualquer iterável de inteiros) contendo os bytes a serem somados na verificação.

handle(debug: bool = False) None

Lê uma única requisição Modbus da UART, atualiza o array interno de registradores conforme necessário e escreve a resposta correspondente de volta na UART.

Códigos de função suportados:

  • 0x03 Read Holding Registers — responde com o intervalo solicitado de valores de registradores.

  • 0x06 Write Single Register — escreve um único registrador e ecoa o endereço e o valor.

  • 0x10 Write Multiple Registers — escreve um intervalo contíguo de registradores e responde com o endereço inicial e a contagem.

Respostas de exceção Modbus são retornadas para:

  • Illegal Function (0x01) — código de função não suportado.

  • Illegal Data Address (0x02) — índice de registrador fora do intervalo.

  • Illegal Data Value (0x03) — a contagem de bytes não corresponde à quantidade declarada de registradores.

Quadros cujo CRC não corresponde ou cujo endereço de escravo não corresponde a SLAVE_ID são silenciosamente descartados.

  • debug se True, imprime no REPL a requisição bruta, o código de função interpretado, a resposta gerada e quaisquer detalhes de erro. O padrão é False.