首页 > 全部分类 > 技术问答 > 帖子内容

支持国产踩到雷了:禾川 X3E 伺服通过 EtherCAT 接汇川 PLC 跑轴控制。 电机是 23 位绝对值编码器的。 在 PLC 里监控它的实际反馈位置(Actual Position),发现一个

联系人:1562486690196

电话/手机:联系客服

发布时间:2026-06-30 23:12

浏览:188次

支持国产踩到雷了:禾川 X3E 伺服通过 EtherCAT 接汇川 PLC 跑轴控制。 电机是 23 位绝对值编码器的。 在 PLC 里监控它的实际反馈位置(Actual Position),发现一个致命 Bug: 电机单向连续转动时,PLC 读到的位置脉冲数总体是递增的,但是在某些固定的关口(比如累计脉冲到 65536、131072 这些 216 的整倍数时),数值会瞬间向上或者向下‘蹦跳’个几十个脉冲,然后又继续正常递增。 导致我的闭环控制系统每次到了这个地方就会因为‘瞬时速度过大’而发生机械抖动。 这绝对是驱动器往 EtherCAT 总线上传数据时,高低 16 位拼接逻辑写错了,厂商打死不承认,有大佬能提供补丁或者解决办法吗?
明扬工控技术客服2026-06-30 23:20:30
答复内容:亲,这个先别急着认定是禾川驱动器 EtherCAT 高低 16 位拼接 Bug。
你说跳点固定在:

65536
131072
196608
……

这个特征太明显了:这是 2^16 边界,不是 23 位绝对值编码器的边界。

23 位编码器单圈边界应该是:

2^23 = 8388608 脉冲/圈

所以它每到 65536、131072 这种关口跳一下,更像是PLC 侧、PDO 映射侧、数据类型侧、位置展开算法侧碰到了 16 位边界,而不是编码器本体或驱动器绝对位置原始数据坏了。

CiA402 里常用的 0x6064 Position actual value 本来就是 32 位 DINT 位置实际值,不应该拆成两个 16 位去自己拼;很多 EtherCAT/CiA402 资料也把 0x6064 定义为 32-bit / DINT 的实际位置对象。

一、第一嫌疑:PLC 把 32 位位置拆成两个 WORD 读了

最常见写法是这样:

LowWord  := PDO_Word0;
HighWord := PDO_Word1;
ActualPos := HighWord * 65536 + LowWord;

看起来没问题,但如果 LowWord 和 HighWord 不是同一个 EtherCAT 周期的快照,就会出事。

尤其在低 16 位从:

65535 → 0

翻转的瞬间,如果 PLC 读到:

低字已经更新
高字还没更新

或者反过来,就会造成一个很短暂的错误位置。

你说“只蹦几十个脉冲”,不是蹦 65536 个脉冲,也很像这种情况:

PLC 读数周期
EtherCAT PDO 更新周期
速度计算周期
三者不同步

低字翻转附近,位置被采到一个“半新半旧”的组合,速度差分就被放大成尖峰。

正确做法是:

不要拆 WORD
直接把 0x6064 映射成 DINT / LINT
在同一个任务周期里一次性读取
不要在不同程序段、不同任务里分别取高低字
二、第二嫌疑:PDO 映射长度错了,只映射了低 16 位

要检查汇川 PLC 的 EtherCAT 配置里,Actual Position 到底是不是:

Index: 0x6064
Subindex: 0
Length: 32 bit
Type: DINT / INT32

如果配置成了:

WORD
UINT
INT
16 bit

那到 65535 附近一定会出怪事。

有些软件界面会把 PDO 显示成两个 WORD,这不代表你应该在程序里按两个 WORD 用。要看最终变量类型是不是 32 位有符号整型。

三、第三嫌疑:符号扩展或 UINT / DINT 转换错了

位置实际值通常按有符号 32 位处理。
如果 PLC 程序里用了:

UINT
WORD
INT
DWORD
REAL

再转来转去,很容易在 16 位边界出毛刺。

尤其要查这些写法:

WORD_TO_INT
INT_TO_DINT
UINT_TO_DINT
SHL(HighWord, 16)
HighWord * 65536
LowWord + HighWord

安全写法应该是:

ActualPos_DINT : DINT;

然后 EtherCAT PDO 直接绑定到这个 DINT 变量。
速度计算也用:

DeltaPos := ActualPos_DINT - LastActualPos_DINT;

不要先转 INT,也不要用 REAL 做原始位置差分。

四、第四嫌疑:你用的是绝对编码器“单圈/多圈拼接值”,不是 CiA402 0x6064

很多伺服除了 0x6064,还会提供厂家对象,例如:

单圈位置低位
单圈位置高位
多圈圈数
编码器原始值
机械位置
反馈位置

