← Back to Robot Communication series
🤖
MODBUS
MODBUS · Prereq: lesson 5

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.

MODBUS ClientMBC_*gripperIEEE754SWAP_WORDlatch trap
Duration
~2 hours
Level
📊 Intermediate
Prerequisite
🎯 Lesson 5
OUTCOME
In the robot=Master structure, control a gripper with MBC_* connection/data commands, handle floats·byte order with IEEE754_ENCODE/DECODE·SWAP_WORD, and avoid the latch trap.

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

ClassCommandNotes
ConnectMBC_RTU_OPEN / MBC_TCP_OPENmust call first for data commands to work
BitREAD_DINPUT/READ_COIL/WRITE_COIL0 or 1, length 1~48
WordREAD_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)

AreaAddrMeaning
HR(R/W)1600direction 0=close/1=open
HR1601travel stroke 0.01mm
HR1606execute (write 1 → move → auto 0 on done)
IR(R)769status 0 Idle/1 Busy/2 Pos reached
IR770current 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.

python
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)            # close
ℹ️

Check 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

  1. Complete an open/close gripper cycle and confirm position via IR[770] (50.00mm→0.00mm)
  2. Drop HR[1606]==0 from the done condition to reproduce the immediate-pass (latch)
  3. Verify the ieee754_encode(10.5)/decode round-trip and swap_word(10)
Example code / lecture materials

All lecture materials and example code (with simulators, homework, and answers) are openly available on GitHub.

View on GitHub ↗