ARCS Modbus 使用指南
1. Modbus 协议介绍
Modbus是一种串行通信协议,最初由 Modicon 公司(现在的施耐德电气)在1979年为使用可编程逻辑控制器(PLC)的自动化设备设计。Modbus 已经成为工业领域通信协议的事实标准。Modbus 协议包括 Modbus RTU 和 Modbus TCP 两种形式。
Modbus RTU(Remote Terminal Unit):这是一种基于串行线(例如 RS-485、RS-422、RS-232)的二进制通信协议。在 Modbus RTU 中,数据以二进制形式传输,每个字节由两个十六进制字符表示。Modbus RTU 主要用于工业和系统自动化应用,其中设备之间的通信距离较长。
Modbus TCP(Transmission Control Protocol):这是一种基于以太网的通信协议。Modbus TCP 使用 TCP/IP 协议进行通信,因此可以利用现有的以太网基础设施。与 Modbus RTU 相比,Modbus TCP 可以支持更多的设备连接,并且通信速度更快。
Modbus RTU 与 Modbus TCP 两者的主要区别:
Modbus RTU 基于串行通信的方式,如 RS-485 接口,其传输速率受限于串行接口的性能。
Modbus TCP 基于 TCP/IP 协议栈,在网络上进行数据传输,支持更高的传输速率。
2. Modbus 主站
2.1 主站介绍
在 Modbus 通信网络中,主站(Master Station)是发起通信的设备,它负责控制和协调与从站(Slave Station)之间的通信过程。主站就像是一个指挥者,主动向从站请求数据或者向从站发送命令,以实现对整个网络的有效管理和数据交互。
2.2 主站用途
在焊接、搬运、装配等操作中作为主站,它需要根据自身的任务流程和工作状态,有针对性地向 PLC 从站请求数据或发送指令。
- 示例:在汽车零部件组装过程中,机器人可能需要从 PLC 获取零部件的位置信息,以便准确地抓取和安装。
机器人主站往往具有较高的智能化程度,能够对获取的数据进行分析和处理,以做出合理的决策。
- 示例:根据 PLC 提供的生产线上的设备状态信息,机器人可以调整自己的工作节奏和动作顺序,实现与其他设备的协同工作。
2.3 Modbus 入口
打开 遨博 STUDIO 软件主页,单击左侧导航栏“配置 > 现场总线 > Modbus”进入 【Modbus 客户端 IO设置】页面。 
2.4 主站 Modbus TCP
单元页面:在 【Modbus 客户端 IO设置】页面单击“单元 > 添加 Modbus 单元 > TCP模式”。

Modbus TCP 设备: 使用 TCP/IP 连接,不需要校验和计算,可配置“设备”、“名称”、“从站编号”、“IP 地址”、“端口”及“操作”。配置 IP 地址后可单击【测试】,弹出测试成功表示可以与目标设备进行通讯,反之则与目标设备不可进行通讯,需检查与目标设备是否在同一网段,防火墙是否关闭等。
注意:
请确保您的TCP设备与目标设备处于同一网段。

信号页面:在 【Modbus 客户端 IO设置】页面单击“信号 > 添加 Modbus 信号”。

