modbus — Protocole esclave Modbus RTU

Ce module fournit une implémentation purement Python d’un esclave Modbus RTU qui communique via un UART. Il maintient un tableau interne de registres de maintien et répond aux codes de fonction Modbus standard 0x03 (lecture de registres de maintien), 0x06 (écriture d’un registre unique) et 0x10 (écriture de plusieurs registres). Le CRC-16 (polynôme Modbus) est calculé à l’aide d’une table de correspondance.

Par exemple

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)

classe ModbusRTU

Un esclave Modbus RTU qui lit les requêtes depuis un UART, met à jour son tableau interne de registres et réécrit la réponse correspondante sur l’UART.

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

Construit un esclave ModbusRTU.

  • uart est une instance UART (par exemple machine.UART ou pyb.UART) utilisée pour envoyer et recevoir les trames Modbus. L’UART doit être configuré avec un débit en bauds, une parité et des délais d’attente appropriés avant d’être passé.

  • slave_id est l’adresse de l’esclave Modbus (1-247) à laquelle cette instance répondra. Les trames adressées à d’autres identifiants d’esclave sont ignorées.

  • register_num est le nombre de registres de maintien 16 bits sous-jacents à cet esclave. Les registres sont stockés dans la liste REGISTER et initialisés à zéro.

SLAVE_ID: int

L’adresse de l’esclave Modbus à laquelle cette instance répondra. Définie à partir de l’argument slave_id du constructeur.

uart: machine.UART

L’instance UART passée au constructeur, utilisée pour toutes les entrées/sorties.

register_num: int

Le nombre de registres de maintien 16 bits, défini à partir de l’argument register_num du constructeur.

REGISTER: list[int]

Liste de longueur register_num contenant les valeurs actuelles des registres 16 bits. Les lectures et écritures effectuées via les requêtes Modbus entrantes mettent à jour cette liste. Le code de l’application peut lire ou écrire directement dans cette liste pour échanger des données avec le maître Modbus.

CRC16_TABLE: list[int]

Table de correspondance précalculée de 256 entrées pour le polynôme CRC-16 de Modbus, utilisée par crc16().

any() int

Renvoie le nombre d’octets actuellement disponibles dans le tampon de réception de l’UART sous-jacent (délègue à uart.any()). Utilisez cette méthode pour vérifier la présence d’une requête entrante avant d’appeler handle().

clear() None

Réinitialise chaque entrée de REGISTER à 0.

crc16(data: bytes | bytearray) bytes

Calcule le CRC-16 Modbus de data à l’aide de CRC16_TABLE et le renvoie sous forme d’objet bytes de 2 octets en petit-boutiste (little-endian), prêt à être ajouté à une trame Modbus.

  • data est un bytes/bytearray (ou tout itérable d’entiers) contenant les octets à vérifier.

handle(debug: bool = False) None

Lit une seule requête Modbus depuis l’UART, met à jour le tableau interne de registres selon les besoins et réécrit la réponse correspondante sur l’UART.

Codes de fonction pris en charge :

  • 0x03 Read Holding Registers — répond avec la plage demandée de valeurs de registres.

  • 0x06 Write Single Register — écrit un seul registre et renvoie en écho l’adresse et la valeur.

  • 0x10 Write Multiple Registers — écrit une plage contiguë de registres et répond avec l’adresse de départ et le nombre.

Des réponses d’exception Modbus sont renvoyées pour :

  • Illegal Function (0x01) — code de fonction non pris en charge.

  • Illegal Data Address (0x02) — indice de registre hors plage.

  • Illegal Data Value (0x03) — le nombre d’octets ne correspond pas à la quantité de registres déclarée.

Les trames dont le CRC ne correspond pas ou dont l’adresse d’esclave ne correspond pas à SLAVE_ID sont ignorées silencieusement.

  • debug si True, affiche la requête brute, le code de fonction analysé, la réponse générée et tous les détails d’erreur sur le REPL. La valeur par défaut est False.