ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

汇川EASY320与SV660N伺服精准定位:MC_MoveAbsolute和MC_MoveRelative实战解析

汇川EASY320与SV660N伺服精准定位:MC_MoveAbsolute和MC_MoveRelative实战解析 做运动控制这些年我见过不少同行在汇川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的增量式编码器电机执行机构机械机构丝杆滑台导程10mm1: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。如果你再发一次Distance500就会从850mm走到1350mm。这就是最核心的区别绝对定位关注“我最终要停在哪个坐标”相对定位关注“我要从当前点走多远”。注意执行绝对定位之前必须先完成回零。否则“绝对坐标”没有基准要么坐标值完全无效要么指令直接报错。2.2 引脚与状态返回值逐个说清楚MC_MoveAbsolute和MC_MoveRelative的引脚结构几乎一样以CODESYS标准实现为准输入引脚含义Execute上升沿触发启动定位Position绝对定位的目标位置仅AbsoluteDistance相对定位的移动距离仅RelativeVelocity最大运行速度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也就是1mm1000脉冲。在这个基础上速度单位可以设成mm/s目标位置单位可以设成mm。这样程序里写Position:1200.0就是1200mm非常直观调试时也不会换算到怀疑人生。换算关系在轴参数的“单位换算”里配置输入电机每转脉冲数、丝杆导程、减速比即可。3.2 伺服驱动器脉冲模式与电子齿轮比设置SV660N这类驱动器要先用面板或调试软件设成脉冲位置模式。最常见的控制方式是Pulse/Dir——一路脉冲输出、一路方向信号。PLC发出的每一个脉冲让电机走一个“最小位置增量”这个最小的增量由驱动器的电子齿轮比决定。我的习惯是让PLC的脉冲数和机械位移之间形成整数关系。还是上面的例子编码器分辨率如果是10000脉冲/圈那电子齿轮比就配成1:1PLC发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个脉冲编码器装在丝杆末端那么同样的换算关系1mm1000脉冲。程序里用实地址读出来的脉冲数除以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运行CODESYSModbus 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这个做法的好处是即使上位机一直把命令字保持在1PLC也只在从0变到1那一瞬间触发一次定位不会重复执行。状态字的更新放在定位状态机里完成后把MW_Status写成2上位机拿到状态字就可以判断动作结束。6.3 上位机联调时的几个经验细节第一通讯扫描周期和PLC扫描周期不同步很正常不要指望命令字写入后立即就能读到状态变化。上位机轮询状态字时要做“非零等待超时判断”比如每100ms读一次等20秒还没完成就强制报警避免现场设备卡死没人知道。第二目标位置写入后最好让HMI做一个二次确认。我遇到过操作工在触摸屏上输错一个小数点导致定位飞车的情况后来在HMI脚本里加上了位置上下限判断超过物理行程范围的输入直接拒绝。软件限位也必须配合在轴参数里把正向/反向软限位设置好这是保护设备安全的最后一道软件防线。第三用GL20-2HC读回来的编码器脉冲和伺服自身的位置反馈可以同时显示在HMI上。两路数据一对比机械误差和电气误差马上就能分清楚。这个数据对比在售后排查现场问题时非常管用直接告诉对方“你看伺服说到了编码器说没到去查伺服和机械的连接”。最后说点我个人的体会这套方案前前后后跑下来我最深的感受是MC_MoveAbsolute和MC_MoveRelative本身只是两个功能块难点从来不在指令语法而在你把它放进真实设备之前有没有把轴换算、电子齿轮、回零基准、软限位这些地基打牢。尤其是绝对定位回零动作可靠性直接决定整个坐标系统的可信度相对定位则要时刻提防累积误差。如果你正在调试类似的项目建议先把轴不动、ER75、定位偏差这三类问题的排查思路背下来现场遇到任何异常都能快速定位。过程虽然折腾但看到设备按着坐标稳稳当当把每一次定位都做出来的那一刻你会觉得前面熬的夜都值了。
返回列表