- COIL STATUS(线圈状态):用于读取和控制远程设备的开关状态,通常用于控制继电器等开关设备。
- INPUT STATUS(输入状态):用于读取远程设备的输入状态,通常用于读取传感器等输入设备的状态。
- HOLDING REGISTER(保持寄存器):用于存储和读取远程设备的数据,通常用于存储控制参数、设备状态等信息。
- INPUT REGISTER(输入寄存器):用于存储远程设备的输入数据,通常用于存储传感器等输入设备的数据。
- 绿色表示为正常通讯,灰色,红色为不通讯,红色响应代码如下所示:
- E1 :非法函数(0x01)查询中接收到的函数代码不是服务器(或从服务器)允许的操作。
- E2 :非法数据地址(0x02)在查询中收到的功能代码不是服务器(或从站)允许的操作,请检查输入的信号地址对应的远程 MODBUS 服务器的设置。
- E3 :非法数据值(0x03)数据字段中包含的值对于服务器(或从服务器)是不允许的值,请检查信号值对于远程 MODBUS 服务器上的指定地址是否有效。
- E4 :从属设备故障(0x04)当服务器(或从服务器)试图执行请求的操作时,发生了一个不可恢复的错误,请检查设备与接线是否损坏,并尝试重启设备。
- E5 :应答(0x05)与发送到远程 MODBUS 单元的编程命令结合使用的专用功能。
- E6 :从设备忙(0x06)与发送到远程 MODBUS 单元的编程命令一起使用,表示设备(服务器)现在无法响应,请等待或尝试重新连接,并排查机器人IP地址是否与同一局域网下其他设备IP地址一致,产生了冲突。
2.5 主站 Modbus RTU
单元页面:在 【Modbus 客户端 IO设置】页面单击“单元 > 添加 Modbus 单元 > RTU模式”。

Modbus RTU 设备:可配置设备“名称”、“从站编号”、“串口号”、“波特率”、“奇偶校验”、“数据位”及“停止位”。
注意:Modbus RTU 设备基于串行通信的方式,其传输速率受限于 RS-485 串行接口的性能。若通信不稳定,信号状态闪烁,可将波特率值调小,若不通讯时排查选择的串口是否符合,可使用 Modbus 串口助手进行排查,参考文档:

Modbus RTU 通讯依赖于控制柜或机械臂末端的 RS-485 串口通讯,在 Modbus 的串口选择可以参考如下:

控制 RS-485 串口号,控制 RS-485 包括末端 RS485 及 USB485。

2.6 Modbus 信号在配置中作为 IO 使用
在【配置】界面单击“一般 > I/O设置”可配置其 I/O 输入动作,除拖动示教外其余信号需要在联动模式下触发信号执行(也可通过 OEM 定制功能使其在手动模式或自动模式生效)。
进行此配置前需要用户在【配置】界面单击“ 现场总线 > Modbus > 信号”中添加信号类型为“寄存器输入”或“数字输入”的Modbus 信号。

为对应的 Modbus 信号配置输入动作。

为对应的 Modbus 信号配置输出动作。

用户可以在左侧导航栏单击“IO > Mobus”查看信号寄存器和数字信号的变化。

2.7 Modbus 信号在程序中使用
- 设置节点: 可以设置 Modbus 信号的“数字输出”和“寄存器输出”以及数字信号的单脉冲参数。
提示
通常需配合“等待信号”做为校验,确保信号设置成功再执行后续流程。
等待节点: 以 Modbus 信号为判断依据,待满足此信号后程序才继续运行,常与设置信号搭配使用。
赋值节点: 以 Modbus 信号值赋值给变量,供后续流程调用。
如果节点: 以 Modbus信号 做为判断条件,信号满足要求时,程序进入判断流程。
循环节点: 以 Modbus 信号做为触发循环的条件,信号满足条件时,程序进入循环流程。

用户可以在左侧导航栏单击“IO > Mobus”查看信号寄存器和数字信号的变化。

