☰
汇川EASY320与SV660N伺服精准定位:MC_MoveAbsolute和MC_MoveRelative实战解析
2026/10/7 5:37:14 网站建设 项目流程

做运动控制这些年,我见过不少同行在汇川PLC上写定位程序时卡在同一个地方:指令明明照着手册抄了,轴就是不动,或者动了之后偏差大得离谱。其实问题往往不在指令本身,而在你还没把“定位”这件事的底层逻辑理顺。这篇文章我就用一套完整可落地的方案来讲——汇川EASY320 PLC作为控制器,搭配GL20-2HC高速计数模块接入外部脉冲传感器,驱动SV660N伺服,在CODESYS环境下用MC_MoveAbsolute和MC_MoveRelative实现精准定位。无论你是第一次接触PLCopen运动控制,还是已经在现场被故障码折磨过,这篇文章都会对你有用。

1. 定位方案是从哪来的:EASY320、GL20-2HC和伺服怎么搭

1.1 一个典型的精准定位需求长什么样

先说我做的这个项目。一条自动上料线,某工位需要把工件从接料位推到加工位,加工完之后再推走。听起来简单,实际要求却很具体:接料位到加工位的距离固定,但不同批次工件尺寸有差异,所以每次推进量不是固定值,有时需要走到一个绝对坐标点,有时需要从当前位置再走一段相对距离;重复定位精度要求±0.1mm;节拍要求不能太慢,否则影响整线产量。

这种需求在包装、锂电、3C、机床上下料行业太常见了。核心就两个动作:走到某个绝对位置,或者相对当前位置走一段距离。这两个动作在PLCopen标准里正好对应MC_MoveAbsolute和MC_MoveRelative两条指令。

1.2 为什么选EASY320而不是传统小型PLC

很多工程师习惯用汇川H系列小型PLC做脉冲定位,DDRVI、DRVI这类指令也确实能干活。但如果你做过稍微复杂一点的多段定位、动态变速、伺服调试联动,就会明显感觉到传统小PLC的局限:程序里要自己处理加减速曲线、要自己算脉冲数、还要自己写一堆复位逻辑。

EASY320这类中型PLC用的编程软件是InoProShop,底层是CODESYS V3内核,自带PLCopen运动控制库。MC_Power、MC_Home、MC_MoveAbsolute、MC_MoveRelative这些都是现成的功能块,加减速、Jerk、软限位、原点回归这些逻辑全部封装好了。你要做的就是把参数配对、把流程写清楚,而不是从零开始造轮子。

再加上EASY320支持GL20系列扩展模块,插一个GL20-2HC高速计数模块就能接外部脉冲传感器或光栅尺编码器,把机械端的真实位置读回PLC做比对,形成准闭环控制。这种组合的性价比很高,比直接上EtherCAT总线伺服省下一大截成本,精度在绝大多数半自动设备里也完全够用。

1.3 硬件清单和电气连接的关键点

我这一套的实际配置如下:

硬件型号/说明作用
PLC本体汇川EASY320运行程序、输出脉冲指令、Modbus通讯
高速计数模块GL20-2HC2路高速计数,接入外部脉冲传感器/编码器反馈
伺服驱动器汇川SV660N接收脉冲/方向信号,驱动伺服电机
伺服电机配套SV660N的增量式编码器电机执行机构
机械机构丝杆滑台,导程10mm,1:1联轴器将旋转运动转为直线运动
触摸屏汇川IT系列或通用Modbus屏设置目标位置、速度、启动命令

接线方面,核心链路有两条。第一条是PLC脉冲输出端到伺服驱动器的Pulse/Dir端子,这条链路决定了“指令位置”。第二条是外部编码器或光栅尺到GL20-2HC的A/B相或脉冲输入通道,这条链路负责把“实际机械位置”告诉PLC。

这里有个特别容易翻车的点:编码器和GL20-2HC之间的线必须用双绞屏蔽线,而且屏蔽层要单端接地。高速计数对干扰极其敏感,现场变频器一启动,如果屏蔽没做好,计数值就会乱跳,最终表现就是定位忽好忽坏。

