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 快速入门
打开ARCS软件,Modbus位于 配置--现场总线--Modbus
2.4 Modbus TCP
单元页面,依次点击添加Modbus单元--TCP模式
Modbus TCP:使用 TCP/IP 连接,不需要校验和计算,可配置设备名称、从站编号、 IP 地址(与目标设备在同一网段),端口号参数。配置IP地址后可点击测试,弹出测试成功表示可以与目标设备通讯,反之则与目标设备不可进行通讯,需检查与目标设备是否在同一网段,防火墙是否关闭等。
信号页面,选择添加Modbus信号
01:COIL STATUS(线圈状态):用于读取和控制远程设备的开关状态,通常用于控制继电器等开关设备。
02:INPUT STATUS(输入状态):用于读取远程设备的输入状态,通常用于读取传感器等输入设备的状态。
03:HOLDING REGISTER(保持寄存器):用于存储和读取远程设备的数据,通常用于存储控制参数、设备状态等信息。
04: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单元--RTU模式
选择串口号,波特率,奇偶校验,数据位,停止位
注意:Modbus RTU 基于串行通信的方式,其传输速率受限于 RS-485 串行接口的性能;若通信不稳定,信号状态闪烁,可将波特率值调小,若不通讯时排查选择选择的串口是否符合,可使用Modbus串口助手进行排查,参考文档:
Modbus RTU 通讯依赖于控制柜或机械臂末端的RS-485串口通讯,在Modbus的串口选择可以参考如下
控制RS-485串口号,控制RS-485包括末端RS485及USB485
信号页面,选择添加Modbus信号,信号类型如图中标号1所示
01:COIL STATUS(线圈状态):用于读取和控制远程设备的开关状态,通常用于控制继电器等开关设备。
02:INPUT STATUS(输入状态):用于读取远程设备的输入状态,通常用于读取传感器等输入设备的状态。
03:HOLDING REGISTER(保持寄存器):用于存储和读取远程设备的数据,通常用于存储控制参数、设备状态等信息。
04:INPUT REGISTER(输入寄存器):用于存储远程设备的输入数据,通常用于存储传感器等输入设备的数据。
绿色表示为正常通讯,灰色,红色为不通讯,对应红色响应代码如下所示:
E1: 非法函数(0x01)查询中接收到的函数代码不是服务器(或从服务器)允许的操作,请检查从站是否存在对应信号类型
E2: 非法数据地址(0x02)在查询中收到的功能代码不是服务器(或从站)允许的操作,请检查输入的信号地址对应于远程MODBUS服务器的设置
E3: 非法数据值(0x03)查询数据字段中包含的值对于服务器(或从服务器)是不允许的值,请检查信号值对于远程MODBUS服务器上的指定地址是有效的
E4: 从属设备故障(0x04)当服务器(或从服务器)试图执行请求的操作时,发生了一个不可恢复的错误,请检查设备与接线是否损坏,尝试重启设备
E5: 应答(0x05)与发送到远程MODBUS单元的编程命令结合使用的专用功能,
E6: 从设备忙(0x06)与发送到远程MODBUS单元的编程命令一起使用,从设备(服务器)现在无法响应,请等待或尝试重新连接,并排查机器人IP地址是否与同一局域网下其他设备IP地址一致,产生了冲突
2.6 Modbus信号在配置中作为IO使用
在“配置 -> 现场总线 -> Modbus -> 信号”中添加信号类型为寄存器/数字输入,在“配置 -> 一般 -> I/O”设置可配置其 I/O 输入动作,除拖动示教外其余信号需要在联动模式下触发信号执行(也可通过OEM定制功能使其在手动模式或自动模式生效)
在配置--一般--I/O设置
为对应的Modbus 信号配置输入动作
为对应的Modbus 信号配置输出动作
可在IO-Modbus中可查看信号寄存器和数字信号的变化
2.7 modbus信号在程序中使用
1.设置节点: 可以设置Modbus数字和寄存器输出,设置数字信号的单脉冲,常与等待信号一起用做为校验确保信号设置成功才往下执行
2.等待节点: 可以使用Modbus信号做为判断,等待满足此信号程序才继续运行,常与设置信号一起使用,
3.赋值节点: 可将Modbus信号值赋值给变量进行使用
4.如果节点: 可将Modbus信号做为判断使用,满足此信号条件程序进入这个判断中
5.循环节点: 可将Modbus信号做为进入循环的条件,满足此信号条件进入循环
可在IO-Modbus中可查看信号寄存器和数字信号的变化
3. Modbus 从站
3.1 从站介绍
Modbus 从站的主要作用是响应主站(Master)的请求并执行相应的操作。实际应用中它可以用于连接和控制生产线上的各种设备,实现设备之间的信息交换和控制指令传递。
3.2 ARCS从站的用途
响应主站(Master)的请求,将机器臂的状态信息实时发送给主站;
响应主站(Master)的请求,将控制器的信息发送给主站;
测试调试时作为数据中转站,将机器臂 I/O 信号的变化实时传递给主站;
测试调试时作为数据中转站,将主站自定义信号实时传递给机器臂;
注意:通过ARCS的主站连接从站的方式,可能会存在信号延时,仅在调试时候使用,不可在程序中使用,若需要在程序中对从站进行寄存器的读写可以参考下文 3.4通用寄存器的读写示例
3.3 从站地址表更新位置
Modbus从站地址表位于钉盘-团队文件-ARCS-对外文件夹-Modbus从站中进行更新,若您是使用客户,可联系本公司技术服务部技术人员获取,若您是技术服务人员可自行获取
3.4 Modbus TCP
开启 Modbus TCP
开启从站之后,就可以使用其它的主站列如PLC或modscan来连接该从站,从站地址请参考 Modbus 从站协议中的定义;
3.5 Modbus RTU
开启Modbus从站
注意:Modbus RTU从站需要先将串口串口参数配置完成,开启后不可修改,需关闭后进行修改
Modbus RTU 通讯依赖于控制柜或机械臂末端的RS-485串口通讯,在Modbus的串口选择可以参考如下
注意:Modbus RTU 基于串行通信的方式,其传输速率受限于 RS-485 串行接口的性能;若通信不稳定,信号状态闪烁,可将波特率值调小,若不通讯时排查选择选择的串口是否符合,可使用Modbus串口助手进行排查,参考文档:
控制RS-485串口号,控制RS-485包括末端RS485及USB485
3.6 Modbus 从站通用寄存器读写接口应用示例
3.6.1 Modbus 从站通用寄存器介绍
为了方便用户使用自定义信号实现PLC(主站)跟控制器通信,Modbus 从站提供了专用的可读写的通用寄存器,通用寄存器的地址为300~525;
通用寄存器读写示例,两种典型的通用寄存器读写示例:
- 使用 SDK 调用接口读写对应地址的通用寄存器信号;
- 使用工程(Lua)脚本读写对应地址的通用寄存器信号;
测试环境描述:
现使用 Modbus 调试助手(Modbus Poll)来模拟 PLC 主站与 Modbus 从站进行通信;Modbus 调试助手的相关地址信号设置如下:
3.6.2 SDK 读写通用寄存器
(1) 读通用寄存器:
使用 SDK 调用 modbusAddSignal 添加对应地址的信号,然后使用 modbusGetSignalStatus 获取对应地址的信号值,最后使用 modbusDeleteSignal 删除该信号;下面使用 SDK 读 Modbus 从站里地址为300、301、303的通用寄存器,具体代码逻辑如下:
// 读通用寄存器
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");
}
读取的结果如下:
(2) 写通用寄存器:
使用 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.3 工程脚本读写通用寄存器
(1) 读通用寄存器:
使用 Modbus 调试助手,设置 Modbus 从站里地址为 300 的通用寄存器值为10;
在示教器中通过编写脚本,获取地址为300的信号值,可以看到获取的值 tmp0 为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")
(2) 写通用寄存器:
--建立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")
在示教器中通过编写脚本,将地址为302的信号值设置为88;
使用 Modbus 调试助手可以看到地址为 302 的通用寄存器值为88;
4. 接口应用
5.1 modbusSendCustomCommand接口功能说明&注意事项
- 将用户指定的命令发送到指定IP地址上的Modbus单元。
- 由于不会接收到响应,因此不能用于请求数据,读数据的功能码暂不可用。
- 用户负责提供对所提供的功能码有意义的数据。
- 内置函数负责构建Modbus帧,因此用户不需要关心命令的长度,不需要输入CRC格式的数据。
5.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 }
5.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
能够相互发送数据,表示能正常通信,串口通信线路没有问题,反之,需要检查通信线路连接情况;