Modbus RTU 协议
Modbus RTU 在 COM1 应答,部分型号的 COM2 也应答,从站 ID 相同。是否提供 Modbus 以型号接口为准。
使用前准备
通信前先完成下面七件事:
- 确认型号提供 Modbus。 对照适用产品;能通信时,读版本信息寄存器得到型号名,不确定时向技术支持确认。
- 关闭周期输出。 带 RS-485 接口的型号出厂不主动输出,无需关闭;其他型号见下方警告。
- 确认串口参数和从站 ID。 串口格式为 8N1,PLC 侧按此设置。出厂值见出厂默认配置;改过参数的,以记录的当前值为准,不确定时见失联恢复。
- 设置主机超时。 读取数据很快。写配置类寄存器要擦写 Flash,应答可能需要数十毫秒,偶尔接近 1 s。主机超时设为 1 s 以上。
- 整帧连续发送。 同一帧内字节之间不停顿。USB 转 RS-485 转换器有字节间延时选项时,请关闭。
- 只向具体的从站 ID 发请求,不用地址 0。 地址 0 是广播,总线上所有从站都会执行写请求,有的设备还会应答,造成总线冲突。
- 写后回读,配置只在需要时写。 Modbus 的回显只说明模块收到了请求,关键参数写入后读回确认,通则见配置流程与保存。配置完成后向寄存器
0x0000(CTRL)写0x0000保存。写配置寄存器可能触发 Flash 擦写,所以不要周期性写入。
警告
作 Modbus 从站前,先用 ASCII 命令关闭周期输出:LOG HI91 ONTIME 0,再执行 SAVECONFIG。已开启的其他周期帧同样要关闭。否则数据帧与应答混在一起,主机会解析出错误数据,且没有任何报错。
帧格式
寄存器为 16 位,大端(高字节在前)。校验为标准 Modbus CRC-16(初值 0xFFFF,多项式 0xA001),低字节在前。使用以下两个功能码:
| 功能码 | 作用 | 限制 |
|---|---|---|
0x03 | 读保持寄存器 | 单次读 1–125 个寄存器 |
0x06 | 写单个寄存器 | 每次写一个 16 位寄存器 |
PLC 中选择“读保持寄存器(FC03)”,不要选“读输入寄存器(FC04)”。本手册未介绍的功能码请不要使用。
读寄存器(0x03):请求 ID 03 ADDR_H ADDR_L CNT_H CNT_L CRC_L CRC_H,其中 ID 为从站 ID,ADDR 为起始寄存器地址,CNT 为读取的寄存器个数。应答 ID 03 N DATA… CRC_L CRC_H,N 为数据字节数。
写寄存器(0x06):请求 ID 06 ADDR_H ADDR_L DATA_H DATA_L CRC_L CRC_H,正常应答与请求相同(回显)。
注意
- 应答功能码的最高位为 1,表示模块拒绝了请求。请先改正请求,不要原样重发。
- 读取未定义、只写或已取消的寄存器不会报错,只返回 0,因此读取成功不能说明寄存器存在。
CRC 计算(C),算出的 crc 低字节先发送:
uint16_t modbus_crc16(const uint8_t *p, size_t n) /* init 0xFFFF, poly 0xA001 */
{
uint16_t crc = 0xFFFF;
while (n--) {
crc ^= *p++;
for (int b = 0; b < 8; b++)
crc = (crc & 1) ? (crc >> 1) ^ 0xA001 : crc >> 1;
}
return crc;
}主机侧完整实现见官方 SDK 的 Python 版:modbus.py(读写寄存器)和 modbus_multinode.py(一条总线上轮询多台模块)。
寄存器列表
寄存器地址以十六进制表示。生效方式分两种:立即表示写入后马上生效;重启表示写入后先保存(向寄存器 0x0000 写 0x0000),再重启(写 0x00FF),重启后才生效。重启生效的项,写入后读回的已是新值,但尚未生效,以重启后的实际行为为准。
表中地址是报文里的协议地址,从 0 起。PLC 软件按 4xxxx 编号时,把地址换成十进制再加 1,例如 0x0034 = 52,对应 40053。
控制与配置寄存器
| 寄存器地址 | 名称 | 类型 | R/W | 取值与说明 | 生效 |
|---|---|---|---|---|---|
| 0x0000 | CTRL | u16 | W | 写 0x0000 保存配置;写 0x0001 恢复出厂(见恢复出厂);写 0x00FF 重启 | 立即 |
| 0x0004 | UART1_BAUD | u16 | R/W | 串口波特率档位,见改波特率 | 重启 |
| 0x0005 | MD_ID | u16 | R/W | Modbus 从站 ID,1–247,出厂 80(0x50);-I2C 型号同时是 I2C 设备地址,范围 0x08–0x77 | 立即 |
| 0x0006 | PROFILE | u16 | R/W | 工作模式:0 = 6 轴、1 = 9 轴、4 = 人形机器人、5 = 室内低速机器人、7 = 低动态 / 倾角仪,见工作模式 | 重启 |
| 0x0007 | COORD | u16 | R/W | 输出数据轴向:0 = 右-前-上(默认)、4 = ROS(REP-103),见输出数据轴向 | 重启 |
| 0x0008 | MCAL_START | u16 | W | 启动地磁校准:1 = 3D、2 = 2D | 立即 |
| 0x0009 | MAIN_STATUS | u16 | R | 状态字,见 MAIN_STATUS 状态字。只解析该表中定义的位,其余位屏蔽后再判断 | — |
| 0x000A | MCAL_STATUS | u16 | R | 地磁校准状态:0 空闲、1 校准中、3 成功、4 失败 | — |
| 0x000B | MCAL_PROGRESS | u16 | R | 校准进度(%):校准中 0–99,成功后 100 | — |
| 0x00A5 | ATT_RST | u16 | W | 姿态零点,取值与含义同 CONFIG ATT RST:0 全部归零、1 航向临时清零、2 相对零点、3 自动校平、5 取消校平;0 / 2 / 3 / 5 写后保存。见姿态零点与校平 | 立即 |
| 0x00A6 | URFR | u16 | R/W | 安装方向编码(十进制数,如 24),见安装方向 | 重启 |
CTRL(0x0000)、MCAL_START(0x0008)、ATT_RST(0x00A5)只写,读取返回 0。重启和恢复出厂后,模块不一定应答,处理方法见配置流程与保存。修改 PROFILE、COORD、URFR 后,先向 ATT_RST 写 5,后续步骤见设置顺序。
数据寄存器
数据寄存器均为只读,内容是模块的实时输出。
| 地址 | 名称 | 类型 | 单位 / 比例 | 说明 |
|---|---|---|---|---|
| 0x0034–0x0036 | ACC X/Y/Z | i16 | G,×0.00048828 | 加速度 |
| 0x0037–0x0039 | GYR X/Y/Z | i16 | deg/s,×0.061035 | 角速度 |
| 0x003A–0x003C | MAG X/Y/Z | i16 | μT,×0.030517 | 磁场 |
| 0x003D–0x003E | ROLL | i32 | deg,×0.001 | 横滚角,高字在前 |
| 0x003F–0x0040 | PITCH | i32 | deg,×0.001 | 俯仰角 |
| 0x0041–0x0042 | YAW | i32 | deg,×0.001 | 航向角,±180° |
| 0x0043 | TEMP | i16 | °C,×0.01 | 温度 |
| 0x0044–0x0045 | PRS | i32 | Pa,×0.01 | 气压,仅带气压计的型号有效 |
| 0x0046–0x0049 | Q0–Q3 | i16 | ×0.0001 | 四元数 W/X/Y/Z |
| 0x004A | INCLI_X | i16 | deg,×0.011 | 倾角 X(横滚) |
| 0x004B | INCLI_Y | i16 | deg,×0.011 | 倾角 Y(俯仰) |
| 0x004C–0x004D | CPUTIME | i32 | ms | 样本时刻,开机累计毫秒,不随对时切换;约 24.8 天后按 i32 解码为负值 |
| 0x004E–0x0050 | HEAVE / SURGE / SWAY | i16 | m,×0.01 | MRU 位移(MRU 型号) |
| 0x0051–0x0053 | HEAVE / SURGE / SWAY 频率 | i16 | Hz,×0.01 | MRU 频率(MRU 型号) |
- 能一次读完的数据,用一次请求读取。同一次请求里的数据更接近同一时刻,分开的请求之间不保证对齐。例如读取
0x0034–0x004D(26 个寄存器),一次得到加速度到 CPUTIME 的全部数据。 - 整型输出按固定量程 ±16 G、±2000 deg/s、±1000 μT 换算,超出量程的读数不可信。需要完整量程或更高精度,使用 HI91 / HI83 的浮点输出,见数据字典。
- 版本与身份寄存器见读取版本信息。HI83 字段用串口命令
LOG HI83 MAP设置,见 HI83 字段选择;-I2C 型号也可以写HI83_MAP寄存器,见I2C 配置寄存器。
地磁校准寄存器
先按校准步骤做好准备。下表给出各步骤对应的寄存器操作。
| 对应步骤 | 寄存器操作 |
|---|---|
| 第 1 步:切换工作模式 | 向寄存器 0x0006(PROFILE)写 1,向寄存器 0x0000(CTRL)写 0x0000 保存,再写 0x00FF 重启。重启后确认 MAIN_STATUS 的 MAG_AIDING 为 1 |
| 第 2 步:检查校准环境 | 无寄存器操作 |
| 第 3 步:执行校准 | 向寄存器 0x0008(MCAL_START)写 1(3D)或 2(2D),随后读寄存器 0x000A(MCAL_STATUS),确认变为 1。校准进行中不再写入 |
| 第 4 步:查询校准状态 | 每 1–2 s 读一次寄存器 0x000A(MCAL_STATUS)和 0x000B(MCAL_PROGRESS),直到 0x000A 为 3(成功)或 4(失败)。以状态值为准,不按固定时长判断 |
| 第 5 步:验证校准结果 | 无寄存器操作。校准成功后自动保存,验证方法见该步骤 |
常用配置示例
注意
以下报文均以出厂从站 ID 80(0x50)为例。改从站 ID 时,同步改报文第一字节;改 DATA 时也一样。两种改动都要重算 CRC。
写入、保存、重启和读回的顺序见寄存器列表开头的生效说明,下表是各步骤的报文。
| 操作 | 报文(Hex) |
|---|---|
| 保存配置 | 50 06 00 00 00 00 84 4B |
| 重启 | 50 06 00 00 00 FF C4 0B |
| 恢复出厂(步骤见恢复出厂) | 50 06 00 00 00 01 45 8B |
| 设为 6 轴模式 | 50 06 00 06 00 00 64 4A |
| 设为 9 轴模式 | 50 06 00 06 00 01 A5 8A |
| 设为低动态 / 倾角仪模式(7) | 50 06 00 06 00 07 25 88 |
| 输出数据轴向设为右-前-上(默认) | 50 06 00 07 00 00 35 8A |
| 输出数据轴向设为 ROS | 50 06 00 07 00 04 34 49 |
| 全部归零(ATT_RST 0) | 50 06 00 A5 00 00 94 68 |
| 相对零点(ATT_RST 2) | 50 06 00 A5 00 02 15 A9 |
| 自动校平(ATT_RST 3) | 50 06 00 A5 00 03 D4 69 |
| 取消校平(ATT_RST 5) | 50 06 00 A5 00 05 54 6B |
改波特率
寄存器 0x0004(UART1_BAUD)的档位码 0–8 依次对应下表。写入后向寄存器 0x0000(CTRL)写 0x0000 保存,再写 0x00FF 重启。发出重启后,主机切换到新波特率并清空接收缓冲,读回寄存器 0x0004 确认。
| 档位码 | 波特率 | 报文(ID = 0x50) | 档位码 | 波特率 | 报文(ID = 0x50) |
|---|---|---|---|---|---|
| 0 | 4800 | 50 06 00 04 00 00 C5 8A | 5 | 115200 | 50 06 00 04 00 05 05 89 |
| 1 | 9600 | 50 06 00 04 00 01 04 4A | 6 | 230400 | 50 06 00 04 00 06 45 88 |
| 2 | 19200 | 50 06 00 04 00 02 44 4B | 7 | 460800 | 50 06 00 04 00 07 84 48 |
| 3 | 38400 | 50 06 00 04 00 03 85 8B | 8 | 921600 | 50 06 00 04 00 08 C4 4C |
| 4 | 57600 | 50 06 00 04 00 04 C4 49 |
注意
档位码只用表内的 0–8。读不到应答时见失联恢复。
改从站 ID
写寄存器 0x0005(MD_ID),格式为 [当前ID] 06 00 05 00 [新ID] CRC。例如把从站 ID 从 0x50 改为 0x51:
→ 50 06 00 05 00 51 55 B6 写寄存器 0x0005,新从站 ID = 0x51
← 50 06 00 05 00 51 55 B6 回显,第一字节仍是原从站 ID 0x50
→ 51 03 00 05 00 01 98 5B 之后使用新从站 ID,读寄存器 0x0005 确认
← 51 03 02 00 51 B9 B4
→ 51 06 00 00 00 00 85 9A 用新从站 ID 保存配置(寄存器 0x00 ← 0x0000)从站 ID 立即生效,之后的报文使用新 ID 并重算 CRC。多从站总线上,一次只接一台模块,不要用广播地址修改。
设置安装方向
写寄存器 0x00A6(URFR),DATA 为安装方向编码(十进制数)转成的十六进制,例如 24 写 0x0018。每次设置后保存、重启,用 LOG USRCONFIG 读回(也可读寄存器 0x00A6),并抬车头、右侧下沉,验证姿态符号。完整的 24 种编码见安装方向,只写表内编码。
| 安装方向(X,Y,Z 箭头指向) | 编码 | 十六进制 | 报文(ID = 0x50) |
|---|---|---|---|
| 右,前,上(默认水平安装) | 024 | 0x0018 | 50 06 00 A6 00 18 64 62 |
| 右,下,前(侧装,Y 朝下) | 043 | 0x002B | 50 06 00 A6 00 2B 24 77 |
读取版本信息
从寄存器 0x0070 起读 19 个寄存器,得到型号名、固件版本、引导程序版本和芯片 ID。
→ 50 03 00 70 00 13 08 5D
← 50 03 26 [型号名 16 字节] [固件版本 2 字节] [引导程序版本 2 字节] [0x007A–0x007E 10 字节] [芯片 ID 8 字节] [CRC_L] [CRC_H]应答共 43 字节,数据区 38 字节,每个寄存器高字节在前:
| 寄存器 | 数据区字节偏移 | 内容 |
|---|---|---|
0x0070–0x0077 | 0–15 | 型号名(PNAME),ASCII |
0x0078 | 16–17 | 固件版本(SW_VER),与 LOG VERSION 的 APP_VER=<固件版本> 对应 |
0x0079 | 18–19 | 引导程序版本(BL_VER),与 BL_VER=<引导程序版本> 对应 |
0x007A–0x007E | 20–29 | 保留,忽略 |
0x007F–0x0082 | 30–37 | 芯片唯一 ID,与 UUID=<芯片 ID> 对应 |
产品序列号用 ASCII 命令 LOG VERSION 读取其中的 SN=<序列号>。
读取 IMU/AHRS 数据
从寄存器 0x0034 起读 15 个寄存器(加速度、角速度、磁场、横滚、俯仰、航向),数据区 30 字节:
→ 50 03 00 34 00 0F 49 81
← 50 03 1E FF 01 03 B0 06 50 FC C9 FF 7C 00 91 01 D5 FD DB FD 27 00 00 21 FF 00 00 7F F6 FF FD 73 E7 3F 04按寄存器列表的比例因子换算:
| 物理量 | 轴 | 寄存器值 | 原始值 | 物理值 |
|---|---|---|---|---|
| 加速度(G,×0.00048828) | X | FF 01 | −255 | −0.1245 |
| Y | 03 B0 | 944 | 0.4609 | |
| Z | 06 50 | 1616 | 0.7891 | |
| 角速度(deg/s,×0.061035) | X | FC C9 | −823 | −50.232 |
| Y | FF 7C | −132 | −8.057 | |
| Z | 00 91 | 145 | 8.850 | |
| 磁场(μT,×0.030517) | X | 01 D5 | 469 | 14.312 |
| Y | FD DB | −549 | −16.754 | |
| Z | FD 27 | −729 | −22.247 | |
| 横滚(deg,×0.001) | — | 00 00 21 FF | 8703 | 8.703 |
| 俯仰(deg,×0.001) | — | 00 00 7F F6 | 32758 | 32.758 |
| 航向(deg,×0.001) | — | FF FD 73 E7 | −166937 | −166.937 |
警告
32 位量(欧拉角、气压、CPUTIME)是大端,占两个连续寄存器,高字在前,需成对读取。先拼成完整的 i32,再乘比例因子,例如 FF FD 73 E7 → 0xFFFD73E7 = −166937 → −166.937°。把两个寄存器分别按 i16 解码,得到的角度是错的,且不会报错。
读取倾角
倾角寄存器随时可读,无需另外开启。从寄存器 0x004A 起读 2 个寄存器,按 i16 有符号数乘 0.011 换算为度:
→ 50 03 00 4A 00 02 E8 5C
← 50 03 04 00 64 FF 38 BB 0BX = 0x0064 = 100 → 1.100°,Y = 0xFF38 = −200 → −2.200°。倾角的范围、工作模式和零点设置见倾角输出,零点向寄存器 0x00A5(ATT_RST)写 2。
读取 MRU 数据
MRU 型号从寄存器 0x004E 起读 6 个寄存器:
→ 50 03 00 4E 00 06 A8 5E
← 50 03 0C [HEAVE] [SURGE] [SWAY] [HEAVE 频率] [SURGE 频率] [SWAY 频率] [CRC_L] [CRC_H]每项 2 字节 i16,高字节在前。位移比例因子 ×0.01 m,频率比例因子 ×0.01 Hz。MRU 输出含义见MRU 输出。