2. MC_MoveAbsolute和MC_MoveRelative的定位逻辑与适用场合

2.1 两条指令的目标位置分别是怎么算出来的

别看两条指令名字很像,计算逻辑完全不同。

MC_MoveAbsolute的目标位置是一个“绝对坐标值”,以机械原点为基准。举例:当前轴位置是350mm,你下发一个Absolute指令,Position填800,那么轴会正向走到800mm,实际走了450mm。

MC_MoveRelative的目标位置是“当前坐标加上增量”。同样当前在350mm,下发Relative指令,Distance填500,轴会走到850mm,实际走了500mm。如果你再发一次Distance=500,就会从850mm走到1350mm。

这就是最核心的区别:绝对定位关注“我最终要停在哪个坐标”,相对定位关注“我要从当前点走多远”。注意,执行绝对定位之前必须先完成回零。否则“绝对坐标”没有基准,要么坐标值完全无效,要么指令直接报错。

2.2 引脚与状态返回值逐个说清楚

MC_MoveAbsolute和MC_MoveRelative的引脚结构几乎一样,以CODESYS标准实现为准:

输入引脚含义
Execute上升沿触发启动定位
Position绝对定位的目标位置(仅Absolute)
Distance相对定位的移动距离(仅Relative)
Velocity最大运行速度
Acceleration加速度
Deceleration减速度
Jerk加加速度变化率,0表示不限制
Direction旋转轴方向选择,直线轴一般忽略
BufferMode缓冲模式,单轴定位默认Aborting即可
输出引脚含义
Done定位完成后置TRUE一个周期
Busy指令正在执行中
CommandAborted指令被其他指令或停止命令打断
Error错误标志
ErrorID错误代码,排查故障时主要看这个

很多初学者容易忽略Jerk这个参数。直白说,Jerk控制的是加速度变化的平滑度。Jerk设0,伺服启动和停止瞬间会有冲击;在一些带易碎工件、液体容器或龙门结构的设备上,冲击会造成抖动和移位。建议设一个适当值,比如加速度的10到20倍,运动起来会平顺很多。

2.3 实际项目里到底该用哪条指令

我的经验就三条。

第一,工位坐标固定、设备上电后先回零、然后按固定坐标走——用绝对定位。比如我这个项目里加工位在1200mm,坐标不会变,写Absolute最直观。

第二,动作是“每次推进固定距离”或“调整量由光电信号触发”——用相对定位。比如送料机构每次推50mm,推完一次停一下,再推再停,下一刀位置永远基于当前点,写Relative就不用去算累加坐标了。

第三,如果设备断过电、原点还没找到,你只知道要往前走一段,不知道当前位置,那只能先做相对定位应急;但完整工艺流程里,绝对定位之前一定要补回零,否则坐标基准是错的。

3. 开干之前做对三件事:轴参数、伺服电子齿轮、GL20-2HC接线

3.1 在InoProShop里建立运动轴并设置单位换算

新建工程时选好EASY320本体后,在PLCopen Motion里添加一个轴对象。这里我有一个强烈建议:一定要在轴参数里配好“轴单位”,不要用默认的脉冲数来做监控界面。

换算过程拿我这个项目举例。伺服电机通过1:1联轴器连丝杆,丝杆导程10mm,也就是电机转一圈、滑台走10mm。伺服驱动器的编码器分辨率我按10000脉冲/圈来设定(某些驱动器是17位131072脉冲,这里只是举例)。那么换算关系是:10000脉冲对应10mm,也就是1mm=1000脉冲。

在这个基础上,速度单位可以设成mm/s,目标位置单位可以设成mm。这样程序里写Position:=1200.0就是1200mm,非常直观,调试时也不会换算到怀疑人生。换算关系在轴参数的“单位换算”里配置,输入电机每转脉冲数、丝杆导程、减速比即可。

3.2 伺服驱动器脉冲模式与电子齿轮比设置

