ModbusRTUMaster

ModbusRTUMaster 实现了 Modbus RTU 主站。ModbusRTUMaster 支持功能码 1(读线圈)、2(读离散输入)、3(读保持寄存器)、4(读输入寄存器)、5(写单线圈)、6(写单保持寄存器)、15(写多线圈)和 16(写多保持寄存器)。

UiFlow2 示例

CoreS3 RTU 主站

在 UiFlow2 中打开 cores3_rtu_master_example.m5f2 项目。

该示例演示如何使用 ModbusRTUMaster 类。

UiFlow2 代码块:

example.png

示例输出:

None

MicroPython 示例

CoreS3 RTU 主站

该示例演示如何使用 ModbusRTUMaster 类。

MicroPython 代码块:

  1# SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
  2#
  3# SPDX-License-Identifier: MIT
  4
  5import os, sys, io
  6import M5
  7from M5 import *
  8from unit import RS485Unit
  9import modbus
 10import time
 11
 12
 13label0 = None
 14label1 = None
 15label2 = None
 16label3 = None
 17label4 = None
 18label5 = None
 19label6 = None
 20label7 = None
 21label8 = None
 22label9 = None
 23label14 = None
 24label19 = None
 25label24 = None
 26label10 = None
 27label15 = None
 28label20 = None
 29label25 = None
 30label11 = None
 31label16 = None
 32label21 = None
 33label26 = None
 34label12 = None
 35label17 = None
 36label22 = None
 37label27 = None
 38label13 = None
 39label18 = None
 40label23 = None
 41label28 = None
 42modbusrtumaster_0 = None
 43rs485_0 = None
 44
 45
 46res = None
 47hr = None
 48coil = None
 49
 50
 51def setup():
 52    global \
 53        label0, \
 54        label1, \
 55        label2, \
 56        label3, \
 57        label4, \
 58        label5, \
 59        label6, \
 60        label7, \
 61        label8, \
 62        label9, \
 63        label14, \
 64        label19, \
 65        label24, \
 66        label10, \
 67        label15, \
 68        label20, \
 69        label25, \
 70        label11, \
 71        label16, \
 72        label21, \
 73        label26, \
 74        label12, \
 75        label17, \
 76        label22, \
 77        label27, \
 78        label13, \
 79        label18, \
 80        label23, \
 81        label28, \
 82        modbusrtumaster_0, \
 83        rs485_0, \
 84        res, \
 85        hr, \
 86        coil
 87
 88    M5.begin()
 89    Widgets.setRotation(1)
 90    Widgets.fillScreen(0x222222)
 91    label0 = Widgets.Label("co", 65, 8, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
 92    label1 = Widgets.Label("di", 135, 8, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
 93    label2 = Widgets.Label("hr", 205, 8, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
 94    label3 = Widgets.Label("ir", 275, 8, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
 95    label4 = Widgets.Label("1000", 4, 45, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
 96    label5 = Widgets.Label("1001", 4, 85, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
 97    label6 = Widgets.Label("1002", 4, 125, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
 98    label7 = Widgets.Label("1003", 4, 165, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
 99    label8 = Widgets.Label("1004", 4, 205, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
100    label9 = Widgets.Label("a00", 65, 45, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
101    label14 = Widgets.Label("a01", 135, 45, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
102    label19 = Widgets.Label("a02", 205, 45, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
103    label24 = Widgets.Label("a03", 275, 45, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
104    label10 = Widgets.Label("a10", 65, 85, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
105    label15 = Widgets.Label("a11", 135, 85, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
106    label20 = Widgets.Label("a12", 205, 85, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
107    label25 = Widgets.Label("a13", 275, 85, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
108    label11 = Widgets.Label("a20", 65, 125, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
109    label16 = Widgets.Label("a21", 135, 125, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
110    label21 = Widgets.Label("a22", 205, 125, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
111    label26 = Widgets.Label("a23", 275, 125, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
112    label12 = Widgets.Label("a30", 65, 165, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
113    label17 = Widgets.Label("a31", 135, 165, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
114    label22 = Widgets.Label("a32", 205, 165, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
115    label27 = Widgets.Label("a33", 275, 165, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
116    label13 = Widgets.Label("a40", 65, 205, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
117    label18 = Widgets.Label("a41", 135, 205, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
118    label23 = Widgets.Label("a42", 205, 205, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
119    label28 = Widgets.Label("a43", 275, 205, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18)
120
121    rs485_0 = RS485Unit(2, port=(18, 17))
122    rs485_0.init(
123        tx_pin=None,
124        rx_pin=None,
125        baudrate=115200,
126        data_bits=None,
127        stop_bits=None,
128        parity=None,
129        ctrl_pin=None,
130    )
131    modbusrtumaster_0 = modbus.ModbusRTUMaster(uart=rs485_0, verbose=True)
132    hr = 0
133    res = modbusrtumaster_0.read_coils(1, 1000, 5, timeout=2000)
134    label9.setText(str(res[0]))
135    label10.setText(str(res[1]))
136    label11.setText(str(res[2]))
137    label12.setText(str(res[3]))
138    label13.setText(str(res[4]))
139    res = modbusrtumaster_0.read_discrete_inputs(1, 1000, 5, timeout=2000)
140    label14.setText(str(res[0]))
141    label15.setText(str(res[1]))
142    label16.setText(str(res[2]))
143    label17.setText(str(res[3]))
144    label18.setText(str(res[4]))
145    res = modbusrtumaster_0.read_holding_registers(1, 1000, 5, timeout=2000)
146    label19.setText(str(res[0]))
147    label20.setText(str(res[1]))
148    label21.setText(str(res[2]))
149    label22.setText(str(res[3]))
150    label23.setText(str(res[4]))
151    res = modbusrtumaster_0.read_input_registers(1, 1000, 5, timeout=2000)
152    label24.setText(str(res[0]))
153    label25.setText(str(res[1]))
154    label26.setText(str(res[2]))
155    label27.setText(str(res[3]))
156    label28.setText(str(res[4]))
157
158
159def loop():
160    global \
161        label0, \
162        label1, \
163        label2, \
164        label3, \
165        label4, \
166        label5, \
167        label6, \
168        label7, \
169        label8, \
170        label9, \
171        label14, \
172        label19, \
173        label24, \
174        label10, \
175        label15, \
176        label20, \
177        label25, \
178        label11, \
179        label16, \
180        label21, \
181        label26, \
182        label12, \
183        label17, \
184        label22, \
185        label27, \
186        label13, \
187        label18, \
188        label23, \
189        label28, \
190        modbusrtumaster_0, \
191        rs485_0, \
192        res, \
193        hr, \
194        coil
195    M5.update()
196    hr = (hr + 1) % 65535
197    coil = not coil
198    modbusrtumaster_0.write_single_coil(1, 1000, coil, timeout=2000)
199    modbusrtumaster_0.write_single_register(1, 1000, hr, timeout=2000)
200    modbusrtumaster_0.write_multiple_coils(1, 1001, [coil, coil, coil], timeout=2000)
201    label9.setText(str(coil))
202    label10.setText(str(coil))
203    label11.setText(str(coil))
204    label12.setText(str(coil))
205    modbusrtumaster_0.write_multiple_registers(1, 1001, [hr, hr, hr], timeout=2000)
206    label19.setText(str(hr))
207    label20.setText(str(hr))
208    label21.setText(str(hr))
209    label22.setText(str(hr))
210    time.sleep(1)
211
212
213if __name__ == "__main__":
214    try:
215        setup()
216        while True:
217            loop()
218    except (Exception, KeyboardInterrupt) as e:
219        try:
220            from utility import print_error_msg
221
222            print_error_msg(e)
223        except ImportError:
224            print("please update to latest firmware")

示例输出:

None

API参考

ModbusRTUMaster

class modbus.ModbusRTUMaster(uart: UART, verbose: bool = False)

创建一个 ModbusRTUMaster 对象。

参数:
  • uart (UART) – UART 对象或 RS485 对象。

  • verbose (bool) – 是否启用详细日志。

UiFlow2 代码块:

init.png

MicroPython 代码块:

from modbus import ModbusRTUMaster
# For CoreS3
# master = ModbusRTUMaster(uart)
read_coils(address: int, register: int, quantity: int, timeout: int = 2000)

读取线圈。

参数:
  • address (int) – 从站地址,范围为 0 到 247。

  • register (int) – 线圈起始地址,范围为 0x0000 至 0xFFFF。

  • quantity (int) – 要读取的寄存器数量。

  • timeout (int) – 超时时间(毫秒)。

返回:

list - 线圈列表,每一项为 True 或 False。

UiFlow2 代码块:

read_coils.png

MicroPython 代码块:

master.read_coils(1, 0, 10)
read_discrete_inputs(address: int, register: int, quantity: int, timeout: int = 2000)

读取离散输入。

参数:
  • address (int) – 从站地址,范围为 0 到 247。

  • register (int) – 离散输入起始地址,范围为 0x0000 至 0xFFFF。

  • quantity (int) – 要读取的寄存器数量。

  • timeout (int) – 超时时间(毫秒)。

返回:

list - 离散输入列表,每一项为 True 或 False。

UiFlow2 代码块:

read_discrete_inputs.png

MicroPython 代码块:

master.read_discrete_inputs(1, 0, 10)
read_holding_registers(address: int, register: int, quantity: int, timeout: int = 2000)

读取保持寄存器。

参数:
  • address (int) – 从站地址,范围为 0 到 247。

  • register (int) – 保持寄存器起始地址,范围为 0x0000 至 0xFFFF。

  • quantity (int) – 要读取的寄存器数量。

  • timeout (int) – 超时时间(毫秒)。

返回:

list - 保持寄存器列表,每一项为 0x0000 至 0xFFFF。

UiFlow2 代码块:

read_holding_registers.png

MicroPython 代码块:

master.read_holding_registers(1, 0, 10)
read_input_registers(address: int, register: int, quantity: int, timeout: int = 2000)

读取输入寄存器。

参数:
  • address (int) – 从站地址,范围为 0 到 247。

  • register (int) – 输入寄存器起始地址,范围为 0x0000 至 0xFFFF。

  • quantity (int) – 要读取的寄存器数量。

  • timeout (int) – 超时时间(毫秒)。

返回:

list - 输入寄存器列表,每一项为 0x0000 至 0xFFFF。

UiFlow2 代码块:

read_input_registers.png

MicroPython 代码块:

master.read_input_registers(1, 0, 10)
write_single_coil(address: int, register: int, value: int, timeout: int = 2000)

写入单个线圈。

参数:
  • address (int) – 从站地址,范围为 0 到 247。

  • register (int) – 线圈起始地址,范围为 0x0000 至 0xFFFF。

  • value (int) – 写入值,取值为 True 或 False。

  • timeout (int) – 超时时间(毫秒)。

返回:

bool - 线圈值。

UiFlow2 代码块:

write_single_coil.png

MicroPython 代码块:

master.write_single_coil(1, 0, True)
write_single_register(address: int, register: int, value: int, timeout: int = 2000)

写入单个寄存器。

参数:
  • address (int) – 从站地址,范围为 0 到 247。

  • register (int) – 保持寄存器起始地址,范围为 0x0000 至 0xFFFF。

  • value (int) – 写入值,范围为 0x0000 至 0xFFFF。

  • timeout (int) – 超时时间(毫秒)。

返回:

int - 写入的值。

UiFlow2 代码块:

write_single_register.png

MicroPython 代码块:

master.write_single_register(1, 0, 100)
write_multiple_coils(address: int, register: int, values: list, timeout: int = 2000)

写入多个线圈。

参数:
  • address (int) – 从站地址,范围为 0 到 247。

  • register (int) – 线圈起始地址,范围为 0x0000 至 0xFFFF。

  • values (list) – 写入值列表,每一项为 True 或 False。

  • timeout (int) – 超时时间(毫秒)。

返回:

int - 已写入的数量。

UiFlow2 代码块:

write_multiple_coils.png

MicroPython 代码块:

master.write_multiple_coils(1, 0, [True, False, True])
write_multiple_registers(address: int, register: int, values: list, timeout: int = 2000)

写入多个寄存器。

参数:
  • address (int) – 从站地址,范围为 0 到 247。

  • register (int) – 保持寄存器起始地址,范围为 0x0000 至 0xFFFF。

  • values (list) – 写入值列表,每一项为 0x0000 至 0xFFFF。

  • timeout (int) – 超时时间(毫秒)。

返回:

int - 已写入的数量。

UiFlow2 代码块:

write_multiple_registers.png

MicroPython 代码块:

master.write_multiple_registers(1, 0, [100, 200, 300])