3. Modbus 从站
3.1 从站介绍
Modbus 从站的主要作用是响应主站(Master)的请求并执行相应的操作。实际应用中它可以用于连接和控制生产线上的各种设备,实现设备之间的信息交换和控制指令传递。
3.2 ARCS 从站的用途
响应主站(Master)的请求,将机器臂的状态信息实时发送给主站。
响应主站(Master)的请求,将控制器的信息发送给主站。
测试调试时作为数据:
- 将机器臂 I/O 信号的变化实时传递给主站。
- 将主站自定义信号实时传递给机器臂。
注意:
通过 ARCS 的主站连接从站的方式,可能会存在信号延时,仅在调试时候使用,不可在程序中使用,若需要在程序中对从站进行寄存器的读写可以参考下文 3.4 通用寄存器的读写示例。
3.3 从站地址表更新位置
Modbus 从站地址表位于“钉盘-团队文件 > ARCS > 对外文件夹 > Modbus从站”中进行更新,若您是使用客户,可联系本公司技术服务部技术人员获取,若您是技术服务人员可自行获取。
Modbus 从站版本与 ARCS 版本的对应关系:
| Modbus 版本 | ARCS 版本 | 修改日期 | 修改内容 |
|---|---|---|---|
| 1.0.4 | 0.29.2-beta.10 | 2024-8-19 | 1. 增加控制工程。 2. 增加工程运行状态。 |
| 1.0.7 | 0.31.0-beta.3 0.32.0-alpha.23 | 2024-12-26 | 更新机器人系列和机器人子型号。 |
| 1.0.8 | 0.29.4-rc.6 0.31.0-beta.5 0.32.0-alpha.32 | 2025-1-9 | 增加 Modbus 从站输出操作模式和心跳。 |
| 1.0.9 | 0.29.5-rc.10 0.31.0-rc.12 0.32.0-alpha.73 | 2025-3-4 | 增加读写工程运行速度百分比。 |
| 1.0.11 | 0.29.5-rc.21 0.31.0-rc.26 0.31.1-beta.7 0.32.0-alpha.117 | 2025-4-25 | 增加 Modbus 从站解除保护性停止。 |
| 1.0.12 | 0.29.5-rc.22 0.29.6-rc.1 0.31.0-rc.28 0.32.0-alpha.136 | 2025-5-12 | 增加 Modbus 从站清除错误弹窗,包括解除保护性停止和重置接口板。 |
| 1.0.13 | 0.31.1-beta.9 0.32.0-alpha.131 | 2025-5-15 | 增加 bool 寄存器。 |
| 1.14 | 0.31.1-beta.10 0.32.0-alpha.139 | 2025-5-21 | 增加切换工程。 |
| 1.14 | 0.31.1-beta.10 0.32.0-alpha.140 | 2025-5-22 | 1.增加操作模式支持输出联动模式。 2.增加输出 Modbus 版本号。 |
3.4 从站 Modbus TCP
在 【Modbus 客户端 IO设置】页面单击【从站】 打开“Modbus TCP”开关。
开启从站之后,可通过 PLC 或 modscan 等主站设备连接该从站,从站地址请参考 Modbus 从站协议中的定义。

3.5 从站 Modbus RTU
在 【Modbus 客户端 IO设置】页面单击【从站】 打开“Modbus RTU”开关。
注意:
- Modbus RTU 从站需要先将串口参数配置完成才可开启。
- 开启后串口参数不可修改,需关闭后再进行修改。

Modbus RTU 通讯依赖与控制柜或机械臂末端的 RS-485 串口通讯,不同设备的串口参数参考如下:
注意:Modbus RTU 基于串行通信的方式,其传输速率受限于 RS-485 串行接口的性能。若通信不稳定,信号状态闪烁,可将波特率值调小,若不通讯时排查选择选择的串口是否符合,可使用 Modbus 串口助手进行排查,参考文档:


控制 RS-485 串口号,控制 RS-485 包括末端 RS485 及 USB485。


3.6 Modbus 从站通用寄存器读写接口应用示例
3.6.1 Modbus 从站通用寄存器介绍
为了方便用户使用自定义信号实现 PLC (主站)与控制器之间的通信,Modbus 从站提供了专用的可读写的通用寄存器,通用寄存器的地址为 300 ~ 525。

通用寄存器读写示例,两种典型的通用寄存器读写示例:
- 使用 SDK 调用接口读写对应地址的通用寄存器信号。
- 使用工程(Lua)脚本读写对应地址的通用寄存器信号。
3.6.2 Modbus TCP 读写通用寄存器
测试环境描述:
现采用 Modbus TCP 通信方式,用 Modbus 调试助手(Modbus Poll)来模拟 PLC 主站与 Modbus TCP 从站进行通信,Modbus 调试助手的相关地址信号设置如下:

