dev
Modbus map
Let a PLC drive the virtual machine, so PLC-side logic can be proven before hardware exists.
Enabling it
Settings → Interfaces → Modbus TCP. Listens on 0.0.0.0:502, Unit ID 1 by default.
Port 502 needs administrator rights on Windows. Using a non-standard port such as 5020 is usually simpler, and most PLCs let you configure the port.
Data conventions
| Item | Convention |
|---|---|
| Byte order | Big endian (Modbus standard); high word first for 32-bit values |
| Positions | int32 in 0.001 mm (120500 = 120.500 mm) |
| Angles | int32 in 0.0001 deg |
| Speeds | int32 in 0.001 mm/s |
| Booleans | Coils / discrete inputs |
Fixed-point integers rather than floats throughout: PLCs disagree about IEEE 754 word order, and integers sidestep that classic problem entirely.
Coils (read/write, FC 01/05/15)
| Address | Name | Meaning |
|---|---|---|
| 00001 | CMD_HOME_ALL |
Rising edge homes all axes |
| 00002 | CMD_STOP_ALL |
Held high stops all motion |
| 00003 | CMD_RESET |
Rising edge clears alarms |
| 00011 | CMD_X_MOVE |
Rising edge moves X to the target in 40011 |
| 00012 | CMD_Y_MOVE |
Target in 40013 |
| 00013 | CMD_Z_MOVE |
Target in 40015 |
| 00021 | CMD_GRAB |
Rising edge grabs a frame |
| 00031–00046 | DO_01–DO_16 |
Digital outputs |
Discrete inputs (read only, FC 02)
| Address | Name | Meaning |
|---|---|---|
| 10001 | ST_READY |
All axes homed, no alarms |
| 10002 | ST_BUSY |
An axis is moving |
| 10003 | ST_ALARM |
An alarm is active |
| 10004 | ST_ESTOP |
E-stop pressed |
| 10011 | ST_X_INPOS |
X in position |
| 10012 | ST_Y_INPOS |
Y in position |
| 10013 | ST_Z_INPOS |
Z in position |
| 10031–10046 | DI_01–DI_16 |
Digital inputs |
Holding registers (read/write, FC 03/06/16)
| Address | Name | Type | Meaning |
|---|---|---|---|
| 40011–40012 | X_TARGET |
int32 | X target, 0.001 mm |
| 40013–40014 | Y_TARGET |
int32 | Y target |
| 40015–40016 | Z_TARGET |
int32 | Z target |
| 40021–40022 | SPEED |
int32 | Speed, 0.001 mm/s |
| 40031 | CALIB_PROC |
uint16 | 1=C1 2=C2 3=C3 4=C4 5=C5 6=C6 |
| 40032 | CALIB_CMD |
uint16 | 1=start 2=abort |
Input registers (read only, FC 04)
| Address | Name | Type | Meaning |
|---|---|---|---|
| 30011–30012 | X_POS |
int32 | X position, 0.001 mm |
| 30013–30014 | Y_POS |
int32 | Y position |
| 30015–30016 | Z_POS |
int32 | Z position |
| 30021 | ALARM_CODE |
uint16 | Active alarm, 0 = none |
| 30031 | CALIB_STATE |
uint16 | 0=idle 1=running 2=pass 3=fail |
| 30032–30033 | CALIB_DEV_UM |
int32 | Last deviation, µm |
A complete PLC-side sequence
1) wait ST_READY = 1
2) write X_TARGET = 120500, Y_TARGET = 96000
3) pulse CMD_X_MOVE, CMD_Y_MOVE
4) wait ST_X_INPOS = 1 and ST_Y_INPOS = 1
5) pulse CMD_GRAB
6) write CALIB_PROC = 1, CALIB_CMD = 1
7) wait CALIB_STATE >= 2
8) read CALIB_DEV_UM and compare against tolerance
Edge-triggered command coils must be reset by the PLC. Holding one high does not re-trigger,
but it does make the ST_BUSY timing look strange.
Last updated: Sep 21, 2026
Was this page helpful?