modbus — Protocolo esclavo Modbus RTU#

Este módulo proporciona una implementación en Python puro de un esclavo Modbus RTU que se comunica a través de un UART. Mantiene un array interno de registros de retención y responde a los códigos de función Modbus estándar 0x03 (Read Holding Registers), 0x06 (Write Single Register) y 0x10 (Write Multiple Registers). El CRC-16 (polinomio Modbus) se calcula mediante una tabla de búsqueda.

Por ejemplo:

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#

Un esclavo Modbus RTU que lee solicitudes desde un UART, actualiza su array interno de registros y escribe la respuesta correspondiente de vuelta al UART.

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

Construye un esclavo ModbusRTU.

  • uart es una instancia de UART (p. ej. machine.UART o pyb.UART) utilizada para enviar y recibir fotogramas Modbus. El UART debe configurarse con la velocidad en baudios, la paridad y los tiempos de espera adecuados antes de pasarlo.

  • slave_id es la dirección de esclavo Modbus (1-247) a la que responderá esta instancia. Los fotogramas dirigidos a otros IDs de esclavo se ignoran.

  • register_num es el número de registros de retención de 16 bits que respaldan a este esclavo. Los registros se almacenan en la lista REGISTER y se inicializan a cero.

SLAVE_ID: int#

La dirección de esclavo Modbus a la que responderá esta instancia. Se establece a partir del argumento del constructor slave_id.

uart: machine.UART#

La instancia de UART pasada al constructor, utilizada para todas las operaciones de E/S.

register_num: int#

El número de registros de retención de 16 bits, establecido a partir del argumento del constructor register_num.

REGISTER: list[int]#

Lista de longitud register_num que contiene los valores actuales de los registros de 16 bits. Las lecturas y escrituras realizadas mediante solicitudes Modbus entrantes actualizan esta lista. El código de la aplicación puede leer o escribir directamente en esta lista para intercambiar datos con el maestro Modbus.

CRC16_TABLE: list[int]#

Tabla de búsqueda precalculada de 256 entradas para el polinomio CRC-16 de Modbus, utilizada por crc16().

any() int#

Devuelve el número de bytes disponibles actualmente en el búfer de recepción del UART subyacente (delega en uart.any()). Úsalo para comprobar si hay una solicitud entrante antes de llamar a handle().

clear() None#

Restablece cada entrada de REGISTER a 0.

crc16(data: bytes | bytearray) bytes#

Calcula el CRC-16 de Modbus de data usando CRC16_TABLE y lo devuelve como un objeto bytes little-endian de 2 bytes adecuado para añadirlo a un fotograma Modbus.

  • data es un bytes/bytearray (o cualquier iterable de enteros) que contiene los bytes a los que aplicar la suma de comprobación.

handle(debug: bool = False) None#

Lee una única solicitud Modbus desde el UART, actualiza el array interno de registros según sea necesario y escribe la respuesta correspondiente de vuelta al UART.

Códigos de función admitidos:

  • 0x03 Read Holding Registers — responde con el rango solicitado de valores de registro.

  • 0x06 Write Single Register — escribe un único registro y devuelve como eco la dirección y el valor.

  • 0x10 Write Multiple Registers — escribe un rango contiguo de registros y responde con la dirección inicial y la cantidad.

Se devuelven respuestas de excepción Modbus para:

  • Illegal Function (0x01) — código de función no admitido.

  • Illegal Data Address (0x02) — índice de registro fuera de rango.

  • Illegal Data Value (0x03) — el número de bytes no coincide con la cantidad declarada de registros.

Los fotogramas cuyo CRC no coincide o cuya dirección de esclavo no coincide con SLAVE_ID se descartan silenciosamente.

  • debug si es True, imprime la solicitud sin procesar, el código de función analizado, la respuesta generada y cualquier detalle de error en el REPL. El valor predeterminado es False.