3.6.2.1 SDK 读写通用寄存器
读取通用寄存器:
通过 SDK 读取 Modbus 信号的核心步骤:
调用 modbusAddSignal 添加对应地址的信号。
使用 modbusGetSignalStatus 获取对应地址的信号值。
使用 modbusDeleteSignal 删除该信号。
使用示例:使用 SDK 读取 Modbus 从站中地址为 300、301、303 的通用寄存器,具体代码逻辑如下:
c++// 读通用寄存器 void exampleModbusSlaveRead(RpcClientPtr impl) { // 根据从站地址新建对应地址的保持寄存器信号 impl->getRegisterControl()->modbusAddSignal( MODBUS_SLAVE_IP, 1, 300, 0x03, "READ_HOLDING_REGISTER_300", true); impl->getRegisterControl()->modbusSetSignalUpdateFrequency( "READ_HOLDING_REGISTER_300", 10); impl->getRegisterControl()->modbusAddSignal( MODBUS_SLAVE_IP, 1, 301, 0x03, "READ_HOLDING_REGISTER_301", true); impl->getRegisterControl()->modbusSetSignalUpdateFrequency( "READ_HOLDING_REGISTER_301", 10); impl->getRegisterControl()->modbusAddSignal( MODBUS_SLAVE_IP, 1, 303, 0x03, "READ_HOLDING_REGISTER_303", true); impl->getRegisterControl()->modbusSetSignalUpdateFrequency( "READ_HOLDING_REGISTER_303", 10); std::this_thread::sleep_for(std::chrono::seconds(1)); int i = 30; while (i--) { // 获取对应地址的保持寄存器信号的值 auto ret0 = impl->getRegisterControl()->modbusGetSignalStatus( "READ_HOLDING_REGISTER_300"); std::cout << "READ_HOLDING_REGISTER_300:" << ret0 << std::endl; auto ret1 = impl->getRegisterControl()->modbusGetSignalStatus( "READ_HOLDING_REGISTER_301"); std::cout << "READ_HOLDING_REGISTER_301:" << ret1 << std::endl; auto ret3 = impl->getRegisterControl()->modbusGetSignalStatus( "READ_HOLDING_REGISTER_303"); std::cout << "READ_HOLDING_REGISTER_303:" << ret3 << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); } // 结束后删除信号 impl->getRegisterControl()->modbusDeleteSignal("READ_HOLDING_REGISTER_300"); impl->getRegisterControl()->modbusDeleteSignal("READ_HOLDING_REGISTER_301"); impl->getRegisterControl()->modbusDeleteSignal("READ_HOLDING_REGISTER_303"); }读取的结果如下:

写入通用寄存器:
通过 SDK 写入 Modbus 通用寄存器的步骤:
使用 SDK 调用 modbusAddSignal 添加对应地址的信号。
使用 modbusSetOutputSignal 写入对应地址的信号值。
使用 modbusDeleteSignal 删除该信号。
使用示例:使用 SDK 写入 Modbus 从站中地址为 302 的通用寄存器,具体代码逻辑如下:
// 写保持寄存器 void exampleModbusSlaveWrite(RpcClientPtr impl) { // 根据从站地址新建对应地址的保持寄存器信号 impl->getRegisterControl()->modbusAddSignal( MODBUS_SLAVE_IP, 1, 302, 0x03, "WRITE_HOLDING_REGISTER_302", true); std::this_thread::sleep_for(std::chrono::seconds(1)); // 写入对应地址保持寄存器的值 impl->getRegisterControl()->modbusSetOutputSignal( "WRITE_HOLDING_REGISTER_302", 25); std::this_thread::sleep_for(std::chrono::seconds(1)); // 结束后删除信号 impl->getRegisterControl()->modbusDeleteSignal( "WRITE_HOLDING_REGISTER_302"); }实现效果:

