modbus — Protocollo slave Modbus RTU

Questo modulo fornisce un’implementazione in puro Python di uno slave Modbus RTU che comunica tramite una UART. Mantiene un array interno di holding register e risponde ai codici funzione Modbus standard 0x03 (Read Holding Registers), 0x06 (Write Single Register) e 0x10 (Write Multiple Registers). Il CRC-16 (polinomio Modbus) viene calcolato usando una lookup table.

Ad esempio:

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

Uno slave Modbus RTU che legge le richieste da una UART, aggiorna il proprio array interno di registri e riscrive la risposta corrispondente sulla UART.

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

Costruisce uno slave ModbusRTU.

  • uart è un’istanza UART (ad es. machine.UART o pyb.UART) usata per inviare e ricevere frame Modbus. La UART deve essere configurata con baud rate, parità e timeout appropriati prima di essere passata.

  • slave_id è l’indirizzo dello slave Modbus (1-247) a cui questa istanza risponderà. I frame indirizzati ad altri ID slave vengono ignorati.

  • register_num è il numero di holding register a 16 bit che supportano questo slave. I registri sono memorizzati nella lista REGISTER e inizializzati a zero.

SLAVE_ID: int

L’indirizzo dello slave Modbus a cui questa istanza risponderà. Impostato dall’argomento del costruttore slave_id.

uart: machine.UART

L’istanza UART passata al costruttore, usata per tutto l’I/O.

register_num: int

Il numero di holding register a 16 bit, impostato dall’argomento del costruttore register_num.

REGISTER: list[int]

Lista di lunghezza register_num che contiene i valori correnti dei registri a 16 bit. Le letture e le scritture eseguite tramite richieste Modbus in arrivo aggiornano questa lista. Il codice applicativo può leggere o scrivere direttamente da questa lista per scambiare dati con il master Modbus.

CRC16_TABLE: list[int]

Lookup table precalcolata di 256 voci per il polinomio Modbus CRC-16, usata da crc16().

any() int

Restituisce il numero di byte attualmente disponibili nel buffer di ricezione della UART sottostante (delega a uart.any()). Usalo per verificare la presenza di una richiesta in arrivo prima di chiamare handle().

clear() None

Reimposta ogni voce di REGISTER a 0.

crc16(data: bytes | bytearray) bytes

Calcola il CRC-16 Modbus di data usando CRC16_TABLE e lo restituisce come oggetto bytes little-endian di 2 byte adatto per essere accodato a un frame Modbus.

  • data è un oggetto bytes/bytearray (o qualsiasi iterabile di interi) contenente i byte di cui calcolare il checksum.

handle(debug: bool = False) None

Legge una singola richiesta Modbus dalla UART, aggiorna l’array interno dei registri come richiesto e riscrive la risposta corrispondente sulla UART.

Codici funzione supportati:

  • 0x03 Read Holding Registers — risponde con l’intervallo richiesto di valori dei registri.

  • 0x06 Write Single Register — scrive un singolo registro e restituisce in eco l’indirizzo e il valore.

  • 0x10 Write Multiple Registers — scrive un intervallo contiguo di registri e risponde con l’indirizzo iniziale e il conteggio.

Le risposte di eccezione Modbus vengono restituite per:

  • Illegal Function (0x01) — codice funzione non supportato.

  • Illegal Data Address (0x02) — indice di registro fuori intervallo.

  • Illegal Data Value (0x03) — il conteggio dei byte non corrisponde alla quantità dichiarata di registri.

I frame il cui CRC non corrisponde o il cui indirizzo slave non corrisponde a SLAVE_ID vengono scartati silenziosamente.

  • debug se True, stampa sulla REPL la richiesta grezza, il codice funzione analizzato, la risposta generata e gli eventuali dettagli degli errori. Il valore predefinito è False.