资讯动态

TwinCAT PLC侧七段式S型加减速规划:Jerk约束与FB实现

发布时间:2026/10/16 13:43:14 来源:尧图企业网站定制
简介TwinCAT外部设定值S型加减速规划资源包面向工业自动化与运动控制开发者解决电机启停冲击大、运行中变更目标位置时难以平稳调速的问题。基于Beckhoff TwinCAT平台重点演示外部设定值发生器如何根据上位机指令动态计算S型速度曲线。压缩包共98个文件主体为54个compiled-library编译库和11个tcpou程序组织单元另含Scope测量工程、tsproj TwinCAT工程、TMC运动控制文件等调试与配置内容整体仅8.26MB便于快速下载部署。该资源已有944人学习。借助其中的PLC逻辑、速度曲线生成模块与实际工程文件可完整掌握外部设定值从接收、S型曲线建模到实时下发驱动器的实现链路掌握编码器反馈闭环与异常停机处理思路适合需要提升定位精度和动态响应能力的TwinCAT中高级开发者。1. 外部设定值做S型加减速为什么PLC侧规划比驱动器内规划更可控做运动控制的人应该都有过这种经历直接给驱动器一个目标速度设备启停总带那么一下「咯噔」导轨振动、工件抖动、步进电机丢步问题往往不在伺服本身而在加减速曲线。TwinCAT 里如果用外部设定值方式做 S 型加减速把速度规划放到 PLC 侧、每个周期往驱动器送一个目标位置治的就是这个病。相比驱动器内部的梯形加减速PLC 侧做规划的好处是曲线形状完全可控S 型曲线的加加速度Jerk是有限值机械冲击小得多而且不依赖驱动器品牌换个驱动器只要外部设定值接口一样规划代码原样复用。这套做法适合做点对点定位、龙门同步、印刷平台这类对启停平稳性有要求的设备熟悉 ST 语言就能落地。2. 七段式S曲线的边界条件把速度、加速度、加加速度的预算先算清楚2.1 梯形加减速的痛点与S型的本质梯形加减速速度曲线是直线段拼的加速段速度线性上升加速度恒定。加速度从 0 瞬间跳到最大值、再从最大值瞬间跳回 0这一跳在力学上就是无限大的加加速度。机械系统都有柔性遇到这个冲击就会振动只是有些设备刚性大、看不明显刚性差一点的负载越大越明显。S 型加减速的本质是让加速度本身也按一定斜率变化这个斜率就是加加速度Jerk单位 mm/s³。加加速度不为无穷大机械受到的冲击就是有限的听感、手感、振动曲线都会有本质区别。所以在做 S 型规划之前先要理解一个概念S 型曲线严格说分七段——加加速、匀加速、减加速、匀速、减加速、匀减速、减减速。前四段把速度从 0 加到位移中点的最大速度后三段镜像减速。每段时间长短由三个预算决定最大速度 Vmax、最大加速度 Amax、加加速度 Jerk。这三个值一旦定了整条曲线能跑多远、各段占多长全部由计算确定没有「凭感觉调」的余地。这也是为什么我建议先在纸上把公式推一遍再把公式写进代码而不是直接在 PID 参数上乱试。2.2 七段时间划分与关键公式设加加速度为 J、最大加速度为 A、最大速度为 V那么加速度从 0 升到 A 需要时间 T1 A/J这一段叫加加速段。从 A 降回 0 也需要同样的时间这就是第三段减加速段时间 T3 T1。中间如果需要保持最大加速度则第二段匀加速时间 T2 V/A - A/(2J)。注意这个式子的物理意义如果 V 不够大T2 会变成负数说明根本到不了最大速度——这就是后面要处理的短行程分支。有了 T1、T2、T3可以把七段时间全部算出来第 1 段 T1第 2 段 T2第 3 段 T3第 4 段匀速 T4第 5、6、7 段分别等于 T3、T2、T1。关键是先算临界位移也就是刚好能加速到 V 又减速回 0 的最小距离参数公式说明加加速段时间 T1A / J加速度线性上升到 A匀加速段时间 T2V/A - A/(2J)若为负说明距离不足临界位移 SminV²/A V·A/J完整七段的最小距离匀速段时间 T4(D - Smin) / VD 为总位移这个 Smin 是我做规划时最先算的一个值它决定了走完整七段还是走降速分支。很多初学的同事把 J 设得很大以为 S 曲线就是「把速度调圆一点」结果 T1 变成零点几毫秒加速度曲线几乎还是直角等于没做。J 的值决定了变加速度的时间尺度太小则曲线太陡太大则加减速过程拖太长。设备上一般先从机械允许的冲击反推 J比如负载 20kg、允许加加速度上限 2000mm/s³这个值写在需求里比写在代码里更靠谱。2.3 两个决定性参数临界位移与降速分支临界位移 Smin 是整篇文章最重要的一个数。实际项目里最常见的问题是目标位置只有 2mmVmax 设了 300mm/sAmax 设了 1500mm/s²J 设了 5000mm/s³算出来 Smin 300²/1500 300×1500/5000 60 90 150mm。要走 2mm 却按 150mm 的曲线去规划结果必然是在加速段都没走完就该减速了时间表根本排不开。处理方法是当实际距离 D 小于 Smin 时不能继续用原 Vmax要反算一个实际能达到的峰值速度 V_eff。解一元二次方程 V²/A V·A/J D得到V_eff ( -A²/J sqrt( A⁴/J² 4·A·D ) ) / 2这个速度会明显小于设定 Vmax。曲线变成五段加加速、匀加速时间变短、减加速到峰值然后镜像减速没有匀速段。更极端的情况如果距离小到连 Amax 都达不到那退化成纯加加速减加速两段加速度峰值小于 Amax。现场我一般把这种极小距离交给驱动器自带的平滑功能兜底PLC 侧只做完整七段和五段两种 profile逻辑简单、不容易出边界问题。3. 在TwinCAT里写一个可复用的S型规划FB核心代码与参数说明3.1 FB接口设计输入输出要按什么单位、什么周期在 TwinCAT 3 里我习惯把规划器封装成一个 Function Block叫 FB_SCurveExt。输入输出全部用 LREAL单位统一为 mm、mm/s、mm/s²、mm/s³。周期时间作为输入参数传入默认 1ms——这个设计是为了让 FB 不依赖具体任务周期万一调试时把任务周期改成 0.5ms 或 2ms不需要改内部代码只需要把实际周期传进来。很多翻车现场就是代码里写死 0.001改了任务周期后规划位置全部失真。FB 的接口这样设计FUNCTION_BLOCK FB_SCurveExt VAR_INPUT bExecute : BOOL; // 上升沿触发一次完整规划 rStart : LREAL; // 起点位置绝对坐标mm rTarget : LREAL; // 终点位置绝对坐标mm rVmax : LREAL; // 最大速度 mm/s rAmax : LREAL; // 最大加速度 mm/s^2 rJerk : LREAL; // 加加速度 mm/s^3 fCycle : LREAL : 0.001; // 调用周期 s默认 1ms END_VAR VAR_OUTPUT rSetpoint : LREAL; // 当前位置设定值每周期刷新 bBusy : BOOL; // 规划执行中 bDone : BOOL; // 规划完成 rVelAct : LREAL; // 规划速度监控用 rAccAct : LREAL; // 规划加速度监控用 END_VAR从使用者的角度看这个 FB 的行为是bExecute 给一个上升沿rSetpoint 就从 rStart 开始按 S 曲线走向 rTargetbDone 置位后设定值保持终点。整个过程不需要外部去管它内部状态。唯一要注意的是 bExecute 必须在 bBusyFALSE 时才能触发规划中改目标位置属于进阶话题后面单独讲。3.2 完整七段路径分段时间表与每周期增量输出核心是一个私有方法负责根据位移距离计算七段时间。我把距离判断和降速分支都放在这里METHOD PRIVATE PrepareProfile VAR_INPUT d : LREAL; // 本次运动距离恒为正mm v : LREAL; // 允许最大速度 mm/s a : LREAL; // 允许最大加速度 mm/s^2 J : LREAL; // 加加速度 mm/s^3 END_VAR VAR T1, T2, T3, T4 : LREAL; sMin : LREAL; vEff : LREAL; END_VAR // 完整七段所需的最小距离 sMin : v*v/a v*a/J; IF d sMin THEN // 距离足够走完整七段 T1 : a/J; T3 : T1; T2 : v/a - a/(2.0*J); T4 : (d - sMin)/v; aPhaseTime[1] : T1; aPhaseTime[2] : T2; aPhaseTime[3] : T3; aPhaseTime[4] : T4; aPhaseTime[5] : T3; aPhaseTime[6] : T2; aPhaseTime[7] : T1; ELSE // 距离不足降速重算解 V^2/a V*a/J d 的方程 vEff : (-a*a/J SQRT(POWER(a,4)/(J*J) 4.0*a*d)) * 0.5; T1 : a/J; T3 : T1; T2 : vEff/a - a/(2.0*J); IF T2 0.0 THEN T2 : 0.0; // 极短距离下连匀加速段都没有 END_IF aPhaseTime[1] : T1; aPhaseTime[2] : T2; aPhaseTime[3] : T3; aPhaseTime[4] : 0.0; aPhaseTime[5] : T3; aPhaseTime[6] : T2; aPhaseTime[7] : T1; END_IF这里有个细节容易看漏短距离分支的 vEff 公式假设加速度能到 Amax只降速度如果距离实在太小T2 会被截成 0此时实际加速度峰值达不到 Amax但作为工程近似是够用的。完整七段里 T2 用的是 Vmax/A - A/(2J)这个式子里的 A/(2J) 是加速度从 0 升到 A 期间走过的路程折算很多从梯形加减速转过来的人会漏掉这个修正项导致实际位移比设定多一块末尾要么过冲要么急停。3.3 周期执行体Jerk驱动数值积分有了分段时间剩下的工作就是把这条曲线一周期一周期地走出来。我用的方法是直接对 Jerk 数值积分每周期先根据当前在第几段确定 Jerk 的符号然后更新加速度、速度、位移。代码rtTrig(CLK : bExecute); IF rtTrig.Q THEN rDist : rTarget - rStart; // 带符号距离决定运动方向 rRel : 0.0; // 相对位移恒为正累计 rVel : 0.0; rAcc : 0.0; iPhase : 1; rPhaseTime : 0.0; PrepareProfile(ABS(rDist), rVmax, rAmax, rJerk); bDone : FALSE; bBusy : TRUE; END_IF dyT : fCycle; IF bBusy THEN // 根据当前段选择本周期 Jerk 符号 CASE iPhase OF 1: rJerkNow : rJerk; // 加加速加速度上升 2: rJerkNow : 0.0; // 匀加速 3: rJerkNow : -rJerk; // 减加速加速度回零 4: rJerkNow : 0.0; // 匀速 5: rJerkNow : -rJerk; // 减加速加速度反向建立 6: rJerkNow : 0.0; // 匀减速 7: rJerkNow : rJerk; // 减减速加速度回到零 END_CASE rAcc : rAcc rJerkNow * dyT; // 更新加速度 rVel : rVel rAcc * dyT; // 更新速度 rRel : rRel rVel * dyT; // 更新位置梯形积分 rVelAct : rVel; // 供监控显示 rAccAct : rAcc; // 段切换时间到就进下一段 rPhaseTime : rPhaseTime dyT; IF rPhaseTime aPhaseTime[iPhase] THEN rPhaseTime : rPhaseTime - aPhaseTime[iPhase]; iPhase : iPhase 1; IF iPhase 7 THEN rRel : ABS(rDist); // 消除积分残差 bBusy : FALSE; bDone : TRUE; END_IF END_IF // 根据方向输出带符号设定值 IF rDist 0.0 THEN rSetpoint : rStart rRel; ELSE rSetpoint : rStart - rRel; END_IF END_IF这个执行体的好处是不管分段时间表是怎么算出来的执行逻辑都是同一套不会因为 profile 是七段还是五段而出错。Jerk 在一个周期内固定加速度曲线就是标准的折线速度曲线是光滑的连续曲线。终点处强制把 rRel 置为总距离目的是消除浮点积分残差——虽然每周期误差极小但长时间往复运动会累积漂移这个强制赋值相当于给位置误差一个兜底。调用这个 FB 时还有一个常见误区有人把 rStart 写成 PLC 实时读到的实际位置而不是规划开始时的位置。外部设定值模式下实际位置有跟踪误差如果规划起点跟着实际位置飘每周期都要重新算一遍 profile曲线永远不稳定。正确做法是规划开始时把 rStart 锁定为当时的实际位置之后不许改。3.4 验证方法先看曲线再接轴代码写完不要直接接伺服我先在 PLC 里跑一个开环测试用一个周期任务调用 FB输入一段 100mm 的距离Vmax200、Amax1000、J5000然后把 rSetpoint、rVelAct、rAccAct 三个变量接到 TwinCAT Scope View 上。正常的 S 曲线速度应该是光滑的钟形加速度应该是梯形加加速度在每一段是恒定值。如果速度曲线上出现折角说明 Jerk 符号选错或者分段时间算错如果加速度曲线有毛刺说明周期时间不稳定得先解决任务配置。这一步虽然看起来啰嗦但能省下大量接线后的排查时间。我把 Scope 配置保存成了模板新项目直接导入改一下变量名就能用。波形验证通过后再把 rSetpoint 接到外部设定值通道进入下一步。4. 外部设定值怎么接把规划输出送进驱动器的三种路径4.1 路径一直接写驱动器的CSP目标位置最直接的做法是把 rSetpoint 每个周期写到驱动器的周期同步位置模式CSP目标位置寄存器。TwinCAT 里通过 EtherCAT 从站映射区操作规划 FB 输出连接到一个变量这个变量映射到从站的输出区每个周期由任务自动刷新。// 1ms 任务内 fbScurve(bExecute : bStart AND NOT fbScurve.bBusy, rStart : rStartPos, rTarget : rTargetPos, rVmax : 200.0, rAmax : 1000.0, rJerk : 5000.0); // 输出映射到从站 CSP 目标位置 stServoOutput.nCspTargetPos : LREAL_TO_DINT(fbScurve.rSetpoint * 1000.0); // 单位 mm - um注意单位换算驱动器寄存器通常要求整数微米或脉冲单位而规划器内部是浮点毫米每次写出前要乘系数并取整。取整用 LREAL_TO_DINT 会截断我一般先加 0.5 再转换避免每周期都往下取整导致速度慢一点。这个路径适合驱动器本身不支持内部平滑、或者要求设定值完全由上位机决定的场合。缺点是每个周期都必须保证实时写入一旦任务卡死驱动器报跟随误差。4.2 路径二通过NC轴的外部设定值接口如果项目里已经有 NC 轴比如用了 TwinCAT NC PTP可以不走 CSP 寄存器而是把规划好的位置作为外部设定值叠加进 NC 轴。常见做法是使用叠加运动功能块或者直接把 rSetpoint 写入轴的设定值通道并关闭 NC 轴自身的加减速规划。这条路径的坑在第 5 章会专门讲这里先给结论只要走 NC就必须确认 NC 侧的速度限制、加速度限制、加加速度限制全部设置得比 PLC 侧规划值大得多否则等于两条 S 曲线串在一起输出变成「S 的 S」动作拖沓不说还容易在交接处产生速度抖动。我一般把 NC 侧的加加速度设成 PLC 侧的三倍以上让 NC 只做跟随不参与规划。4.3 波形验收用Scope确认S曲线没有「隐形折角」接好之后先做低速小行程试跑把 rSetpoint、驱动器实际位置、跟随误差三条曲线放到一个 Scope 里看。判断标准有三个第一实际位置曲线应该跟设定值重合跟随误差不超过一个稳定的小范围第二速度曲线没有台阶或突变第三在运动结束段听不到机械「咯噔」声。这里有个容易忽略的检查点——加速度曲线。外部设定值模式下规划器输出的加速度曲线是折线如果驱动器内部又做了一阶滤波实际加速度会变圆这是正常的但如果加速度曲线上出现高频毛刺问题不在规划器而在周期抖动或 EtherCAT 同步性能。可以先用示波器看 Sync 信号和任务周期实际抖动再回头查规划器。我见过不少项目为了这事反复调 Jerk 参数最后发现是任务没设成固定周期用的还是默认的「可被中断」类型。5. 避坑排查外部S型加减速最常见的五个翻车现场5.1 双重规划叠罗汉现象接好线后第一次跑轴动作明显「肉」速度达不到设定值加速过程拖得很长波形上速度曲线起点有个小台阶。原因驱动器或 NC 轴内部也开了 S 型平滑。PLC 侧已经规划好一条 S 曲线内部平滑又按自己的 Jerk 限制再修一次等于两条曲线串联。解决确认驱动器工作在外部设定值模式时内部加减速设为直通或极大值NC 轴的加加速度设成 PLC 规划值的 3 倍以上让它的时间常数远小于 PLC 侧基本不参与整形。5.2 短行程负时间炸数组现象目标距离只有几个毫米一触发就报错数组越界或者 FB 状态卡死。原因距离小于 Smin 时如果不做降速分支T2 会算出负值数组下标和相位判断全部错乱。这是新手最先遇到也最烦的问题。解决在 PrepareProfile 里先算 Smin距离不足时必须走降速分支并判断 T20 时截成 0。现场我还会加一个超小距离保护如果距离小于 0.1mm直接不做 S 型规划把设定值一步置到目标等伺服跟随即可。5.3 周期抖动造成加速度尖刺现象Scope 看 rAccAct 曲线本应平滑的折线出现了密集毛刺电机声音发毛机械振动变大。原因FB 里用了固定的 fCycle但任务实际周期不稳定或者任务被其他高优先级任务打断导致 dyT 与实际时间不一致。加速度尖刺直接等于冲击载荷。解决把规划 FB 放在独立的固定周期任务中优先级调到最高同时读 TwinCAT 的实际循环时间并滤波后参与积分而不是用默认值 0.001。如果因为项目结构原因任务周期确实会波动可以把规划器输出的位置设定值再过一层低通滤波但要注意相位滞后不要太大。5.4 浮点累计误差越跑越偏现象单次运行终点精度没问题连续往复运行几百个循环后轴的实际停止位置慢慢偏离目标。原因每周期做浮点积分位置增量一直有舍入误差修正段结束时虽然强制对齐但之前在段切换时把残余时间带入了下一段误差会以不同方式累积。解决除了终点强制对齐还要把 rPhaseTime 的残余部分在段切换时保留并带入下一段我代码里就是这么做的保证七段总时间不漂移。如果驱动器寄存器只接受整数用带舍入的转换而不是截断转换。5.5 运行中改目标导致速度跳变现象轴还在运动中工艺信号要求改到新目标位置直接改 rTarget 后速度曲线出现突变甚至反向瞬跳。原因外部设定值模式下FB 处于 bBusy 状态时更新 rTarget内部仍在执行旧 profile两个距离冲突输出位置不再是连续函数。解决运行中改目标必须先停止再重新规划。稳妥做法是收到新目标后让轴按当前规划走完剩下行程先停稳再触发下一次 bExecute如果工艺要求不停顿就需要做一个「飞行改目标」的进阶功能让当前速度、加速度作为新 profile 的初值重新计算剩余距离的七段曲线。这个做法相对复杂下一章单独说。6. 进阶运行中改目标的最稳处理与验收习惯运行中改目标在印刷、贴装这类设备上很常见——前一个位置还没到传感器就报了新的来料停下来再走会掉节拍。最稳的处理不是往七段曲线中间硬插一段而是把「当前速度」和「当前加速度」作为新规划的初值从当前位置重新做一次完整规划。数学上只要保证新 profile 在起点处的速度、加速度和当前位置正好等于旧曲线的瞬时值拼接处就是连续的实测速度曲线看不出拼接痕迹。具体做法是把 FB 增加一组控制字bAbort 上升沿时锁存当前 rRel、rVel、rAcc 作为新起点状态然后调用 PrepareProfile 计算从当前点移动到新目标的剩余距离。因为新起点加速度不是零分段时间表的计算要复杂一些我这里给一个工程上更常用的简化方案收到改目标请求后先生成一个「降速到零」的减速 profile等轴停稳再走新目标。这个方案的代价是损失几百毫秒节拍但胜在稳定尤其适合对位置精度要求高的场合因为它在数学上不需要推导带初速度的分段公式出错概率大幅降低。如果确实要做飞行改目标我的习惯是做一个模拟验证脚本Mathcad 或者 Excel 都行把旧曲线和新曲线的速度、加速度在切换点对齐画在同一张图上检查连续性。这事不能省因为拼接点的速度差哪怕只是 1mm/s在机械上都会表现为一次轻微冲击拼接点加速度差则直接表现为一次加加速度尖峰比速度差更伤机械。回到这个 FB 本身我还想强调一个验收习惯每次在新设备上启用外部 S 型加减速我会先跑三组测试——100mm 长行程看完整七段、5mm 中行程看降速五段、1mm 短行程看极短距离边界。三组波形全部合格才允许接入实际工艺。从那以后凡是启停有顿挫的设备我都强制先跑这三组曲线再谈调参很多时候问题根本不在 PID而在 S 曲线没算对。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