3.6.2.2 工程脚本读写通用寄存器
读取通用寄存器:
实现目标:使用 Modbus 调试助手,设置 Modbus 从站中地址为 300 的通用寄存器值为 10。

示例代码:
--建立 modbus 信号,(ip,站号,寄存器起始地址,功能码名,字) modbusAddSignal("127.0.0.1,502",1,300,0x03,"READ_HOLDING_REGISTER_300",true) -- 获取 modbus 的寄存器的值,并赋值给变量,赋值给变量是为了方便在示教器上查看 tmp0=modbusGetSignalStatus("READ_HOLDING_REGISTER_300") -- 删除指定名称的信号 modbusDeleteSignal("READ_HOLDING_REGISTER_300")实现效果:在示教器中通过编写脚本,获取地址为 300 的信号值,可以看到获取的值 tmp0 为10。

写入通用寄存器:
实现目标:在示教器中通过编写脚本,将地址为 302 的信号值设置为 88。
示例代码:
--建立modbus信号,(ip,站号,寄存器起始地址,功能码名,字) modbusAddSignal("127.0.0.1,502",1,300,0x03,"WRITE_HOLDING_REGISTER_300",true) --写入modbus的值,并赋值给变量,赋值给变量是为了方便在示教器上查看 tmp0 = modbusSetOutputSignal("WRITE_HOLDING_REGISTER_300",88) --删除指定名称的信号 modbusDeleteSignal("WRITE_HOLDING_REGISTER_300")实现效果:使用 Modbus 调试助手可以看到地址为 302 的通用寄存器值为 88。

3.6.3 Modbus RTU 读写通用寄存器
测试环境描述:
现使用 Modbus RTU 通信方式,用编程调用接口方式和 Modbus RTU 从站进行通信。
由于串口通信时,Modbus RTU 从站不支持同时连接多个 Modbus 主站,所以此处不使用 Modbus 调试助手来辅助测试,而是通过调用接口获取相应地址的信号值来查看信号变化是否正确。
选择两个可以通信的串口号,本次测试使用的是
/dev/ttyS0和/dev/ttyS1,/dev/ttyS1分配给 Modbus RTU 从站使用,/dev/ttyS0在编程调用接口时使用。开启 Modbus RTU 从站,相关配置如下图:

重要:
进行串口通信时,请确保所用两个串口号能够正常通信,可以使用 cutecom 等调试助手来辅助测试确认。
同一串口号不能同时被多个主站或从站使用。
3.6.3.1 SDK 读写通用寄存器
通过 SDK 读写通用寄存器示例流程:
- 调用 modbusAddSignal 添加对应地址的信号。
- 调用 modbusGetSignalStatus 读取对应地址的信号值,查看地址存储的初始值。
- 调用 modbusSetOutputSignal 写入对应地址的信号值。
- 调用 modbusGetSignalStatus 读取对应地址的信号值。
- 最后使用 modbusDeleteSignal 删除该信号。
下面使用 SDK 读写 Modbus 从站里地址为 302 的通用寄存器,具体代码逻辑如下:
c++// 使用 Modbus RTU 读写保持寄存器 #define MODBUS_SERIAL_PORT "/dev/ttyS0,115200,N,8,1" void exampleModbusRtu(RpcClientPtr impl) { // 根据从站地址新建对应地址的保持寄存器信号 impl->getRegisterControl()->modbusAddSignal( MODBUS_SERIAL_PORT, 1, 302, 0x03, "HOLDING_REGISTER_302", true); std::this_thread::sleep_for(std::chrono::seconds(1)); // 获取对应地址的保持寄存器信号的值 auto ret0 = impl->getRegisterControl()->modbusGetSignalStatus( "HOLDING_REGISTER_302"); std::cout << "读取 --> HOLDING_REGISTER_302:" << ret0 << std::endl; // 写入对应地址保持寄存器的值 impl->getRegisterControl()->modbusSetOutputSignal("HOLDING_REGISTER_302", 66); std::cout << "将 66 写入 HOLDING_REGISTER_302 的值" << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); // 获取对应地址的保持寄存器信号的值 auto ret1 = impl->getRegisterControl()->modbusGetSignalStatus( "HOLDING_REGISTER_302"); std::cout << "读取 --> HOLDING_REGISTER_302:" << ret1 << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); // 写入对应地址保持寄存器的值 impl->getRegisterControl()->modbusSetOutputSignal("HOLDING_REGISTER_302", 88); std::cout << "将 88 写入 HOLDING_REGISTER_302 的值" << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); // 获取对应地址的保持寄存器信号的值 auto ret2 = impl->getRegisterControl()->modbusGetSignalStatus( "HOLDING_REGISTER_302"); std::cout << "读取 --> HOLDING_REGISTER_302:" << ret2 << std::endl; std::this_thread::sleep_for(std::chrono::seconds(1)); // 结束后删除信号 impl->getRegisterControl()->modbusDeleteSignal( "WRITE_HOLDING_REGISTER_302"); }从下面的输出结果里可以看到,地址为 302 的通用寄存器的初始值为 0。写入 66 后,获取的值为 66。写入 88后,获取的值为 88 。说明 SDK 可以正常读写 Modbus 从站里的通用寄存器。

