ModbusRTUSlave
ModbusRTUSlave implements the Modbus RTU slave. ModbusRTUSlave 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 Slave
Open the cores3_rtu_slave_example.m5f2 project in UiFlow2.
This example demonstrates how to use the ModbusRTUSlave class.
UiFlow2 Code Block:
Example output:
None
MicroPython Example
CoreS3 RTU Slave
This example demonstrates how to use the ModbusRTUSlave 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 * 8import modbus 9from unit import ISO485Unit 10 11 12label0 = None 13label1 = None 14label2 = None 15modbusrtuslave_0 = None 16iso485_0 = None 17 18 19starting_register1 = None 20slave_list1 = None 21register1 = None 22slave_value1 = None 23starting_register4 = None 24slave_list4 = None 25register2 = None 26slave_value2 = None 27starting_register2 = None 28slave_list2 = None 29starting_register6 = None 30slave_list6 = None 31starting_register5 = None 32slave_list5 = None 33starting_register3 = None 34slave_list3 = None 35 36 37def modbus_read_coils_cb(args): 38 global \ 39 label0, \ 40 label1, \ 41 label2, \ 42 modbusrtuslave_0, \ 43 iso485_0, \ 44 starting_register1, \ 45 slave_list1, \ 46 register1, \ 47 slave_value1, \ 48 starting_register4, \ 49 slave_list4, \ 50 register2, \ 51 slave_value2, \ 52 starting_register2, \ 53 slave_list2, \ 54 starting_register6, \ 55 slave_list6, \ 56 starting_register5, \ 57 slave_list5, \ 58 starting_register3, \ 59 slave_list3 60 _, starting_register1, slave_list1 = args 61 label0.setText(str("read coils")) 62 label1.setText(str(starting_register1)) 63 label2.setText(str(slave_list1)) 64 65 66def modbus_write_single_coil_cb(args): 67 global \ 68 label0, \ 69 label1, \ 70 label2, \ 71 modbusrtuslave_0, \ 72 iso485_0, \ 73 starting_register1, \ 74 slave_list1, \ 75 register1, \ 76 slave_value1, \ 77 starting_register4, \ 78 slave_list4, \ 79 register2, \ 80 slave_value2, \ 81 starting_register2, \ 82 slave_list2, \ 83 starting_register6, \ 84 slave_list6, \ 85 starting_register5, \ 86 slave_list5, \ 87 starting_register3, \ 88 slave_list3 89 _, register1, slave_value1 = args 90 label0.setText(str("write single coil")) 91 label1.setText(str(register1)) 92 label2.setText(str(slave_value1)) 93 94 95def modbus_read_input_registers_cb(args): 96 global \ 97 label0, \ 98 label1, \ 99 label2, \ 100 modbusrtuslave_0, \ 101 iso485_0, \ 102 starting_register1, \ 103 slave_list1, \ 104 register1, \ 105 slave_value1, \ 106 starting_register4, \ 107 slave_list4, \ 108 register2, \ 109 slave_value2, \ 110 starting_register2, \ 111 slave_list2, \ 112 starting_register6, \ 113 slave_list6, \ 114 starting_register5, \ 115 slave_list5, \ 116 starting_register3, \ 117 slave_list3 118 _, starting_register4, slave_list4 = args 119 label0.setText(str("read input register")) 120 label1.setText(str(starting_register4)) 121 label2.setText(str(slave_list4)) 122 123 124def modbus_write_single_registers_cb(args): 125 global \ 126 label0, \ 127 label1, \ 128 label2, \ 129 modbusrtuslave_0, \ 130 iso485_0, \ 131 starting_register1, \ 132 slave_list1, \ 133 register1, \ 134 slave_value1, \ 135 starting_register4, \ 136 slave_list4, \ 137 register2, \ 138 slave_value2, \ 139 starting_register2, \ 140 slave_list2, \ 141 starting_register6, \ 142 slave_list6, \ 143 starting_register5, \ 144 slave_list5, \ 145 starting_register3, \ 146 slave_list3 147 _, register2, slave_value2 = args 148 label0.setText(str("write single registers")) 149 label1.setText(str(register2)) 150 label2.setText(str(slave_value2)) 151 152 153def modbus_read_discrete_inputs_cb(args): 154 global \ 155 label0, \ 156 label1, \ 157 label2, \ 158 modbusrtuslave_0, \ 159 iso485_0, \ 160 starting_register1, \ 161 slave_list1, \ 162 register1, \ 163 slave_value1, \ 164 starting_register4, \ 165 slave_list4, \ 166 register2, \ 167 slave_value2, \ 168 starting_register2, \ 169 slave_list2, \ 170 starting_register6, \ 171 slave_list6, \ 172 starting_register5, \ 173 slave_list5, \ 174 starting_register3, \ 175 slave_list3 176 _, starting_register2, slave_list2 = args 177 label0.setText(str("read discrete input")) 178 label1.setText(str(starting_register2)) 179 label2.setText(str(slave_list2)) 180 181 182def modbus_write_multiple_registers_cb(args): 183 global \ 184 label0, \ 185 label1, \ 186 label2, \ 187 modbusrtuslave_0, \ 188 iso485_0, \ 189 starting_register1, \ 190 slave_list1, \ 191 register1, \ 192 slave_value1, \ 193 starting_register4, \ 194 slave_list4, \ 195 register2, \ 196 slave_value2, \ 197 starting_register2, \ 198 slave_list2, \ 199 starting_register6, \ 200 slave_list6, \ 201 starting_register5, \ 202 slave_list5, \ 203 starting_register3, \ 204 slave_list3 205 _, starting_register6, slave_list6 = args 206 label0.setText(str("write multiple registers")) 207 label1.setText(str(slave_list6)) 208 label2.setText(str(slave_list6)) 209 210 211def modbus_write_multiple_coils_cb(args): 212 global \ 213 label0, \ 214 label1, \ 215 label2, \ 216 modbusrtuslave_0, \ 217 iso485_0, \ 218 starting_register1, \ 219 slave_list1, \ 220 register1, \ 221 slave_value1, \ 222 starting_register4, \ 223 slave_list4, \ 224 register2, \ 225 slave_value2, \ 226 starting_register2, \ 227 slave_list2, \ 228 starting_register6, \ 229 slave_list6, \ 230 starting_register5, \ 231 slave_list5, \ 232 starting_register3, \ 233 slave_list3 234 _, starting_register5, slave_list5 = args 235 label0.setText(str("write multiple coils")) 236 label1.setText(str(slave_list5)) 237 label2.setText(str(slave_list5)) 238 239 240def modbus_read_holding_registers_cb(args): 241 global \ 242 label0, \ 243 label1, \ 244 label2, \ 245 modbusrtuslave_0, \ 246 iso485_0, \ 247 starting_register1, \ 248 slave_list1, \ 249 register1, \ 250 slave_value1, \ 251 starting_register4, \ 252 slave_list4, \ 253 register2, \ 254 slave_value2, \ 255 starting_register2, \ 256 slave_list2, \ 257 starting_register6, \ 258 slave_list6, \ 259 starting_register5, \ 260 slave_list5, \ 261 starting_register3, \ 262 slave_list3 263 _, starting_register3, slave_list3 = args 264 label0.setText(str("read holding register")) 265 label1.setText(str(starting_register3)) 266 label2.setText(str(slave_list3)) 267 268 269def setup(): 270 global \ 271 label0, \ 272 label1, \ 273 label2, \ 274 modbusrtuslave_0, \ 275 iso485_0, \ 276 starting_register1, \ 277 slave_list1, \ 278 register1, \ 279 slave_value1, \ 280 starting_register4, \ 281 slave_list4, \ 282 register2, \ 283 slave_value2, \ 284 starting_register2, \ 285 slave_list2, \ 286 starting_register6, \ 287 slave_list6, \ 288 starting_register5, \ 289 slave_list5, \ 290 starting_register3, \ 291 slave_list3 292 293 M5.begin() 294 Widgets.setRotation(1) 295 Widgets.fillScreen(0x222222) 296 label0 = Widgets.Label("label0", 79, 60, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18) 297 label1 = Widgets.Label("label1", 73, 100, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18) 298 label2 = Widgets.Label("label2", 67, 135, 1.0, 0xFFFFFF, 0x222222, Widgets.FONTS.DejaVu18) 299 300 iso485_0 = ISO485Unit(2, port=(1, 2)) 301 iso485_0.init( 302 tx_pin=None, 303 rx_pin=None, 304 baudrate=115200, 305 data_bits=None, 306 stop_bits=None, 307 parity=None, 308 ctrl_pin=None, 309 ) 310 modbusrtuslave_0 = modbus.ModbusRTUSlave(iso485_0, device_address=1, verbose=True) 311 modbusrtuslave_0.set_callback(modbusrtuslave_0.READ_COILS_EVENT, modbus_read_coils_cb) 312 modbusrtuslave_0.set_callback( 313 modbusrtuslave_0.WRITE_SINGLE_COIL_EVENT, modbus_write_single_coil_cb 314 ) 315 modbusrtuslave_0.set_callback( 316 modbusrtuslave_0.READ_INPUT_REGISTERS_EVENT, modbus_read_input_registers_cb 317 ) 318 modbusrtuslave_0.set_callback( 319 modbusrtuslave_0.WRITE_SINGLE_REGISTER_EVENT, modbus_write_single_registers_cb 320 ) 321 modbusrtuslave_0.set_callback( 322 modbusrtuslave_0.READ_DISCRETE_INPUTS_EVENT, modbus_read_discrete_inputs_cb 323 ) 324 modbusrtuslave_0.set_callback( 325 modbusrtuslave_0.WRITE_MULTIPLE_REGISTERS_EVENT, modbus_write_multiple_registers_cb 326 ) 327 modbusrtuslave_0.set_callback( 328 modbusrtuslave_0.WRITE_MULTIPLE_COILS_EVENT, modbus_write_multiple_coils_cb 329 ) 330 modbusrtuslave_0.set_callback( 331 modbusrtuslave_0.READ_HOLDING_REGISTERS_EVENT, modbus_read_holding_registers_cb 332 ) 333 modbusrtuslave_0.add_coil(1000, True) 334 modbusrtuslave_0.add_coil(1001, False) 335 modbusrtuslave_0.add_coil(1002, True) 336 modbusrtuslave_0.add_coil(1003, False) 337 modbusrtuslave_0.add_coil(1004, True) 338 modbusrtuslave_0.add_discrete_input(1000, True) 339 modbusrtuslave_0.add_discrete_input(1001, False) 340 modbusrtuslave_0.add_discrete_input(1002, True) 341 modbusrtuslave_0.add_discrete_input(1003, False) 342 modbusrtuslave_0.add_discrete_input(1004, True) 343 modbusrtuslave_0.add_holding_register(1000, 0x0102) 344 modbusrtuslave_0.add_holding_register(1001, 0x0304) 345 modbusrtuslave_0.add_holding_register(1002, 0x0304) 346 modbusrtuslave_0.add_holding_register(1003, 0x0304) 347 modbusrtuslave_0.add_holding_register(1004, 0x0304) 348 modbusrtuslave_0.add_input_register(1000, 0x0102) 349 modbusrtuslave_0.add_input_register(1001, 0x0304) 350 modbusrtuslave_0.add_input_register(1002, 0x0304) 351 modbusrtuslave_0.add_input_register(1003, 0x0304) 352 modbusrtuslave_0.add_input_register(1004, 0x0304) 353 354 355def loop(): 356 global \ 357 label0, \ 358 label1, \ 359 label2, \ 360 modbusrtuslave_0, \ 361 iso485_0, \ 362 starting_register1, \ 363 slave_list1, \ 364 register1, \ 365 slave_value1, \ 366 starting_register4, \ 367 slave_list4, \ 368 register2, \ 369 slave_value2, \ 370 starting_register2, \ 371 slave_list2, \ 372 starting_register6, \ 373 slave_list6, \ 374 starting_register5, \ 375 slave_list5, \ 376 starting_register3, \ 377 slave_list3 378 M5.update() 379 modbusrtuslave_0.tick() 380 381 382if __name__ == "__main__": 383 try: 384 setup() 385 while True: 386 loop() 387 except (Exception, KeyboardInterrupt) as e: 388 try: 389 from utility import print_error_msg 390 391 print_error_msg(e) 392 except ImportError: 393 print("please update to latest firmware")
Example output:
None
API
ModbusRTUSlave
- class modbus.ModbusRTUSlave(uart, device_address: int = 1, context=None, ignore_unit_id: bool = False, verbose: bool = False)
Create a ModbusRTUSlave object.
- Parameters:
contextis a dictionary that contains the Modbus server context. the format is as follows:{ "discrete_inputs": [ { "register": 0, # Start address of the discrete inputs. "value": [False, True, False, True] # Values of the discrete inputs. quantity is the length of the list. } ], "coils": [ { "register": 0, # Start address of the coils. "value": [False, True, False, True] # Values of the coils. quantity is the length of the list. quantity is the length of the list. } ], "input_registers": [ { "register": 0, # Start address of the input registers. "value": [0x0000, 0x0001, 0x0002, 0x0003] # Values of the input registers. quantity is the length of the list. quantity is the length of the list. } ], "holding_registers": [ { "register": 0, # Start address of the holding registers. "value": [0x0000, 0x0001, 0x0002, 0x0003] # Values of the holding registers. quantity is the length of the list. quantity is the length of the list. } ], }
UiFlow2 Code Block:

MicroPython Code Block:
from modbus import ModbusRTUSlave # slave = ModbusRTUSlave(uart, device_address=1, context=context)
- start()
Start the Modbus RTU slave.
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.start()
- stop()
Stop the Modbus RTU slave.
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.stop()
- add_coil(register: int, value: bool)
Add a coil to the modbus register dictionary.
- Parameters:
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.add_coil(0, True)
- add_discrete_input(register: int, value: bool)
Add a discrete input to the modbus register dictionary.
- Parameters:
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.add_discrete_input(0, True)
- add_holding_register(register: int, value: int)
Add a holding register to the modbus register dictionary.
- Parameters:
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.add_holding_register(0, 100)
- add_input_register(register: int, value: int)
Add an input register to the modbus register dictionary.
- Parameters:
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.add_input_register(0, 100)
- remove_coil(register: int)
Remove a coil from the modbus register dictionary.
- Parameters:
register (int) – address of the coils. The address is 0x0000 to 0xFFFF.
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.remove_coil(0)
- remove_discrete_input(register: int)
Remove a discrete input from the modbus register dictionary.
- Parameters:
register (int) – address of the discrete inputs. The address is 0x0000 to 0xFFFF.
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.remove_discrete_input(0)
- remove_holding_register(register: int)
Remove a holding register from the modbus register dictionary.
- Parameters:
register (int) – address of the holding registers. The address is 0x0000 to 0xFFFF.
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.remove_holding_register(0)
- remove_input_register(register: int)
Remove an input register from the modbus register dictionary.
- Parameters:
register (int) – address of the input registers. The address is 0x0000 to 0xFFFF.
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.remove_input_register(0)
- get_coil(register: int)
Get the coil value.
- Parameters:
register (int) – address of the coils. The address is 0x0000 to 0xFFFF.
- Returns:
bool - The value of the coil.
UiFlow2 Code Block:

MicroPython Code Block:
value = slave.get_coil(0)
- get_discrete_input(register: int)
Get the discrete input value.
- Parameters:
register (int) – address of the discrete inputs. The address is 0x0000 to 0xFFFF.
- Returns:
bool - The value of the discrete input.
UiFlow2 Code Block:

MicroPython Code Block:
value = slave.get_discrete_input(0)
- get_holding_register(register: int)
Get the holding register value.
- Parameters:
register (int) – address of the holding registers. The address is 0x0000 to 0xFFFF.
- Returns:
int - The value of the holding register.
UiFlow2 Code Block:

MicroPython Code Block:
value = slave.get_holding_register(0)
- get_input_register(register: int)
Get the input register value.
- Parameters:
register (int) – address of the input registers. The address is 0x0000 to 0xFFFF.
- Returns:
int - The value of the input register.
UiFlow2 Code Block:

MicroPython Code Block:
value = slave.get_input_register(0)
- set_coil(register: int, value: bool)
Set the coil value.
- Parameters:
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.set_coil(0, True)
- set_multi_coils(register: int, value: list)
Set the multi coils value.
- Parameters:
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.set_multi_coils(0, [True, False])
- set_discrete_input(register: int, value: bool)
Set the discrete input value.
- Parameters:
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.set_discrete_input(0, True)
- set_multi_discrete_input(register: int, value: list)
Set the multi discrete inputs value.
- Parameters:
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.set_multi_discrete_input(0, [True, False])
- set_holding_register(register: int, value: int)
Set the holding register value.
- Parameters:
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.set_holding_register(0, 100)
- set_multi_holding_register(register: int, value: list)
Set the multi holding registers value.
- Parameters:
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.set_multi_holding_register(0, [100, 200])
- set_input_register(register: int, value: int)
Set the input register value.
- Parameters:
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.set_input_register(0, 100)
- set_multi_input_register(register: int, value: list)
Set the multi input registers value.
- Parameters:
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.set_multi_input_register(0, [100, 200])
- tick()
Modbus RTU slave tick function. This function should be called in the main loop.
- Returns:
None
UiFlow2 Code Block:

MicroPython Code Block:
slave.tick()
- set_callback(func_code: int, handler)
Set the callback function for the function code.
- Parameters:
func_code (int) – Function code. The function code is 1 to 6, 15, 16. the symbol is defined in the modbus.ModbusRTUSlave (*_EVENT etc.).
handler – Callback function.
- Returns:
None
UiFlow2 Code Block:








MicroPython Code Block:
def callback(arg): pass slave.set_callback(1, callback)
- READ_COILS_EVENT
Function code 1 (Read Coils).
- READ_DISCRETE_INPUTS_EVENT
Function code 2 (Read Discrete Inputs).
- READ_HOLDING_REGISTERS_EVENT
Function code 3 (Read Holding Registers).
- READ_INPUT_REGISTERS_EVENT
Function code 4 (Read Input Registers).
- WRITE_SINGLE_COIL_EVENT
Function code 5 (Write Single Coil).
- WRITE_SINGLE_HOLDING_REGISTER_EVENT
Function code 6 (Write Single Holding Register).
- WRITE_MULTIPLE_COILS_EVENT
Function code 15 (Write Multiple Coils).
- WRITE_MULTIPLE_HOLDING_REGISTERS_EVENT
Function code 16 (Write Multiple Holding Registers).