SV660N这类驱动器要先用面板或调试软件设成脉冲位置模式。最常见的控制方式是Pulse/Dir——一路脉冲输出、一路方向信号。PLC发出的每一个脉冲让电机走一个“最小位置增量”,这个最小的增量由驱动器的电子齿轮比决定。

我的习惯是让PLC的脉冲数和机械位移之间形成整数关系。还是上面的例子,编码器分辨率如果是10000脉冲/圈,那电子齿轮比就配成1:1,PLC发10000个脉冲电机转一圈。如果编码器分辨率是131072,而我想让PLC发10000个脉冲电机转一圈,那就需要把电子齿轮比设成131072/10000。

这里面有一个坑:电子齿轮比放大之后,PLC侧只要发一个很小的脉冲数,驱动器可能就要求电机跑一大段。如果你在程序里没算对,PLC认为只走了几毫米,实际伺服已经冲出去几十上百毫米,这就是定位事故。所以电子齿轮比和PLC侧的轴参数换算必须是同一个基准,两边对不上,后面必出问题。

3.3 GL20-2HC高速计数模块怎么接、怎么读

GL20-2HC是两路高速计数模块,可以工作在A/B相正交计数或脉冲加方向模式。在这个项目里,我用它接一个外部旋转编码器,编码器装在丝杆末端,这样PLC能够拿到丝杆真实转角对应的脉冲数,而不是只依赖伺服驱动器内部反馈。

在InoProShop的IO配置里把GL20-2HC添加进扩展机架,选择计数模式和滤波时间。A/B相模式下,模块会根据两相信号相位差自动判断正反向,计数值会加或减。程序里直接读取映射到PLC地址中的计数值,然后用脉冲当量换算成机械位置。

举个例子:如果GL20-2HC接入的编码器是2500线,在4倍频模式下每圈输出10000个脉冲,编码器装在丝杆末端,那么同样的换算关系1mm=1000脉冲。程序里用实地址读出来的脉冲数除以1000,就是当前的机械位置mm。注意GL20-2HC的计数值是32位,做换算时先转成LREAL再做除法,否则整数溢出会让你怀疑人生。

4. 手把手写代码:ST语言、上升沿触发和多段定位状态机

4.1 一个最简直接可运行的ST程序

下面这段代码是我平时做原型验证时用的最小模板,逻辑完整但没有封装成FB,适合理解用。实际项目建议再封装,后面我会说。

PROGRAM MAIN VAR bPowerOn : BOOL := TRUE; bHome : BOOL; bStartAbs : BOOL; bStartRel : BOOL; rAbsPos : LREAL := 1200.0; rRelDist : LREAL := 50.0; rVelocity : LREAL := 80.0; bAbsDone : BOOL; bRelDone : BOOL; Axis1 : AXIS_REF; fbPower : MC_Power; fbHome : MC_Home; fbAbs : MC_MoveAbsolute; fbRel : MC_MoveRelative; rCurPos : LREAL; wErrorID : WORD; END_VAR // 1. 轴使能 fbPower.Axis := Axis1; fbPower.Enable := TRUE; fbPower.bRegulatorOn := TRUE; fbPower(); wErrorID := fbPower.ErrorID; // 2. 回零 IF bHome THEN fbHome.Axis := Axis1; fbHome.Enable := TRUE; fbHome.Execute := TRUE; fbHome.Position := 0.0; END_IF fbHome(); IF fbHome.Done THEN fbHome.Execute := FALSE; END_IF // 3. 绝对定位 IF bStartAbs THEN fbAbs.Axis := Axis1; fbAbs.Execute := TRUE; fbAbs.Position := rAbsPos; fbAbs.Velocity := rVelocity; fbAbs.Acceleration := 500.0; fbAbs.Deceleration := 500.0; fbAbs.Jerk := 0.0; bStartAbs := FALSE; END_IF fbAbs(); IF fbAbs.Done THEN bAbsDone := TRUE; fbAbs.Execute := FALSE; END_IF // 4. 相对定位 IF bStartRel THEN fbRel.Axis := Axis1; fbRel.Execute := TRUE; fbRel.Distance := rRelDist; fbRel.Velocity := rVelocity; fbRel.Acceleration := 500.0; fbRel.Deceleration := 500.0; fbRel.Jerk := 0.0; bStartRel := FALSE; END_IF fbRel(); IF fbRel.Done THEN bRelDone := TRUE; fbRel.Execute := FALSE; END_IF // 5. 读取轴实际位置用于HMI显示 rCurPos := Axis1.ActualPosition;

