MaixCAM MaixPy 使用 Modbus 协议

MaixPy 适配了 modbus 协议, 其底层是 libmodbus.

在 MaixPy 上使用 modbus 协议非常简单, 您只需要知道:

  • 当您使用 modbus.Slave 时, MaixCAM(Pro) 就是一个从设备(比如说作为传感器模块), 控制该模块的就是一个主机(比如说您的MCU/PC), 您的主机只需要像读写芯片寄存器一样从从设备读写寄存器即可.

  • 您可以简单理解为:

    对主机来说, coils 是可读可写寄存器组, 存储一组布尔值; discrete input 是可读不可写寄存器组, 存储一组布尔值; input registers 是可读不可写寄存器组, 存储一组 16bit int值; holding registers 是可读可写寄存器组, 存储一组 16bit int 值.

    对从设备来说, 所有寄存器组可读可写, 且可自定义分配各组寄存器的大小, 其余特性跟上述主机视角一致.

直接上例程:

from maix.comm import modbus
from maix import app, err

slave = modbus.Slave(
    modbus.Mode.RTU,    # modbus 模式选择为 rtu
    "/dev/ttyS0",       # 选择与主机通信的串口
    0x00, 10,           # coils 开始地址以及该组寄存器数量
    0x00, 10,           # discrete input 开始地址以及该组寄存器数量
    0x00, 10,           # input registers 开始地址以及该组寄存器数量
    0x00, 10,           # holding registers 开始地址以及该组寄存器数量
    115200, 1,          # 115200波特率, 默认为 8N1, 后面的 1 代表 rtu 的从机地址
    0, False            # tcp 端口号, 我们使用的是 rtu, 随便填写即可, 后者为 是否打印 debug 信息
)

"""
以 coils 寄存器组为例, 起始地址为 0x00, 数量为 10, 代表该从机 coils 寄存器组的地址范围为 0x00~0x09 共 10 个寄存器, 每个寄存器存储一个布尔值.
"""

# 读取当前 input registers 寄存器组里的所有值
# 寄存器内初始值均为 0
old_ir = slave.input_registers()
print("old ir: ", old_ir)

# 将列表内的值从引索2开始更新到 input registers 中
# 寄存器组内数值将变成 [0x00 0x00 0x22 0x33 0x44 0x00 0x00 0x00 0x00 0x00]
data : list[int] = [0x22, 0x33, 0x44]
slave.input_registers(data, 2)
# 读取, 打印验证
new_ir = slave.input_registers()
print("new ir:", new_ir)


while not app.need_exit():
    # 等待主机的读写操作
    if err.Err.ERR_NONE != slave.receive(2000): #timeout 2000ms
        continue

    # 获取主机的操作类型
    rtype = slave.request_type()
    # 如果主机想要读取 holding registers
    if rtype == modbus.RequestType.READ_HOLDING_REGISTERS:
        # 准备数据
        # 获取并查看当前 holding registers 内数据
        print("master read hr")
        hr = slave.holding_registers()
        print("now hr: ", hr)

        # 更新 holding registers 内所有数据
        hr = [x+1 for x in hr]
        print("now we make hr+1: ", hr)
        print("update hr")
        slave.holding_registers(hr)
    # else ... 处理其他操作

    # 自动处理主机请求, 自动更新寄存器值
    slave.reply()
from maix.comm import modbus
from maix import app, err

slave = modbus.Slave(
    modbus.Mode.TCP,    # 模式: TCP
    "",                 # 保持空即可
    0x00, 10,
    0x00, 10,
    0x00, 10,
    0x00, 10,
    0, 1,               # 我们使用的是 TCP 模式, 忽略波特率和rtu地址即可
    5020, False         # TCP 端口号, 后者为 是否打印 debug 信息
)

### 以下代码与 RTU 部分一致

old_ir = slave.input_registers()
print("old ir: ", old_ir)
data : list[int] = [0x22, 0x33, 0x44]
slave.input_registers(data, 3)
new_ir = slave.input_registers()
print("new ir:", new_ir)

while not app.need_exit():
    if err.Err.ERR_NONE != slave.receive(2000): #timeout 2000ms
        continue

    rtype = slave.request_type()
    if rtype == modbus.RequestType.READ_HOLDING_REGISTERS:
        print("master read hr")
        hr = slave.holding_registers()
        print("now hr: ", hr)
        hr = [x+1 for x in hr]
        print("now we make hr+1: ", hr)
        print("update hr")
        slave.holding_registers(hr)

    slave.reply()

这样, 我们就可以将 MaixCAM(Pro) 作为一个从设备, 主机可以随时读(写)其中的寄存器.

有关 Modbus API 的详细说明请看 Modbus API 文档.