modbus — Protokół slave Modbus RTU

Moduł ten dostarcza czysto pythonową implementację urządzenia slave Modbus RTU, które komunikuje się przez UART. Utrzymuje wewnętrzną tablicę rejestrów holding i odpowiada na standardowe kody funkcji Modbus 0x03 (Read Holding Registers), 0x06 (Write Single Register) oraz 0x10 (Write Multiple Registers). CRC-16 (wielomian Modbus) jest obliczany przy użyciu tablicy przeglądowej.

Na przykład:

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)

klasa ModbusRTU

Urządzenie slave Modbus RTU, które odczytuje żądania z UART, aktualizuje swoją wewnętrzną tablicę rejestrów i odsyła odpowiednią odpowiedź z powrotem do UART.

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

Konstruuje urządzenie slave ModbusRTU.

  • uart to instancja UART (np. machine.UART lub pyb.UART) używana do wysyłania i odbierania ramek Modbus. UART musi zostać skonfigurowany z odpowiednią szybkością transmisji (baud), parzystością i limitami czasu przed jego przekazaniem.

  • slave_id to adres slave Modbus (1-247), na który ta instancja będzie odpowiadać. Ramki adresowane do innych identyfikatorów slave są ignorowane.

  • register_num to liczba 16-bitowych rejestrów holding obsługiwanych przez to urządzenie slave. Rejestry są przechowywane na liście REGISTER i inicjalizowane wartością zero.

SLAVE_ID: int

Adres slave Modbus, na który ta instancja będzie odpowiadać. Ustawiany z argumentu konstruktora slave_id.

uart: machine.UART

Instancja UART przekazana do konstruktora, używana do całej komunikacji we/wy.

register_num: int

Liczba 16-bitowych rejestrów holding, ustawiana z argumentu konstruktora register_num.

REGISTER: list[int]

Lista o długości register_num przechowująca bieżące 16-bitowe wartości rejestrów. Odczyty i zapisy wykonywane poprzez przychodzące żądania Modbus aktualizują tę listę. Kod aplikacji może bezpośrednio odczytywać z tej listy lub zapisywać do niej, aby wymieniać dane z masterem Modbus.

CRC16_TABLE: list[int]

Wstępnie obliczona tablica przeglądowa o 256 wpisach dla wielomianu CRC-16 Modbus, używana przez crc16().

any() int

Zwraca liczbę bajtów aktualnie dostępnych w buforze odbiorczym bazowego UART (deleguje do uart.any()). Użyj tego, aby sprawdzić obecność przychodzącego żądania przed wywołaniem handle().

clear() None

Resetuje każdy wpis w REGISTER do wartości 0.

crc16(data: bytes | bytearray) bytes

Oblicza CRC-16 Modbus dla data przy użyciu CRC16_TABLE i zwraca je jako 2-bajtowy obiekt bytes w kolejności little-endian, odpowiedni do dołączenia do ramki Modbus.

  • data to obiekt bytes/bytearray (lub dowolny iterowalny obiekt liczb całkowitych) zawierający bajty do obliczenia sumy kontrolnej.

handle(debug: bool = False) None

Odczytuje pojedyncze żądanie Modbus z UART, w razie potrzeby aktualizuje wewnętrzną tablicę rejestrów i odsyła odpowiednią odpowiedź z powrotem do UART.

Obsługiwane kody funkcji:

  • 0x03 Read Holding Registers — odpowiada żądanym zakresem wartości rejestrów.

  • 0x06 Write Single Register — zapisuje pojedynczy rejestr i odsyła echo adresu oraz wartości.

  • 0x10 Write Multiple Registers — zapisuje ciągły zakres rejestrów i odpowiada adresem początkowym oraz liczbą.

Odpowiedzi wyjątkowe Modbus są zwracane dla:

  • Illegal Function (0x01) — nieobsługiwany kod funkcji.

  • Illegal Data Address (0x02) — indeks rejestru poza zakresem.

  • Illegal Data Value (0x03) — liczba bajtów nie odpowiada zadeklarowanej liczbie rejestrów.

Ramki, których CRC się nie zgadza lub których adres slave nie odpowiada SLAVE_ID, są po cichu odrzucane.

  • debug jeśli ma wartość True, wypisuje surowe żądanie, sparsowany kod funkcji, wygenerowaną odpowiedź oraz wszelkie szczegóły błędów do REPL. Domyślnie False.