ModbusRTUMaster

ModbusRTUMaster implements the Modbus RTU master. ModbusRTUMaster support function codes 1 (Read Coils), 2 (Read Discrete Inputs), 3 (Read Holding Registers), 4 (Read Input Registers), 5 (Write Single Coil), 6 (Write Single Holding Register), 15 (Write Multiple Coils), and 16 (Write Multiple Holding Registers).

UiFlow2 Example

CoreS3 RTU Master

Open the cores3_rtu_master_example.m5f2 project in UiFlow2.

This example demonstrates how to use the ModbusRTUMaster class.

UiFlow2 Code Block:

example.png

Example output:

None

MicroPython Example

CoreS3 RTU Master

This example demonstrates how to use the ModbusRTUMaster class.

MicroPython Code Block:

  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")

Example output:

None

API

ModbusRTUMaster

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

Create a ModbusRTUMaster object.

Parameters:
  • uart (UART) – UART object or RS485 object.

  • verbose (bool) – Verbose mode.

UiFlow2 Code Block:

init.png

MicroPython Code Block:

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

Read coils.

Parameters:
  • address (int) – Slave address. The address is 0 to 247.

  • register (int) – Start address of the coils. The address is 0x0000 to 0xFFFF.

  • quantity (int) – Quantity of registers to read.

  • timeout (int) – Timeout in milliseconds.

Returns:

list - A list of coils. The item of the list is True or False.

UiFlow2 Code Block:

read_coils.png

MicroPython Code Block:

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

Read discrete inputs.

Parameters:
  • address (int) – Slave address. The address is 0 to 247.

  • register (int) – Start address of the discrete inputs. The address is 0x0000 to 0xFFFF.

  • quantity (int) – Quantity of registers to read.

  • timeout (int) – Timeout in milliseconds.

Returns:

list - A list of discrete inputs. The item of the list is True or False.

UiFlow2 Code Block:

read_discrete_inputs.png

MicroPython Code Block:

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

Read holding registers.

Parameters:
  • address (int) – Slave address. The address is 0 to 247.

  • register (int) – Start address of the holding registers. The address is 0x0000 to 0xFFFF.

  • quantity (int) – Quantity of registers to read.

  • timeout (int) – Timeout in milliseconds.

Returns:

list - A list of holding registers. The item of the list is 0x0000 to 0xFFFF.

UiFlow2 Code Block:

read_holding_registers.png

MicroPython Code Block:

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

Read input registers.

Parameters:
  • address (int) – Slave address. The address is 0 to 247.

  • register (int) – Start address of the input registers. The address is 0x0000 to 0xFFFF.

  • quantity (int) – Quantity of registers to read.

  • timeout (int) – Timeout in milliseconds.

Returns:

list - A list of input registers. The item of the list is 0x0000 to 0xFFFF.

UiFlow2 Code Block:

read_input_registers.png

MicroPython Code Block:

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

Write a single coil.

Parameters:
  • address (int) – Slave address. The address is 0 to 247.

  • register (int) – Start address of the coils. The address is 0x0000 to 0xFFFF.

  • value (int) – Value to write. The value is True or False.

  • timeout (int) – Timeout in milliseconds.

Returns:

bool - The value of the coil.

UiFlow2 Code Block:

write_single_coil.png

MicroPython Code Block:

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

Write a single register.

Parameters:
  • address (int) – Slave address. The address is 0 to 247.

  • register (int) – Start address of the holding registers. The address is 0x0000 to 0xFFFF.

  • value (int) – Value to write. The value is 0x0000 to 0xFFFF.

  • timeout (int) – Timeout in milliseconds.

Returns:

int - the written value

UiFlow2 Code Block:

write_single_register.png

MicroPython Code Block:

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

Write multiple coils.

Parameters:
  • address (int) – Slave address. The address is 0 to 247.

  • register (int) – Start address of the coils. The address is 0x0000 to 0xFFFF.

  • values (list) – Values to write. The item of the list is True or False.

  • timeout (int) – Timeout in milliseconds.

Returns:

int - the written count.

UiFlow2 Code Block:

write_multiple_coils.png

MicroPython Code Block:

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

Write multiple registers.

Parameters:
  • address (int) – Slave address. The address is 0 to 247.

  • register (int) – Start address of the holding registers. The address is 0x0000 to 0xFFFF.

  • values (list) – Values to write. The item of the list is 0x0000 to 0xFFFF.

  • timeout (int) – Timeout in milliseconds.

Returns:

int - the written count.

UiFlow2 Code Block:

write_multiple_registers.png

MicroPython Code Block:

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