第4章 Modbus与伺服驱动器对接:读写参数、控制启停、读取状态
各位同行,今天咱们聊聊Modbus和伺服驱动器的对接。说实话,这个组合在工业现场太常见了。我最早接触这个,是在一个包装机械项目上。当时客户要求用PLC通过Modbus控制三台伺服,实现同步追剪。嗯,那会儿踩了不少坑,今天把这些经验分享给你。
4.1 为什么选Modbus控制伺服?
你可能会问:现在都流行EtherCAT、Profinet了,干嘛还用Modbus?
原因其实很简单:成本低、兼容性好、调试方便。
- 很多国产伺服驱动器,标配就是Modbus RTU
- 老设备改造,PLC可能只有串口,Modbus是唯一选择
- 调试时用USB转485,笔记本直接连,不用额外工具
我在一个纺织项目里,就是用Modbus控制20多台伺服做张力控制。虽然速度比不上总线,但稳定性和成本控制得很好。
4.2 伺服驱动器的Modbus寄存器映射
每个伺服厂家的寄存器地址都不一样。但万变不离其宗,核心功能就这几类:
| 功能分类 | 寄存器地址(举例) | 说明 |
|---|---|---|
| 控制命令 | 0x2000 | 启停、急停、复位 |
| 目标速度 | 0x2002 | 单位:rpm 或 0.1Hz |
| 目标位置 | 0x2004-0x2005 | 32位,低16位+高16位 |
| 状态读取 | 0x2100 | 运行中、报警、到位等 |
| 当前位置 | 0x2102-0x2103 | 32位编码器位置 |
| 参数读写 | 0x3000-0x3FFF | PID参数、加减速时间等 |
注意:不同厂家的寄存器地址差异很大。我遇到过最坑的一次,是某品牌伺服把控制命令放在0x1000,但手册写的是0x2000。后来发现是固件版本不同。所以,拿到驱动器后第一件事:读手册,确认寄存器映射表。
4.3 通过Modbus读写伺服参数
参数读写,说白了就是读/写保持寄存器(功能码03和06)。
举个例子,我要修改伺服驱动器的电子齿轮比:
// 假设电子齿轮比分子在0x3000,分母在0x3001
// 使用Modbus功能码06写单个寄存器
// 写分子:设为10000
发送:01 06 30 00 27 10 [CRC]
// 01: 从站地址
// 06: 写单个寄存器
// 30 00: 寄存器地址0x3000
// 27 10: 数据10000 (0x2710)
// 写分母:设为1000
发送:01 06 30 01 03 E8 [CRC]
// 读回来验证
发送:01 03 30 00 00 02 [CRC]
// 返回:01 03 04 27 10 03 E8 [CRC]
// 分子0x2710=10000,分母0x03E8=1000,正确
我的习惯:写参数前,先读一次当前值。万一写错了,还能恢复。我曾经在调试时手滑写了个0到速度上限寄存器,伺服直接飞车...还好有急停。
4.4 控制伺服启停
控制启停,通常用功能码06写控制命令寄存器。常见的控制字定义:
| 控制字值 | 含义 |
|---|---|
| 0x0000 | 停止/急停 |
| 0x0001 | 正转启动 |
| 0x0002 | 反转启动 |
| 0x0004 | 故障复位 |
| 0x0008 | 点动模式 |
实际项目中,我一般这样写控制逻辑:
// 启动伺服(正转)
发送:01 06 20 00 00 01 [CRC]
// 停止伺服
发送:01 06 20 00 00 00 [CRC]
// 故障复位
发送:01 06 20 00 00 04 [CRC]
关键点:启停命令之间要加延时。我见过有人连续发启动和停止,结果伺服根本没反应。为什么?因为驱动器处理需要时间。一般建议:两次命令间隔至少20ms。
4.5 读取伺服状态
状态读取用功能码03。我通常会一次性读多个寄存器,减少通信次数。
// 读取状态寄存器0x2100-0x2103(共4个寄存器)
发送:01 03 21 00 00 04 [CRC]
// 返回示例
// 01 03 08 [状态字] [当前位置低16] [当前位置高16] [报警码] [CRC]
// 比如:01 03 08 00 01 12 34 56 78 00 00 [CRC]
// 解析:
// 状态字 0x0001:运行中
// 当前位置:0x56781234(编码器脉冲数)
// 报警码 0x0000:无报警
状态字每一位的含义,不同厂家定义不同。但常见的位定义:
- Bit0: 伺服准备好
- Bit1: 运行中
- Bit2: 报警
- Bit3: 到位信号
- Bit4: 速度到达
避坑指南:我曾经在读取状态时,只读了一个寄存器。结果发现状态更新不及时。后来改成一次读4个寄存器,包括位置和报警码,这样一次通信就能拿到所有关键信息。通信效率提升了不少。
4.6 完整通信流程示例
下面是一个完整的启停+读取状态流程:
// 1. 先读参数确认配置
发送:01 03 30 00 00 02 [CRC]
返回:01 03 04 27 10 03 E8 [CRC] // 电子齿轮比10000:1000
// 2. 设置目标速度(假设速度寄存器0x2002,单位rpm)
发送:01 06 20 02 03 E8 [CRC] // 设置速度为1000rpm
// 3. 启动伺服
发送:01 06 20 00 00 01 [CRC]
// 4. 延时20ms
// 5. 读取状态确认运行
发送:01 03 21 00 00 04 [CRC]
返回:01 03 08 00 01 12 34 56 78 00 00 [CRC]
// 状态字0x0001:运行中,无报警
// 6. 停止伺服
发送:01 06 20 00 00 00 [CRC]
// 7. 再次读取状态确认停止
发送:01 03 21 00 00 01 [CRC]
返回:01 03 02 00 00 [CRC] // 状态字0x0000:停止
4.7 常见问题与解决方案
做Modbus对接伺服,我总结了几条血泪教训:
- 通信超时问题:伺服驱动器处理Modbus命令需要时间。我一般设置超时500ms,重试3次。
- 波特率匹配:PLC和伺服必须一致。我习惯用115200,速度快且稳定。
- 终端电阻:485总线两端必须加120Ω电阻。不加的话,长距离通信会丢包。
- 地址冲突:多台伺服时,地址不能重复。我习惯用拨码开关设置,方便现场更换。
核心要点总结:
- 先读手册,确认寄存器映射
- 写参数前先读,防止误写
- 启停命令间加延时
- 一次多读几个寄存器,提高效率
- 485通信注意终端电阻和波特率
好了,Modbus对接伺服的基本操作就这些。说白了,就是读读写写,注意时序和参数匹配。你在项目中遇到什么问题,欢迎交流。
公众号:蓝海资料掘金营,微信deep3321