3.6.3.2 工程脚本读写通用寄存器
实现目标:在示教器中通过编写脚本来实现以下流程,且每次获取的信号值都赋值给 tmp0。
- 调用 modbusGetSignalStatus 获取地址为 300 的信号值,
- 调用 modbusSetOutputSignal 将地址为 300 的信号值设置为 88。
- 调用 modbusGetSignalStatus 获取地址为 300 的信号值。
- 调用 modbusSetOutputSignal 将地址为 300 的信号值设置为 66。
示例代码:
--建立modbus信号,(设备信息,站号,寄存器起始地址,功能码,名,字) modbusAddSignal("/dev/ttyS0,115200,N,8,1",1,300,0x03,"HOLDING_REGISTER_300",true) -- 获取modbus的寄存器的值,并赋值给变量,赋值给变量是为了方便在示教器上查看 tmp0=modbusGetSignalStatus("HOLDING_REGISTER_300") --写入modbus的值,并赋值给变量,赋值给变量是为了方便在示教器上查看 modbusSetOutputSignal("HOLDING_REGISTER_300",88) -- 获取modbus的寄存器的值,并赋值给变量,赋值给变量是为了方便在示教器上查看 tmp0=modbusGetSignalStatus("HOLDING_REGISTER_300") --写入modbus的值,并赋值给变量,赋值给变量是为了方便在示教器上查看 modbusSetOutputSignal("HOLDING_REGISTER_300",66) -- 获取modbus的寄存器的值,并赋值给变量,赋值给变量是为了方便在示教器上查看 tmp0=modbusGetSignalStatus("HOLDING_REGISTER_300") -- 删除指定名称的信号 modbusDeleteSignal("READ_HOLDING_REGISTER_300")实现效果:可以看到 tmp0 的值在 66 和 88 之间变化。