这段代码的关键有两点。

第一,MC_Power要一直调用,放在程序最前面,不能只触发一次就扔掉。CODESYS里的运动功能块都需要每个扫描周期被调用,功能块内部状态机才会持续运行。

第二,MC_MoveAbsolute的Execute要配合“启动按钮”的上升沿,启动后马上把启动变量清掉,或者用R_TRIG上升沿检测。这样确保指令只触发一次,不至于在条件持续为TRUE的扫描周期里反复触发。

4.2 Execute上升沿这件事,理解了能少踩一半坑

PLCopen规范里,Execute是上升沿触发,也就是说信号从FALSE变TRUE的那一瞬间,指令才开始执行。只要不出现下降沿,你再怎么让它保持TRUE,它都不会重新启动。

很多新手写程序,习惯把执行条件一直挂着,比如用触摸屏一个启动按钮直接连到Execute,按钮按下一次,到位以后按钮还停在ON,这时再按第二下是没反应的,因为触点上没有新的上升沿。必须把按钮先断一次,或者程序里启动后自复位,才能产生新的上升沿。

我建议在正式项目里用R_TRIG功能块:

R_TRIG_StartAbs(CLK := bStartAbs); IF R_TRIG_StartAbs.Q THEN fbAbs.Execute := TRUE; END_IF fbAbs(); IF fbAbs.Done THEN fbAbs.Execute := FALSE; END_IF

这样既保证了只在按钮按住那一刻触发,又能在到位后把Execute清掉,下次启动一定会有新的上升沿。

4.3 多段定位用状态机,别用一堆互锁

如果你的工艺是“先绝对走到A点,再相对走50mm,停一下,再绝对到B点”,我强烈建议用一个整型状态变量来管理流程,而不是把几个启动按钮串在一起互锁。

实际项目里我经常这么写:

CASE iStep OF 0: IF bCycleStart THEN fbAbs.Execute := TRUE; iStep := 10; END_IF 10: fbAbs(); IF fbAbs.Done THEN fbAbs.Execute := FALSE; iStep := 20; END_IF IF fbAbs.Error THEN iStep := 90; END_IF 20: fbRel.Execute := TRUE; iStep := 30; 30: fbRel(); IF fbRel.Done THEN fbRel.Execute := FALSE; iStep := 40; END_IF IF fbRel.Error THEN iStep := 90; END_IF 40: // 点位到位后的稳定延时和输出控制 iStep := 0; 90: // 异常复位 fbAbs.Execute := FALSE; fbRel.Execute := FALSE; iStep := 0; END_CASE

状态机的可读性和可维护性比一坨互相置位复位的BOOL要好太多,尤其是后期加工艺流程时,你只需要在CASE里插入新状态编号就行。

4.4 同一根轴不要同时被多个运动功能块接管

一条轴在任意时刻只能有一个主控运动指令。MC_MoveAbsolute和MC_MoveRelative同时启动,或者一个正在Busy时另一个被触发,后启动的指令会按BufferMode决定是打断前者还是排队等待。默认Aborting模式是直接打断当前运动,这在绝大多数情况下不是你想要的效果。

所以在实际工程里,我会做一层“指令仲裁”:先把所有启动条件汇总到一个执行变量,在同一个扫描周期只把当前需要执行的指令置True,其他指令保持False。绝对和相对指令共用完复用同一个缓冲区,避免两个FB同时竞争一根轴。

5. 调试实录:轴不动、ER75报警、定位偏差大的排查链路

