从第一次调试双轴同步设备那天起,我就栽了个大跟头:从轴在机床启动时还能跟上主轴,跑了半分钟位置就开始慢慢漂,最后直接触发跟随误差报警。查了一圈,发现问题根本不在伺服参数,而在PLC程序里对同步阶段的管理太粗糙。后来用了汇川中型PLC做纯ST语言重写整个轴控逻辑,才真正把同步这件事理顺。这篇文章就围绕这条主线展开,适合那些刚接触中型PLC、想用结构化文本实现双轴同步设备的开发者,也适合做过梯形图但想换一种更清晰的编程思路的同行。
1. 双轴同步设备为什么需要中型PLC和ST语言
先说为什么不用小型PLC。小型PLC也能做双轴定位,但所谓“同步”通常是靠插补指令或固定的电子齿轮模块。轴少、速度低、加减速要求不苛刻的时候,小型PLC完全够用。可一旦涉及剪裁、飞锯、追剪这类工艺,从轴要在主轴运行的任意相位完成加速、切入、同步运行、退出、返回这一整套动作,小型PLC的梯形图写起来会非常吃力。
汇川中型PLC在这类场景的优势体现在三个地方。第一是轴资源充足,一个CPU挂多根总线轴,不用像小型PLC那样从外部再加运动控制模块;第二是原生支持IEC 61131-3标准的结构化文本,也就是ST语言,复杂算法、数组、结构体、自定义功能块都能直接写;第三是调试手段友好,支持在线监视、强制变量、波形追踪,程序出问题时不用靠眼睛一遍一遍盯指示灯。
ST语言给初学者带来的最大好处,是代码结构天然更接近普通软件开发。你把一段“使能、回零、等待位置到达”的逻辑封装成一个功能块,接口、内部变量、状态一目了然。以后再做同类设备,直接复制功能块,改参数,接主轴和从轴的地址就行,比在梯形图里逐行找触点快得多。
不过也要泼一盆冷水:ST语言不背工艺的锅。它只是表达工具。双轴同步能不能做好,核心在于你清不清楚设备工艺在每个阶段要求什么——主轴和从轴的速比是多少、同步区在哪里、从轴在哪个相位开始加速、哪个相位必须退出。把这些理清楚了,ST代码只是把工艺翻译成机器指令。这也正是本文接下来要解决的主要问题。
2. 从设备工艺反推轴控方案,再动手写代码
很多人一上来就写代码,这是双轴同步项目最常见的翻车原因。轴控程序写到最后发现来回改结构,往往就是因为工艺没有先转化成运动控制需求。我建议先花半小时画一张表,把设备动作写出来,再决定用电子齿轮还是电子凸轮。
2.1 先分清“电子齿轮”和“电子凸轮”
拿最常见的双轴送料裁切设备举例。主轴是送料辊,从轴是旋转裁刀。如果产品切长固定、主轴匀速,从轴只需要和主轴保持一个固定速度比,这是标准的电子齿轮,MC_GearIn一条指令就能解决。
但切长要频繁变化,或者主轴速度不是恒定,裁切位置有严格要求,这时从轴不能简单按比例跟转。它要在主轴转过特定角度时完成一次切入和返回,速度和主轴之间是非线性关系,必须用电子凸轮,也就是MC_CamIn。电子凸轮本质上是一张“主轴位置→从轴位置”的映射表,PLC根据主轴位置查表,实时算出从轴的目标位置。
初学者最容易搞错的是:电子齿轮也能让从轴在某个区间内同步,但它无法描述“从轴先加速追上、再同步走一段、然后减速返回”这类复杂曲线。曲线上每一点的速度、加速度都要单独控制,只能走电子凸轮。
2.2 用一张表抽象设备工艺
对于一个带追剪功能的双轴设备,我一般会先写下面这种参数表:
| 参数 | 含义 | 示例值 |
|---|---|---|
| 主轴脉冲当量 | 主轴编码器每转对应的机械行程 | 100mm/转 |
| 同步区长度 | 从轴参与同步加工时的主轴行程 | 150mm |
| 返回区长度 | 从轴从同步区退出后返回起始点的主轴行程 | 120mm |
| 同步速比 | 同步区从轴/主轴的速度比 | 1.2 |
| 凸轮点密度 | 一个周期内采样的主从位置点数 | 200点 |
| 设备周期 | PLC扫描周期 | 4ms |
这张表的价值在于,它把工艺人员口中的“切得快一点”翻译成了“同步区缩短、返回速比加大”这种PLC能算的东西。接下来所有代码里的常量、数组长度、轨迹计算,都从这张表里来。
2.3 轴控方案要确定的三个问题
第一个问题:主轴和从轴的编码器/伺服反馈分别从哪里来。一般主轴是变频器加编码器,从轴是伺服电机,两者都接到总线轴配置里。第二个问题:同步切入方式。从轴初始停在等待位,凸轮启动时不能直接CamIn,必须先把从轴当前位置归零或者让从轴位置曲线与凸轮表起点对齐,否则切入瞬间会出现位置跳变。第三个问题:要不要回零。配备绝对值编码器的伺服,回零可以做得很简单,但增量编码器则必须每次上电走一次回零。
这三点不是编程问题,是方案问题。方案定了,写程序只是打字。
3. 汇川中型PLC工程搭建与纯ST代码组织
我在汇川中型PLC上做的项目,编程环境是InoProShop,工程逻辑和IEC 61131-3标准基本一致。第一次用的时候可以先从建工程和配置轴开始。
3.1 工程配置里容易被忽略的两步
新建工程后,第一件事是把设备型号选对。很多初学者新建完就往里写代码,忘了在“轴配置”里添加运动轴。汇川中型PLC的运动轴分为实轴和虚拟轴,实轴对应总线上具体的伺服站号,虚拟轴用于仿真和逻辑验证。开发阶段建议先加两根虚拟轴,把程序逻辑跑通再改成实轴。
第二件事是设好轴的单位。PLC里轴位置单位默认可能是脉冲,但做设备时用mm更直观。轴配置里把“位置单位”改成mm,并填入电机每转对应的脉冲数和减速比,后续代码中所有目标位置和速度都直接用mm和mm/s表示,避免到处除来除去。
3.2 纯ST程序怎么组织才不乱
我习惯把程序分成四层,每个程序组织单元(POU)只干一件事:
- 全局变量层(GVL):放轴引用、设备工艺参数、全局状态字。
- 轴控制功能块层:每根轴一个功能块,封装使能、回零、绝对定位、错误复位。
- 工艺控制功能块层:负责同步策略,里面调用轴控制功能块,并根据当前状态机选择执行GearIn/CamIn还是CamOut。
- 主程序层(PRG);只做循环扫描、调用功能块实例、汇总报警。
这样分层的最直接好处是,换设备型号或者把单轴设备改成双轴设备时,轴控制功能块和工艺控制功能块完全不用重写,只要在PRG里增加一个功能块实例,接上新的轴引用。
下面是一段GVL定义的示例:
VAR_GLOBAL bSystemPowerOn : BOOL; bStartSync : BOOL; bStopSync : BOOL; rMainAxisPos : LREAL; // 主轴实际位置,mm rSlaveAxisPos : LREAL; // 从轴实际位置,mm rCutLength : LREAL := 150.0; // 切长,mm rSyncLength : LREAL := 150.0; // 同步区长度,mm rReturnLength : LREAL := 120.0; // 返回区长度,mm rSlaveSpeedRatio : LREAL := 1.2; // 同步区速比 eSyncState : (SYNC_WAIT, SYNC_NOT_IN, SYNC_IN, SYNC_OUT); END_VAR注意其中eSyncState这个枚举变量。很多初学者把所有状态都用BOOL表示,程序一长就晕。用枚举类型来表示工艺阶段,状态切换逻辑直观得多,调试时一眼就能看出当前设备到底在哪一步。
4. 轴控制功能块的ST实现,让单轴逻辑先稳下来
双轴设备最怕的是从轴自己还没站稳就去同步。所以单轴功能块必须先写得足够可靠。这里我给出一个简化但完整可用的轴功能块骨架。
4.1 功能块的接口设计
接口设计的原则是:让使用方只关心业务信号,不关心轴控细节。对于一根轴,主程序需要输入的只有:使能指令、回零指令、目标位置、目标速度,以及伺服使能到位反馈。对外输出则包括轴状态、当前位置、报错代码。
FUNCTION_BLOCK FB_AxisControl VAR_INPUT bEnable : BOOL; bGoHome : BOOL; bMoveAbs : BOOL; rTargetPos : LREAL; rVelocity : LREAL; bAxisReady : BOOL; // 伺服使能反馈 END_VAR VAR_OUTPUT bRunning : BOOL; rActualPos : LREAL; wErrorCode : WORD; ePhase : (PH_IDLE, PH_ENABLING, PH_HOMING, PH_READY, PH_MOVING); END_VAR4.2 状态机是实现可靠轴控的核心
我见过不少程序把使能、回零、定位全部平铺在PRG里,每个周期无条件执行。这样一旦报警或操作顺序错误,轴可能同时被多段逻辑控制,轻则报错,重则设备撞机。功能块内部用状态机串起流程就安全得多。
CASE ePhase OF PH_IDLE: IF bEnable THEN bRunning := TRUE; ePhase := PH_ENABLING; END_IF PH_ENABLING: IF bAxisReady THEN ePhase := PH_HOMING; END_IF PH_HOMING: // bGoHome为TRUE时执行MC_Home,回零完成后进入READY IF bGoHome THEN mcHome.Execute := TRUE; // 简写:实际项目中要判断mcHome.Done ePhase := PH_READY; END_IF PH_READY: IF bMoveAbs THEN mcMoveAbs.Execute := TRUE; mcMoveAbs.Position := rTargetPos; mcMoveAbs.Velocity := rVelocity; ePhase := PH_MOVING; END_IF PH_MOVING: IF mcMoveAbs.Done THEN mcMoveAbs.Execute := FALSE; ePhase := PH_READY; END_IF END_CASE这个骨架最关键的一点是:每个阶段只允许一个运动指令处于活动状态。上一条指令的Done信号没到位之前,绝不启动下一条指令。
4.3 使能和回零顺序为什么不能省
伺服驱动器的使能反馈没有建立之前,MC_Home和MC_MoveAbsolute都不会真正执行运动。所以功能块里PH_ENABLING状态是必不可少的。很多初学者把使能和回零写到一起,以为一个周期内都能完成,结果现场偶发轴不动、报警紊乱。顺序执行,每次只推进一个阶段,问题就好定位了。
绝对编码器和增量编码器在这个环节也有区别。增量编码器必须每次上电执行回零,回零方式可以是找原点开关+Z相脉冲。绝对值编码器如果机械结构固定,可以配置为在使能后读取当前绝对位置当作零位,上电不回零也能知道轴在哪里。但这里有一个容易出问题的点:如果机械上的零位与PLC期望的坐标零点不一致,绝对值编码器反而会给你一个“看起来正确但不正确”的位置。建议绝对值系统也要在初次调试时手动校核一次坐标原点。
5. 双轴同步核心逻辑,电子齿轮和电子凸轮的落地
单轴逻辑稳定之后,双轴同步才有讨论的基础。下面分电子齿轮和电子凸轮两种场景讲落地方法。
5.1 电子齿轮的速比计算
电子齿轮用汇川中型PLC的MC_GearIn实现,主要参数是RatioNumerator和RatioDenominator。这里的分子分母是主轴速度到从轴速度的换算系数,不是随便写的。例如主轴电机每转送料200mm,从轴与主轴的实际机械速比是3:1,要实现从轴速度是主轴的1.2倍,那么分子分母需要包含机械速比和工艺速比一同折算。
numerator := rSlaveSpeedRatio * rGearRatioNumerator; denominator := rGearRatioDenominator; mcGearIn.RatioNumerator := numerator; mcGearIn.RatioDenominator := denominator;切长固定的设备,把速比固化在参数表里就行。但双轴同步项目中,更常见的需求是切长可变,这时候电子齿轮就无法胜任了,必须上电子凸轮。
5.2 用一段ST代码生成凸轮表
汇川中型PLC的电子凸轮基于主轴位置查从轴位置。这个表的数据可以外部导入,也可以直接在PLC里用ST代码生成。我偏向后者,因为切长变化时不需要重新传表,只要按新切长重算数组内容。
下面是生成一段追剪凸轮表的简化思路:
// 假设周期位置:同步区0~rSyncLength,返回区rSyncLength~rSyncLength+rReturnLength FOR i := 0 TO 199 DO rPhase := rSyncLength / 199 * i; IF rPhase <= rSyncLength THEN // 同步区:从轴位置跟随主轴位置乘速比 rCamTable[i] := rPhase * rSlaveSpeedRatio; ELSE // 返回区:位置从同步终点线性回到起点 rReturnPhase := rPhase - rSyncLength; rCamTable[i] := rSyncLength * rSlaveSpeedRatio * (1 - rReturnPhase / rReturnLength); END_IF END_FOR凸轮表点数是200个。实际项目中,关键不是表的点数多,而是要让同步区和返回区的连接点处速度连续。上例中返回区起点如果直接设置0位置,会造成从轴瞬间跳变。我用线性返回只是为了演示表的结构,真实追剪设备通常使用五次多项式或者正弦过渡,让连接处速度和加速度都为0。
5.3 同步工艺的状态切换
从轴同步运行过程中,系统会经历三个阶段:同步区、返回区、等待区。整个流程不能靠一条CamIn贯穿,必须在合适的相位解除凸轮、复位从轴、再等待下一个触发位置。
我在代码里用eSyncState枚举管理这个流程。当主轴位置到达凸轮启动相位、且从轴当前位置与凸轮表起点对齐,执行MC_CamIn;当主轴走过同步区终点,执行MC_CamOut并让从轴快速返回;返回结束,等待下一个启动点。
实际项目里还有更细节的问题。比如主轴是匀速还是变速,如果主轴启停频繁,凸轮表的相位计算不能只看主轴当前位置,还要结合主轴方向。主轴反转时凸轮表的方向要相应反转,否则从轴会往反方向冲。这个问题常被忽略,建议在PH_NOT_IN状态判断主轴方向后再决定是否允许CamIn。
5.4 从轴切入瞬间的位置对齐技巧
电子凸轮切入时,从轴位置必须与凸轮表起点的位置一致。如果两者相差哪怕0.5mm,切入瞬间从轴就会有一个位置阶跃,实际表现为“咔”的一下撞击。解决办法是在启动凸轮前,先让从轴执行一次绝对定位到凸轮表的起始位置,到位后再执行CamIn。这样虽然逻辑上多了一步,但能避免很多调试过程中的机械冲击。
有经验的开发者还会在同步切入前用一个小增益的位置修正,让从轴以极低速度悄悄“贴”上凸轮曲线,而不是直接跳上去。从参数上就是让速度尽可能小,等待从轴实际位置与目标位置差小于0.1mm再切入。
6. 调试、仿真以及初学者最容易踩的坑
这一部分聊实测。开发阶段尽可能用仿真把逻辑跑通,再上电联调。汇川中型PLC的仿真环境支持虚拟轴,状态机、参数表、同步逻辑都能在电脑上完整跑一遍,非常推荐先做这一步。
6.1 联机调试的正确顺序
正确的顺序是先单轴、后同步。先把从轴当成普通定位轴,使能、回零、绝对定位反复测试十几分钟,确认没有报警;然后把主轴跑起来,在主界面监视主轴位置、主轴速度两个变量是否平滑。最后再来做同步,而且第一次同步一定要把速度降到正常工艺的10%左右,先验证状态切换顺序,再逐步提速。
一次提速只能改一档,不要一次从10%直接拉到100%。同步逻辑里很多隐藏问题是加速度相关的,高速度下从轴跟不上不是程序的错,而是机械惯量超过伺服能力,这时需要改加速度曲线或者增强机械刚性,而不是改凸轮表。
6.2 几个高频问题和排查思路
我把带过的初学者最容易遇到的几个问题整理成了一张表:
| 故障现象 | 可能原因 | 排查与处理 |
|---|---|---|
| CamIn后从轴猛地跳一下 | 切入前位置没有对齐凸轮表起点 | 启动凸轮前先定位到凸轮起点 |
| 同步运行一段时间后位置漂移 | 主轴位置单位或编码器倍率设置不一致 | 核对轴配置中的单位、电子齿轮比、编码器分辨率 |
| 凸轮表加载失败 | 数组越界或点数与查询配置不匹配 | 检查凸轮表数组上界和凸轮查询点数设置 |
| 切断时相位不对 | 凸轮表同步区长度与实际送料长度不符 | 重新按实际切长计算同步区长度,并核查主轴位置反馈的滞后补偿 |
| 从轴使能后一直处于报错状态 | 伺服未上电或使能前先执行了运动指令 | 严格让状态机等到bAxisReady再切换 |
| 返回阶段设备振动明显 | 返回区速度太高或加速度曲线不连续 | 对返回区做速度规划,尽量用正弦加减速 |
调试过程中,我强烈建议把主轴位置和当前凸轮相位这两个变量放到波形监视里。同步区开始后的主轴实际位置如果和凸轮表里的相位存在持续偏差,往往不是PLC算错,而是主轴编码器反馈有滞后或者主轴速度波动。这时候去查机械和主传动,比反复改程序效率高。
6.3 个人经验:把“慢”当作调试的默认选项
最后分享一点实际操作心得。双轴同步设备出问题的时候,千万不能指望在现场快速调参数解决。以前我犯过最傻的错误就是在烧断保险丝之后,把速度比又调大了一点再试,结果第二次直接撞弯了机构。
正确的做法是,程序里预留一个全局的比例速度系数,例如rSpeedScale := 1.0,测试时把它改成0.1。这个系数的存在,等于给所有轴指令都加了统一的速度限制,不会漏掉任何一处运动指令。调试完再把系数设回1.0。这个习惯帮我在后面几个设备项目里省下了大量返工时间。
另外,程序里一定要给凸轮表生成代码留一个可以随时手动触发的测试位。切长变更后重新计算凸轮表,如果新表生成后没有生效,从轴会按旧表乱跑。这个测试位用来强制刷新表数据,并在刷新后把从轴重新定位到起点,能避免大半个小时的懵圈排查。