4. 接口应用
4.1 modbusSendCustomCommand 接口功能说明 & 注意事项
- 将用户指定的命令发送到指定 IP 地址上的 Modbus 单元。
- 由于不会接收到响应,因此不能用于请求数据,读数据的功能码暂不可用。
- 用户负责提供对所提供的功能码有意义的数据。
- 内置函数负责构建 Modbus 帧,因此用户不需要关心命令的长度,不需要输入 CRC 格式的数据。
4.2 参数定义及格式
// 接口定义
int modbusSendCustomCommand(const std::string &device_info,int slave_number, int function_code, const std::vector<uint8_t> &data);
// device_info: 设备信息
* 设备信息是 RTU 格式,
* 例如:"serial_port,baud,parity,data_bit,stop_bit"
* (1)serial_port 参数指定串口的名称,
* 例如,在 Linux 上为"/dev/ttyS0"或"/dev/ttyUSB0",在Windows上为"\.\COM10"
* (2)baud 参数指定通信的波特率,例如 9600、19200、57600、115200 等 。
* (3)parity 参数指定奇偶校验方式,N 表示无校验,E 表示偶校验,O表示奇校验。
* (4)data_bit 参数指定数据位数,允许的值为5、6、7和8。
* (5)stop_bit 参数指定停止位数,允许的值为1和2。
*
* 设备信息是 TCP 格式,例如:"ip address,port"
* (1)ip address 参数指定服务器的IP地址
* (2)port 参数指定服务器监听的端口号
// slave_number: 指定用于自定义命令的从站号
// function_code: 指定自定义命令的功能码
* MODBUS_FC_READ_COILS 0x01 // 读线圈寄存器
* MODBUS_FC_READ_DISCRETE_INPUTS 0x02 // 读离散输入状态
* MODBUS_FC_READ_HOLDING_REGISTERS 0x03 // 读保持寄存器
* MODBUS_FC_READ_INPUT_REGISTERS 0x04 // 读输入寄存器
* MODBUS_FC_WRITE_SINGLE_COIL 0x05 // 写单线圈
* MODBUS_FC_WRITE_SINGLE_REGISTER 0x06 // 写单寄存器
* MODBUS_FC_READ_EXCEPTION_STATUS 0x07 // 读异常状态(限串行线)
* MODBUS_FC_WRITE_MULTIPLE_COILS 0x0F // 写多线圈
* MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10 // 写多个寄存器
* MODBUS_FC_REPORT_SLAVE_ID 0x11 // 报告丛机ID(限串行线)
* MODBUS_FC_MASK_WRITE_REGISTER 0x16 // 带屏蔽字写入寄存器
* MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17 // 读&写寄存器
// data: 必须是有效的字节值(0-255)
* { 0x00, 0x02, 0x00, 0x0F }
* { 0x06, 0x0A, 0x0F, 0x08, 0x00, 0x0F }4.3 调用示例
// 定义IP
#define MODBUS_IP "172.16.3.111,502"
// 建立对象
RpcClientPtr impl;
// 发送自定义数据
impl->getRegisterControl()->modbusSendCustomCommand(MODBUS_IP, 1, 0x06, { 0x00, 0x02, 0x00, 0x0F });5. 问题处理
Modbus TCP信号通信失败
修复流程:
- 排查设备与机器人之间网络是否能正常通信,首先查看是否关闭设备的防火墙,然后使用
ping命令检查网络是否能正常通信。 - 排查主站建立的信号地址在从站中是否存在,主站新建的信号对应地址在从站中必须存在,信号才能正常通信。
- 排查机器人 IP 地址是否与同一局域网下其他设备 IP 地址一致,是否产生了冲突。
Modbus RTU信号通信失败
修复流程:
排查设备与机器人之间串口通信是否正常,可以使用设备与机器人中的串口调试助手来测试串口通信状态。
排查主站建立的信号地址在从站中是否存在,主站新建的信号对应地址在从站中必须存在,信号才能正常通信。
操作步骤:
- 在机器人控制柜中使用命令安装
cutecom。
- 打开cutecom,并设置“串口号”、“波特率”、“奇偶校验”、“数据位”及“停止位”。

- 若设备端是 PLC,则用
cutecom直接连接 PLC 测试,若设备是本机电脑,可在电脑中安装串口调试助手,例如:XCOM。
- 如果
cutecom和PLC/XCOM能够相互发送数据,表示能正常通信,串口通信线路没有问题,反之,需要检查通信线路连接情况。
- 在机器人控制柜中使用命令安装
6. 常见问题
Q1. 在用无线示教器时,使用路由器来桥接网络,可能会出现 IP 能 ping 通,但是 Modbus 主站信号不通。

解决方案: 检查路由器是否配置端口转发,如果没有配置,需将 Modbus TCP 使用的端口号配置上。