5.1 给了启动信号,伺服却一动不动,先查这三处

轴不动作是我遇到最多的问题,而且90%的情况出在“轴根本还没使能”而不是指令本身。

第一,打开MC_Power的Status输出,确认轴已经处于使能状态。MC_Power的Enable和bRegulatorOn都要为TRUE,并且要给足伺服启动时间,不要在同一个扫描周期里刚使能就触发定位指令,至少等100ms以上再发运动命令。

第二,看轴是否处于ErrorStop状态。CODESYS轴报错后会锁住,你发任何运动指令都不会执行。这时用MC_Reset复位错误状态,然后再确认ErrorID清掉了。

第三,看伺服驱动器面板有没有使能信号。很多系统里驱动器的使能端子还需要外部接线或者由PLC输出信号控制,EASY320的脉冲输出和伺服使能是两回事。PLC发脉冲了,但驱动器的使能没打开,电机照样纹丝不动。

一个有效的排查技巧:在伺服驱动器面板上直接看“位置指令”或“脉冲输入”计数值。如果PLC发了很多脉冲、面板数值在跳,说明指令已经到驱动器了,问题就在伺服侧;如果脉冲数值一直是0,那就要回查PLC的脉冲输出轴配置和程序逻辑。

5.2 ER75报警的完整排查过程

项目现场报“ER75”这类故障码的时候,先别急着备份程序,绝大部分原因是“跟随误差太大”。也就是说,驱动器发指令让电机走到某个位置,但编码器反馈回来说电机实际位置没跟上,偏差超出了驱动器设定的允许范围。

我那次现场排查的顺序是这样的:

排查步骤操作现象判断
1.机械检查手动盘动电机轴/丝杆盘不动或有异响,优先查机械卡滞
2.参数调低把程序里的速度和加速度降一半不报警了,说明加减速太猛
3.电子齿轮核对查看伺服当前电子齿轮比与PLC轴换算两边不一致会导致位置指令超出伺服能力
4.使能检查运行时监视伺服状态使能被意外断开会导致位置丢失
5.编码器反馈查看电机编码器反馈是否跳动干扰、编码器线松动会导致反馈异常

那次最后查到的情况是加速时间设得太短。速度80mm/s,加速度却给了5000mm/s²,伺服电机从0加速到80只用了16ms,机械负载偏重,实际位移跟不上指令位置,偏差越积越大,最后触发ER75。把加速度改到1000mm/s²之后,故障码再也没出现。

如果你的工艺必须用很快的加速度,那就得从机械端减负或者换更大扭矩的伺服,不能一味在软件里把这个报警屏蔽掉。安全余量不足迟早会爆发。

5.3 定位偏差分三种:固定偏差、有规律偏差、随机偏差

定位精度不好,先判断偏差的规律,别抓着伺服一顿乱调。

固定偏差,比如每次都差0.3mm。这种情况优先检查机械连接:丝杆有没有间隙、联轴器有没有打滑、同步带轮有没有松动。固定偏差常常和伺服的PID没关系,你调什么参数都调不回来,因为问题在机械传动链。

有规律的偏差,比如走得越远偏差越大。这种情况优先怀疑脉冲当量或电子齿轮比算错了。发5000个脉冲实际走了5.2mm,而不是5.0mm,倍率关系不对,一定是某个换算系数有问题。

随机偏差,时好时坏。这种最头疼,通常和现场干扰、编码器反馈抖动、伺服刚性不足有关。这时候用GL20-2HC读回来的外部编码器数据就有大用了——把实际机械位置和伺服反馈位置对比,如果外部编码器读数稳定但伺服飘,问题在伺服环;如果外部编码器读数自己就乱跳,那就是接线或者干扰的问题,先去处理屏蔽和接地。

还有一个我在现场吃过亏的细节:绝对定位到位后,不要立刻进行下一步动作。伺服虽然报了Done,但机械传动链可能还有微小弹性形变需要释放。我一般会在Done之后插入50到100ms的稳定延时,再读一次GL20-2HC的外部位置做确认,差值在允许范围之内才继续下一段流程。这个习惯帮我挽回了好几批差点报废的工件。

