modbus — Modbus RTU slave protocol

Цей модуль надає реалізацію на чистому Python підлеглого пристрою Modbus RTU, що комунікує через UART. Він підтримує внутрішній масив регістрів зберігання та відповідає на стандартні функціональні коди Modbus: 0x03 (читання регістрів зберігання), 0x06 (запис одного регістра) та 0x10 (запис кількох регістрів). CRC-16 (поліном Modbus) обчислюється за допомогою таблиці підстановки.

Наприклад:

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

Підлеглий пристрій Modbus RTU, що зчитує запити з UART, оновлює внутрішній масив регістрів і записує відповідну відповідь назад у UART.

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

Конструює підлеглий пристрій ModbusRTU.

  • uart — екземпляр UART (наприклад, machine.UART або pyb.UART), що використовується для надсилання та отримання кадрів Modbus. UART повинен бути налаштований з відповідною швидкістю передачі (бод), парністю та тайм-аутами перед передачею.

  • slave_id — адреса підлеглого пристрою Modbus (1-247), на яку відповідає цей екземпляр. Кадри, адресовані іншим ідентифікаторам підлеглих пристроїв, ігноруються.

  • register_num — кількість 16-бітних регістрів зберігання для цього підлеглого пристрою. Регістри зберігаються у списку REGISTER та ініціалізуються нулями.

SLAVE_ID: int

Адреса підлеглого пристрою Modbus, на яку відповідає цей екземпляр. Встановлюється з аргументу конструктора slave_id.

uart: machine.UART

Екземпляр UART, переданий конструктору, що використовується для всіх операцій введення/виведення.

register_num: int

Кількість 16-бітних регістрів зберігання, встановлена з аргументу конструктора register_num.

REGISTER: list[int]

Список довжиною register_num, що містить поточні 16-бітні значення регістрів. Читання та записи, що виконуються через вхідні запити Modbus, оновлюють цей список. Код застосунку може безпосередньо читати з цього списку або записувати до нього для обміну даними з майстром Modbus.

CRC16_TABLE: list[int]

Попередньо обчислена таблиця підстановки з 256 записів для полінома Modbus CRC-16, що використовується crc16().

any() int

Повертає кількість байтів, що наразі доступні у буфері прийому базового UART (делегує до uart.any()). Використовуйте це для перевірки наявності вхідного запиту перед викликом handle().

clear() None

Скидає кожен запис у REGISTER до 0.

crc16(data: bytes | bytearray) bytes

Обчислює Modbus CRC-16 для data за допомогою CRC16_TABLE і повертає його як 2-байтний об’єкт bytes у форматі little-endian, придатний для додавання до кадру Modbus.

  • data — об’єкт bytes/bytearray (або будь-який ітерований об’єкт цілих чисел), що містить байти для обчислення контрольної суми.

handle(debug: bool = False) None

Зчитує один запит Modbus з UART, при необхідності оновлює внутрішній масив регістрів і записує відповідну відповідь назад у UART.

Підтримувані функціональні коди:

  • 0x03 Read Holding Registers — відповідає із запитаним діапазоном значень регістрів.

  • 0x06 Write Single Register — записує один регістр і повертає назад адресу та значення.

  • 0x10 Write Multiple Registers — записує суміжний діапазон регістрів і відповідає початковою адресою та кількістю.

Виняткові відповіді Modbus повертаються для:

  • Illegal Function (0x01) — непідтримуваний функціональний код.

  • Illegal Data Address (0x02) — індекс регістра виходить за межі діапазону.

  • Illegal Data Value (0x03) — кількість байтів не відповідає заявленій кількості регістрів.

Кадри, чий CRC не збігається або чия адреса підлеглого пристрою не відповідає SLAVE_ID, мовчки відкидаються.

  • debug якщо True, виводить до REPL необроблений запит, розібраний функціональний код, згенеровану відповідь та будь-які деталі помилок. За замовчуванням False.