Using Modbus Protocol with MaixCAM MaixPy
MaixPy has adapted the Modbus protocol, with its underlying implementation based on libmodbus.
Using the Modbus protocol on MaixPy is straightforward. Here’s what you need to know:
When you use
modbus.Slave
, MaixCAM(Pro) acts as a slave device (such as a sensor module), and the controlling device is the master (such as your MCU/PC). The master can read and write registers from the slave device just like reading and writing chip registers.You can think of it simply as:
From the master's perspective,
coils
are read/write register groups storing a set of boolean values;discrete input
are read-only register groups storing a set of boolean values;input registers
are read-only register groups storing a set of 16-bit int values;holding registers
are read/write register groups storing a set of 16-bit int values.From the slave's perspective, all register groups are read/write and can be custom-sized. The other characteristics are consistent with the master's view.
Example:
from maix.comm import modbus
from maix import app, err
slave = modbus.Slave(
modbus.Mode.RTU, # Modbus mode set to RTU
"/dev/ttyS0", # Serial port for communication with the master
0x00, 10, # Start address and number of coils
0x00, 10, # Start address and number of discrete inputs
0x00, 10, # Start address and number of input registers
0x00, 10, # Start address and number of holding registers
115200, 1, # Baud rate 115200, default 8N1, the last 1 represents the RTU slave address
0, False # TCP port number (irrelevant for RTU), the latter is whether to print debug information
)
"""
Taking the coils register group as an example, the start address is 0x00, and the number is 10, which means the address range of the slave's coils register group is 0x00~0x09, with a total of 10 registers, each storing a boolean value.
"""
# Read all values from the current input registers group
# Initial values in the registers are all 0
old_ir = slave.input_registers()
print("old ir: ", old_ir)
# Update the values in the input registers starting from index 2
# The register group values will become [0x00 0x00 0x22 0x33 0x44 0x00 0x00 0x00 0x00 0x00]
data : list[int] = [0x22, 0x33, 0x44]
slave.input_registers(data, 2)
# Read and print to verify
new_ir = slave.input_registers()
print("new ir:", new_ir)
while not app.need_exit():
# Wait for the master's read/write operation
if err.Err.ERR_NONE != slave.receive(2000): #timeout 2000ms
continue
# Get the master's operation type
rtype = slave.request_type()
# If the master wants to read holding registers
if rtype == modbus.RequestType.READ_HOLDING_REGISTERS:
# Prepare data
# Get and view the current holding registers data
print("master read hr")
hr = slave.holding_registers()
print("now hr: ", hr)
# Update all data in holding registers
hr = [x+1 for x in hr]
print("now we make hr+1: ", hr)
print("update hr")
slave.holding_registers(hr)
# else ... handle other operations
# Automatically handle the master's request, automatically update register values
slave.reply()
from maix.comm import modbus
from maix import app, err
slave = modbus.Slave(
modbus.Mode.TCP, # Mode: TCP
"", # Keep empty
0x00, 10,
0x00, 10,
0x00, 10,
0x00, 10,
0, 1, # We are using TCP mode, ignore baud rate and RTU address
5020, False # TCP port number, the latter is whether to print debug information
)
### The following code is consistent with the RTU part
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()
This way, we can use MaixCAM(Pro) as a slave device, and the master can read (write) its registers at any time.
For detailed Modbus API documentation, please refer to the Modbus API Documentation.