07. MODBUS CLIENT (Robot = Master)
In lesson 6 the robot was controlled (Slave Server). Here the roles flip: the robot becomes a Master Client, actively controlling an electric gripper·other robots·PLCs. With MBC_* commands one robot connects to up to 4 servers at once and reads/writes the four data types. Since Modbus can't carry floats directly, you learn why IEEE754 conversion and SWAP_WORD (byte-order fix) are needed.
What you'll learn
- 1Explain how the robot=Master Client actively controls a gripper·PLC·other robot
- 2Know the structure where one robot connects to up to 4 servers (connection numbers 1~4)
- 3Distinguish MBC connection commands and data commands (Bit/Word, 'W'/'D' types)
- 4Know why SWAP_WORD·IEEE754_ENCODE/DECODE are needed and do the conversions
Introduction
The robot (Master/Client) sends requests first — writing "open" to the gripper's Holding Register, reading a sensor value from the PLC's Input Register. The peer (Slave/Server) only responds, never speaks first. This is the opposite of lesson 6 (6: robot=Server passive / 7: robot=Client active).
Key concepts
1) One robot = up to 4 servers at once
One robot can control a gripper (connection 1)·PLC (2)·vision (3)·another robot (4) simultaneously. Each connection is identified by a connection number 1~4, the first argument of every MBC_* data command.
2) MBC_* commands — Bit vs Word
| Class | Command | Notes |
|---|---|---|
| Connect | MBC_RTU_OPEN / MBC_TCP_OPEN | must call first for data commands to work |
| Bit | READ_DINPUT/READ_COIL/WRITE_COIL | 0 or 1, length 1~48 |
| Word | READ_INPUT/READ_HOLDING/WRITE_HOLDING | 'W'=one 16-bit, 'D'=two as 32-bit |
'W' (Word) is one 16-bit register; 'D' (Double Word) combines two consecutive into 32-bit (Low word first). Start addresses are 0-based (1-based on screen).
3) Why conversion commands are needed
Modbus registers carry only 16-bit integers — no floats, no integers over 16 bits, and byte order (High/Low word) varies by device. IEEE754_ENCODE (float→32-bit int, 10.5→1093140480) before sending and IEEE754_DECODE to restore; if byte order is reversed, SWAP_WORD (10→655360) fixes it.
4) Gripper register map (XEG-64)
| Area | Addr | Meaning |
|---|---|---|
| HR(R/W) | 1600 | direction 0=close/1=open |
| HR | 1601 | travel stroke 0.01mm |
| HR | 1606 | execute (write 1 → move → auto 0 on done) |
| IR(R) | 769 | status 0 Idle/1 Busy/2 Pos reached |
| IR | 770 | current position 0.01mm |
Done-check trap: looking only at IR[769]==2 (Pos) passes immediately because the prior motion's status latches. Always check IR[769]==2 AND HR[1606]==0 (the execute flag auto-resets).
Core example
As the robot (Master Client), confirm the gripper model and open 50.00mm then close.
def run_gripper(m, direction, stroke=5000, speed=5000):
m.write_holding(1600, direction) # ① direction (0=close/1=open)
m.write_holding(1601, stroke) # ② stroke (0.01mm)
m.write_holding(1602, speed) # ③ speed
m.write_holding(1606, 1) # ④ execution trigger
while not (m.read_input(769,1)[0]==2 and m.read_holding(1606,1)[0]==0):
time.sleep(0.05) # ⑤ avoid latch trap: check both
with RobotMaster(host, port) as m: # MBC_TCP_OPEN(1,"...",502)
model = m.read_holding(1536, 1)[0] # 2624 = XEG-64
run_gripper(m, 1, 5000) # open 50.00mm
run_gripper(m, 0, 5000) # closeCheck values: ieee754_encode(10.5)=1093140480, swap_word(10)=655360. Real-hardware mapping: with RobotMaster↔MBC_TCP_OPEN, write_holding↔MBC_WRITE_HOLDING, read_input↔MBC_READ_INPUT. Start the gripper server separately: gripper_sim.py --port 1503.
Common mistakes
Q. I checked IR[769]==2 for done but it passed before motion started.
A. The latch trap. After the prior motion, IR[769] stays 2 (Pos), so it's briefly 2 right after the next command too. Also watch HR[1606] (which the gripper zeros on motion) and treat done only when IR[769]==2 AND HR[1606]==0.
Q. I wrote a float coord (10.5) to a register and it corrupted.
A. Modbus can't carry floats directly. Convert with IEEE754_ENCODE(10.5)→1093140480 before sending and restore with IEEE754_DECODE. Integer coords over 16 bits use the 'D' type (or split_word).
Q. The gripper doesn't move or goes to the wrong position.
A. Wrong write order. Write direction (1600)·stroke (1601)·speed (1602) first, then the execution trigger (1606=1) last. The values at trigger time are used.
Summary
- Robot=Master Client. Actively reads/writes the four registers; one robot connects to up to 4 servers (connection numbers 1~4)
- Open the connection first (MBC_*_OPEN), then exchange via Bit commands and Word commands ('W'/'D')
- Gripper cycle: write direction·stroke → HR1606=1 → poll IR769==2 AND HR1606==0 (avoid latch)
- Floats go via IEEE754_ENCODE/DECODE; byte order via SWAP_WORD
Exercises
- Complete an open/close gripper cycle and confirm position via IR[770] (50.00mm→0.00mm)
- Drop HR[1606]==0 from the done condition to reproduce the immediate-pass (latch)
- Verify the ieee754_encode(10.5)/decode round-trip and swap_word(10)
All lecture materials and example code (with simulators, homework, and answers) are openly available on GitHub.
View on GitHub ↗