如果你读的是厂家扩展对象,而不是标准 0x6064,那 PLC 可能真的在读两个分开的量:

单圈低 16 位
单圈高 16 位
多圈计数

这类数据如果没有驱动器内部一次性锁存,主站自己拼接时就容易在 16 位进位点跳动。

所以建议先做一个对比:

A:PLC 当前读到的 Actual Position
B:驱动器调试软件里显示的实际位置
C:SDO 直接读 0x6064:0 的值
D:PDO 映射进 PLC 的 0x6064 值

如果 B、C 都平滑,只有 D 或 PLC 程序变量跳,那就是 PLC 映射/程序问题。

五、第五嫌疑:速度计算没有做边界保护

你说“闭环系统因为瞬时速度过大而机械抖动”,这里也要小心。

很多人速度计算是:

Velocity := ActualPos - LastActualPos;

如果 ActualPos 偶发毛刺几十个脉冲,速度就会被放大。
如果再拿这个速度直接进闭环,会把机械打一下。

即使最终查明是映射问题,闭环程序也应该加保护:

如果 DeltaPos > 本周期最大可能位移 × 2
则判为异常采样,不参与速度计算
保持上一周期速度
记录一次 position glitch

这不是掩盖问题,而是运动控制里必须有的输入防毛刺逻辑。

六、怎么快速证明是不是驱动器 Bug?
1. 用 EtherCAT 抓包或主站在线监控看原始 PDO

重点看 0x6064 的 4 个字节。

比如位置在 65536 附近,正常应该是:

65535 = 16#0000FFFF
65536 = 16#00010000
65537 = 16#00010001

EtherCAT 小端显示时,字节顺序会是:

65535:FF FF 00 00
65536:00 00 01 00
65537:01 00 01 00

如果抓包里原始 4 字节是连续的,而 PLC 变量跳,那就是 PLC 映射或程序问题。

如果抓包里 4 字节本身就跳,那才有资格怀疑驱动器固件。

2. 把 0x6064 直接映射成 DINT

临时建一个最简单工程:

只映射:
6041 Statusword
6064 Position actual value
606C Velocity actual value

不做高低字拼接
不做缩放
不做闭环
只记录原始 DINT

让电机慢慢单向转过 65536、131072。

如果这个原始 DINT 不跳,说明原程序错了。

3. 用 SDO 周期读 0x6064 对照 PDO

虽然 SDO 不适合实时控制,但用来诊断很好:

PDO ActualPos
SDO 0x6064 ActualPos
驱动器软件 ActualPos

三者对照。

结果判断:

PDO 跳,SDO 不跳:PDO 映射/主站解析问题
PDO 和 SDO 都跳:驱动器实际对象有问题
只有 PLC 闭环变量跳:程序处理问题
七、现场临时解决办法

如果现在项目急着跑,可以先这样做:

1. 0x6064 直接映射为 DINT,不再拆 WORD
2. EtherCAT 任务和运动控制任务放同一周期
3. 只在 EtherCAT 数据更新后读取位置
4. 速度差分加最大位移限幅
5. 遇到 1 个周期异常跳变,丢弃该周期速度
6. 闭环控制不要直接吃未滤波的 Actual Position 差分速度

例如逻辑上可以这样:

Delta := ActualPos - LastPos;

IF ABS(Delta) > MaxDeltaPerCycle THEN
    Velocity := LastVelocity;
    GlitchCounter := GlitchCounter + 1;
ELSE
    Velocity := Delta / CycleTime;
    LastPos := ActualPos;
END_IF;

这个能先防止机械抖动,但根因还是要继续查。

八、我会优先判断的结论

这个案例最像:

第一:
0x6064 的 32 位位置值被 PLC 拆成高低 16 位处理,低 16 位进位时采样不同步。

第二:
EtherCAT PDO 映射长度或 PLC 变量类型错,把 32 位 DINT 当成 WORD/UINT/INT 用。

第三:
程序里做了高低字拼接、符号扩展或 REAL 转换,在 65536 边界出错。

第四:
读的不是标准 0x6064,而是厂家单圈/多圈/低高字扩展对象,主站自己拼接时没有锁存。

第五:
速度差分没有异常采样保护,一个几十脉冲的小毛刺被放大成瞬时速度冲击。

一句话:

23 位编码器不会在 65536 这种 16 位边界天然出问题;65536、131072 固定关口跳动,第一反应应该查 32 位位置值在 PLC 侧有没有被拆 WORD、错类型、错同步。先抓原始 PDO 的 4 个字节,如果 EtherCAT 帧里的 0x6064 连续,厂商驱动器就不是第一嫌疑。
对不起,请登录后再发表评论!

触屏端
扫一扫手机也能发信息
明扬工控商城-工控网-工控自动化真品,一站式专业服务!