6. 把定位程序和HMI打通:Modbus RTU寄存器怎么分配

6.1 PLC寄存器与Modbus地址的映射关系

EASY320运行CODESYS,Modbus RTU从站功能配置好后,保持寄存器直接映射到PLC的内存地址。习惯上,我这样分配地址:

寄存器PLC地址含义数据格式
40001%MW0目标位置(整数,×10换算为mm)字
40002%MW1运行速度(整数,×10换算为mm/s)字
40003%MW2命令字:0停止、1绝对、2相对字
40004%MW3状态字:0空闲、1运行中、2完成、3报警字
40005%MW4报警代码字
40006%MW5当前实际位置高16位字
40007%MW6当前实际位置低16位字

为什么要用整数×10而不是直接传浮点数?因为Modbus RTU传输浮点数涉及大小端和双寄存器组合,不同触摸屏和上位机组态软件的字节序还可能不一致,极容易踩坑。用整数缩小十倍传输,在HMI端只需要做一次除法显示,非常稳。

位置精度需要0.1mm,乘以10够用;如果项目要求0.01mm,就乘以100。程序里再除以相应倍数得到真实值。

6.2 PLC侧命令字处理的实用逻辑

上位机或触摸屏写入命令字之后,PLC里要有对应的处理逻辑。我通常的做法是检测命令字变化而非电平,用两个变量保存上一次命令字:

wOldCmd := wCurCmd; wCurCmd := MW_Command; // 从Modbus映射地址读取 IF wCurCmd <> wOldCmd THEN CASE wCurCmd OF 1: rAbsPos := UINT_TO_LREAL(MW_TargetPos) / 10.0; bStartAbs := TRUE; 2: rRelDist := UINT_TO_LREAL(MW_TargetPos) / 10.0; bStartRel := TRUE; 0: // 停止逻辑 END_CASE END_IF

这个做法的好处是,即使上位机一直把命令字保持在1,PLC也只在从0变到1那一瞬间触发一次定位,不会重复执行。状态字的更新放在定位状态机里,完成后把MW_Status写成2,上位机拿到状态字就可以判断动作结束。

6.3 上位机联调时的几个经验细节

第一,通讯扫描周期和PLC扫描周期不同步很正常,不要指望命令字写入后立即就能读到状态变化。上位机轮询状态字时要做“非零等待+超时判断”,比如每100ms读一次,等20秒还没完成就强制报警,避免现场设备卡死没人知道。

第二,目标位置写入后最好让HMI做一个二次确认。我遇到过操作工在触摸屏上输错一个小数点导致定位飞车的情况,后来在HMI脚本里加上了位置上下限判断,超过物理行程范围的输入直接拒绝。软件限位也必须配合,在轴参数里把正向/反向软限位设置好,这是保护设备安全的最后一道软件防线。

第三,用GL20-2HC读回来的编码器脉冲和伺服自身的位置反馈,可以同时显示在HMI上。两路数据一对比,机械误差和电气误差马上就能分清楚。这个数据对比在售后排查现场问题时非常管用,直接告诉对方“你看,伺服说到了,编码器说没到,去查伺服和机械的连接”。

最后说点我个人的体会

这套方案前前后后跑下来,我最深的感受是:MC_MoveAbsolute和MC_MoveRelative本身只是两个功能块,难点从来不在指令语法,而在你把它放进真实设备之前,有没有把轴换算、电子齿轮、回零基准、软限位这些地基打牢。尤其是绝对定位,回零动作可靠性直接决定整个坐标系统的可信度;相对定位,则要时刻提防累积误差。如果你正在调试类似的项目,建议先把轴不动、ER75、定位偏差这三类问题的排查思路背下来,现场遇到任何异常都能快速定位。过程虽然折腾,但看到设备按着坐标稳稳当当把每一次定位都做出来的那一刻,你会觉得前面熬的夜都值了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询