我最早遇到 MC_ProgramSpeedMotor1() 这条调用,是在一条汽车焊装线的转台工位。当时设备手册被翻得快烂了,标准 KRL 指令表里始终找不到它的完整解释,最后是老工程师一句话点醒我:这不是你日常写的运动指令,它是力控软件包里的电机速度编程接口,而且必须在后台循环里伺候它。后来我在好几个项目里反复跟这条指令打交道,发现大家对它的"速度行为"理解普遍偏浅。很多人以为给个速度值它就按这个值跑,实际上从参数传入到电机实际转起来,中间至少隔了三层控制逻辑。这篇文章就把这条指令的来龙去脉、调速链路和现场踩坑记录完整拆开讲,给正在做 FCT 相关调试和伺服单元速度控制的朋友一个参考。
1. 指令从哪里来:先弄清楚 MC_ProgramSpeedMotor1 所处的运行环境
1.1 它在标准 KRL 指令集里查不到,别浪费时间
很多同事第一次看到 MC_ProgramSpeedMotor1() 的报错时,第一反应是打开 KUKA 的 KRL 编程手册搜索,结果一无所获。这个现象非常正常。标准 KRL 里负责运动的是 PTP、LIN、CIRC 这类指令,配合 $VEL_AXIS、$VEL_CP 这些系统变量实现速度控制,但 MC_ProgramSpeedMotor1 并不在其中。
这条指令来自 KUKA 的力控和相关工艺软件包,最常见的载体是 KUKA.ForceTorqueControl,也就是现场常说的 FCT 包。在 FCT 框架下,系统允许你把某个轴、某个外部驱动单元从普通位置伺服模式临时切换成"速度可控模式",通过一个运动控制接口把目标速度交给电机。MC_ProgramSpeedMotor 后面的数字 1,通常代表电机编号或轴编号,具体几号取决于你工程里定义了几个可控电机。
我在做过的一个打磨单元里,就用它控制一个外部转台轴。夹具把工件夹紧后,转台需要以一个相对稳定的表面线速度旋转,让打磨头在工件表面做恒力进给。用传统 PTP 或 LIN 去写圆周运动当然也能转,但一旦力控反馈需要实时微调转速,标准运动指令根本做不到,这时候 FCT 包提供的电机速度编程接口就派上了用场。所以如果你想在标准 KRL 手册里找答案,方向就错了,应该去找 FCT 软件包手册和力控功能的技术附录。
1.2 Submit 解释器是它的主战场
这条指令还有一个让新手困惑的地方:它很少出现在主程序 .src 的运动指令段里,反而大量出现在 Submit 解释器或者后台循环中。原因是 MC_ProgramSpeedMotor1 承担的是一种"过程级"控制,它需要在一个周期内反复被调用、刷新,而不是像 PTP 那样执行完一条指令就结束运动。
Submit 解释器在 KRC4 系统里相当于一个独立于主程序的后台任务,以固定周期和主程序并行运行。把 MC_ProgramSpeedMotor1 放在 Submit 里,意味着每个控制周期系统都会重新读取参数并下发到伺服驱动,这样一来,力控 PLC 或者传感器给出的实时速度修正确实能及时反映到电机上。在主程序里调用不是完全不行,但主程序一旦运行到等待指令、暂停或者切换运动语句,这条指令的刷新就会中断,速度行为会变得非常"跳",现场最容易表现出来的就是转台一顿一顿。
我自己常用的做法是单独写一个 Submit 文件,专门负责速度编程接口的后台刷新。里面只做三件事:读取外部使能信号、判断当前是否处于速度控制模式、调用 MC_ProgramSpeedMotor1 并记录返回值。主程序只负责告诉后台"现在需要运行哪种工艺",具体的速度刷新完全交给 Submit 处理。这样职责清楚,后续排查问题也方便。
1.3 软件包版本和安全配置共同构成的前提条件
不能假设所有 KRC4 系统天然支持 MC_ProgramSpeedMotor1 的调用。这个指令需要对应的软件包被正确安装并激活,常见的就是 KUKA.ForceTorqueControl 相关版本。如果软件包缺失,你在编辑器里手工敲出这条指令,编译阶段就会报未知标识符。
另外安全配置同样关键。FCT 功能允许程序在运行时修改轴速度,这涉及机器人安全监控范围。我在某个项目里就遇到了第一次调用时报"Stop override active"的问题,查了一圈才发现是安全 PLC 侧没有把速度控制模式对应的安全确认信号置位。系统设计上,当 MC_ProgramSpeedMotor1 被激活并接管轴速度时,安全控制器需要确认"我知道这台设备现在正在以速度模式运行",否则机器人控制器会认为自己失去对轴位置的控制能力,直接触发停止级响应。
所以在现场接线和调试前,我建议先确认三件事:软件包是否已经出现在 WorkVisual 的项目结构里;FCT 或工艺包授权是否激活;安全配置中的速度模式确认信号是否已经映射到实际输入。这三项缺一不可,任何人告诉你"软包装了就能用",你都要留个心眼。
2. 速度行为的三层调速:设定值、Override 与 FCT 修正
2.1 第一层:指令参数里的目标速度单位与方向约定
先看指令本身的参数。MC_ProgramSpeedMotor1 一般会接收几个核心参数:电机编号、控制模式、目标速度、加减速斜坡相关参数。不同版本的软件包给出的接口签名不完全一样,但核心逻辑一致:告诉系统"我要把几号电机切到速度模式,目标速度是多少,斜坡时间多长"。
最容易出问题的就是单位。有些版本里目标速度直接是百分比,比如 50 就代表电机额定速度的百分之五十;有些版本则用工程单位,比如 mm/s 或 rpm。如果你从别的项目复制了一段现成代码,没有核对单位就上电,电机可能会以超预期速度旋转,这非常危险。我处理过一个外部轴,程序里写的速度值是 80,实际电机转速直接拉满,就是因为原项目单位是百分比,而这个电机型号的额定转速更高,换算逻辑完全不一样。
方向约定也值得单独说。MC_ProgramSpeedMotor1 的速度参数通常有正负号含义,正负号决定电机旋转方向。有些工程师喜欢统一传正值,再用额外参数控制方向;有些版本则直接通过符号控制。无论哪种,我强烈建议在程序开头做一次方向验证:手动输入一个很低的验证速度,比如额定速度的百分之三,确认转向和工艺要求一致后,再进入自动流程。方向反了在转台和打磨轴这类场景里不只是工艺问题,还可能导致工件飞出或者工装损坏。
2.2 第二层:全局 Override 和轴组 Override 的叠加
很多人忽略了一点:即使 MC_ProgramSpeedMotor1 传入了一个明确的目标速度,实际作用到电机的速度仍然会受到系统 Override 的影响。KRC4 里的 Override 不单单作用于主程序中的 PTP 和 LIN,它同样作用于速度编程接口下发的速度设定值,只是表现方式略微不同。
全局 Override,也就是示教器上的那个速度百分数,会作为第一层缩放因子叠加到目标速度上。假设你传了 100 mm/s,示教器 Override 在 50%,那么基础输出就是 50 mm/s。如果此时用户把 Override 推到 120%(这在 KRC4 里允许),基础输出会变成 120 mm/s。这个叠加逻辑在调试阶段既方便又危险,方便的是可以快速验证电机在低速下是否正常,危险的是速度行为不再由程序唯一决定。
轴组 Override 也要注意。KUKA 的轴组里往往有独立的倍率设定,比如 $OV_JOG 和 $OV_PRO 这类变量会按轴组或者运动类型区分。MC_ProgramSpeedMotor1 控制的对象如果是某个外部轴或伺服电机,它受的 Override 影响可能和控制六轴机器人的 Override 不是同一个变量。我在调试时吃过一次亏:程序里和示教器都设成 100%,但轴还是慢吞吞的,最后发现是 WorkVisual 配置里那个轴组的速度倍率被限制成了 30%,而这部分界面在调试初期根本没人去动。所以速度不对时,别只盯着指令参数,三级倍率都得查一遍:程序内部倍率、轴组倍率、全局 Override。
2.3 第三层:力控回路对速度的实时干预
这是 MC_ProgramSpeedMotor1 和普通速度赋值最大的区别所在。FCT 包引入的不仅是"速度可设定",更重要的是"力或者扭矩可以作为反馈量实时修正速度"。这一层修正通常发生在控制周期内部,由 FCT 的控制算法根据传感器信号计算得出。
用一个具体场景说明:打磨轴的恒定进给速度。工艺上要求打磨头接触工件后,接触力保持在 30N 左右。当打磨头遇到工件表面凸起时,接触力会瞬时增大,如果速度不变,力可能冲到 60N,造成砂带磨损或表面过切。引入 FCT 后,控制器检测到力上升,会在毫秒级时间内把速度编程接口的输出值向下调整,让接触力回落到目标区间。这个调整不是改你程序里的参数值,而是在内部叠加一个修正量,所以你在程序里看到的 SpeedValue 可能一直是 30,但实际电机速度已经根据力变化在 15 到 30 之间动态浮动。
这层逻辑对现场调试非常重要。很多工程师看到 Trace 里力值波动正常,但实际转速和程序设定不一致,就误以为指令有问题。其实这正是 FCT 的工作方式:速度是手段,力是目标,速度行为必须放在力控闭环里理解,不能只看单点设定值。如果希望速度完全恒定,那就不要启用力反馈的比例调节,把 FCT 控制模式切成纯速度模式,或者把力修正系数设为零。否则,你会永远在"程序写的速度"和"实际看到的转速"之间找不到对应关系。
3. 我常用的调用框架:启停逻辑与参数组合
3.1 用 SpeedControl 建立开关控制,而不是裸调指令
实际项目里我不建议直接在每个周期无脑调用 MC_ProgramSpeedMotor1,那样会让速度控制的启停完全失控。我会建立一个开关式的控制块,最外面是一个速度控制总使能,内部再区分目标速度来源和异常复位逻辑。
下面是我在实际项目中用过的一种框架,具体接口名以你所装软件包版本为准,但思路可以平移:
; Submit 解释器内循环 ; 外部 PLC 通过数字量输入给出速度控制使能 IF ($IN[101] == TRUE) THEN ; 第一次进入时完成模式切换 IF (bSpeedModeActive == FALSE) THEN SpeedControl ON bSpeedModeActive = TRUE ENDIF ; 每周期刷新目标速度与斜坡 MC_ProgramSpeedMotor1( MotorNo := 1, Mode := #FCT_SPEED, SpeedVelocity := nTargetSpeedMM, Ramp := nSpeedRamp, ReturnCode := nRet ) ; 记录返回值,便于后续诊断 nRetCodeBuffer = nRet ELSE ; 退出速度模式时先退出再清标志 IF (bSpeedModeActive == TRUE) THEN SpeedControl OFF bSpeedModeActive = FALSE ENDIF ENDIF在这个结构里,外部信号 101 是总开关,第一次从 OFF 切到 ON 时才执行 SpeedControl ON,避免每个周期重复执行切换动作。nTargetSpeedMM 和 nSpeedRamp 可以从主程序里的全局变量获得,这样一来主程序可以随时修改速度目标,后台循环负责执行。
SpeedControl 这个开关指令在不同版本里名称可能不同,有些版本直接叫 CTRL AXIS,有些版本用 FCT_ACTIVATE 之类的功能块,但本质都是建立"进入速度控制模式"和"退出速度控制模式"的边界。这个边界必须清晰,否则后续的异常处理会非常被动。
3.2 实际测试过的一组参数与斜坡设定
参数设定上,我以一套外部转台轴为例:电机额定转速 3000 rpm,工艺要求转台表面线速度约 500 mm/min,转台直径 400mm。换算下来目标转速约 23.9 rpm,对应额定速度的 0.8% 左右。这个例子很极端,只是为了说明工程单位换算的必要性。
实际调用时我更倾向于直接用"相对于额定速度的百分比"作为目标速度,因为 FCT 内部和驱动通信时,工程单位换算往往要依赖轴配置里的减速比和机械参数。如果机械参数没有标定准确,你写 500 mm/min 人家执行出来可能是完全不同的速度。百分比模式绕开了减速比误差,至少驱动层面的执行是准确的,机械层面的误差再通过实际测试校准。
斜坡时间我一般先设定 500ms 到 1000ms。这个参数决定了速度从 0 升到目标速度的时间。太短了容易造成机械冲击,尤其是转台带着大惯量工件的时候;太长则会让工艺启动段变得迟钝。我曾经为了照顾一个重型夹具,把斜坡调到 2500ms,结果每次启动都会在工艺传感器触发前还在爬速,导致检测时序错乱。后来改成 800ms,同时增加启动前的速度到达确认位,才解决了时序问题。
3.3 触发条件、退出时间与异常复位
调用框架里还需要加入触发条件判断。速度控制不是一开启就要立刻全速运转,必须等工艺条件满足。我常用的触发链是:总使能 ON -> 工件夹紧信号 OK -> 安全门确认 -> 速度模式使能 -> 目标速度从零开始递增。每个环节都有对应的数字量信号或者内部标志。
退出时间同样重要。当外部信号撤掉时,速度模式不能马上让电机自由滑行,而是要让速度斜坡降到零,再退出速度控制模式。这个"先降速、再断使能"的顺序,在气动夹紧和伺服电机配合的场景里属于保命级别的要求。试想一下,转台带着 50kg 的工件在高速旋转,你直接断开速度控制,机械上会怎样。所以我通常在总使能 OFF 后,先把目标速度置为零,等电机监测到实际速度低于阈值,或者一个固定延时结束,才真正执行 SpeedControl OFF。
异常复位方面,我会监控 MC_ProgramSpeedMotor1 的返回值。当返回值出现非零错误码时,后台循环自动把目标速度清零,同时向 PLC 发送一个"速度控制异常"信号。复位流程是 PLC 先撤掉总使能,现场确认无误后再重新给出 ON。这个设计看起来简单,但在实际产线上能省掉大量反复重启控制器的时间。
4. 那些"速度不对"的现场故障:完整排查链路
4.1 现象一:信号给了但轴不动,没报错也没报警
这个现象最迷惑人,因为系统没有任何报警,程序也在正常循环调用 MC_ProgramSpeedMotor1,但轴就是纹丝不动。我排查这类问题有一套固定链路,从外到内逐层确认。
第一步查使能链路上的所有输入信号。MC_ProgramSpeedMotor1 要真正驱动电机,往往还叠加了一个"驱动使能"条件,这个条件不一定是指令自身的参数,而是来自安全电路或者伺服放大器使能信号。我就遇到过一次 PLC 程序升级后,某个内部中间变量没有置位,导致驱动使能一直处于 FALSE,指令调用正常但输出被硬件锁住。
第二步检查是否处于位置监控冲突状态。速度控制模式下,如果机器人的位置监控或者轴位置偏差监控还在按位置模式运行,控制器会在内部禁止轴运动。表现就是指令返回正常,但实际速度始终为零。解决方式是在进入速度模式前,将对应轴的监控模式切换成速度监控,或者把偏差监控窗口放宽。
第三步,用系统变量确认当前有效速度是多少。通过示教器或者 Trace 查看实际轴速度,如果实际速度变量里能看到一个非零值在变化,但机械轴没动,那就要怀疑机械传动本身了,比如联轴器打滑、减速机卡死。我在一个老转台项目里就遇到联轴器键槽磨损,程序里速度完全正常,电机也转,但输出轴就是不转,这个和指令本身没有任何关系,但如果不按链路排查,很容易被带到沟里去。
4.2 现象二:Override 变化后速度掉零,且无法自行恢复
另一个高频问题发生在用户操作示教器改变 Override 之后。现象通常是:工艺运行中,操作工觉得转速太快,把 Override 从 80% 降到 40%,结果轴速度瞬间变成零,而且怎么推 Override 都不恢复。
这类问题的根因往往在速度斜坡和 Override 变化的交互上。当 Override 突降时,系统会试图让当前实际速度快速匹配新的倍率,这个匹配过程会触发一个向下的斜坡。如果此时 MC_ProgramSpeedMotor1 的目标速度被设定得比较低,再加上 FCT 内部的低通滤波,实际速度计算值会收敛到零附近。而恢复时,由于速度编程接口需要重新建立速度设定窗口,某些版本里必须先把速度模式退出再重新进入,否则内部状态机锁在"降速中"。
处理办法分两步。第一步是优化交互逻辑:在后台循环里不要直接跟随 Override 瞬时变化,而是对 Override 做滤波或者限制变化率,让速度调节变得平滑。第二步是增加自动退出重入机制:当检测到实际速度低于某个阈值且目标速度大于零时,自动执行一次 SpeedControl OFF,然后延时 100ms 再执行 SpeedControl ON,强制刷新速度控制状态机。这个办法不算优雅,但非常有效,我在两个项目里都靠它避免了操作工频繁重启控制器。
4.3 把变量、Trace 和系统状态串起来定位
如果三层调速链路都检查完毕,问题还没浮出水面,那就需要借助 Trace 把所有关键变量记录下来,一遍运行一遍分析。我推荐的 Trace 通道包括:指令返回值、实际速度变量、目标速度变量、系统 Override 变量、FCT 力反馈值、当前运行模式标志位。
举个实际例子。某个打磨项目中,砂带机的电机速度周期性波动,波动周期大约 4 秒。通过 Trace 观察发现,FCT 的力反馈值也在以相同周期波动,而力反馈波动的来源竟然是砂带接头处的一处硬点,每个周期经过打磨接触区时都会造成力跳变。控制系统为了维持目标力,自动把速度降了下来。从机械角度讲,砂带接头是事故源;从控制角度讲,速度波动只是系统的正常响应。Trace 把变量的因果关系展示得非常清楚,否则我们可能一直在调试速度参数,反而把真正的问题搞复杂了。
Trace 采样周期建议设在 4ms 到 8ms 之间,太短占用系统资源,太长捕捉不到力控调整的瞬态过程。至少采集整个工艺循环的前后 10 秒,方便对比不同阶段的稳态和动态响应。
5. 与传统 $VEL_AXIS 编程对比:该选谁,不该选谁
5.1 直接写入 $VEL_AXIS 和走 FCT 指令的区别
老一辈 KUKA 工程师在需要控制轴速度时,可能会直接修改 $VEL_AXIS 系统变量。$VEL_AXIS 确实能影响后续运动指令的执行速度,但它在本质上服务于位置运动,也就是说它的作用是给位置插补提供速度上限,而不是直接把轴切换到速度控制模式。
MC_ProgramSpeedMotor1 走的是另一条路径。它把轴从位置闭环中部分解耦,允许外部目标速度直接作用到驱动层,同时保留必要的位置安全监控。相当于一个"给速度的控制接口",而不是"给位置运动设定速度上限"。
用一句话概括:$VEL_AXIS 适合在位置轨迹中调整运动快慢,MC_ProgramSpeedMotor1 适合在需要持续长时间、允许速度围绕某个工艺目标动态调整的场景。如果你只是想让某个 PTP 运动慢一点,完全没必要动用 FCT 这条链路,直接用 Override 或者 $VEL_AXIS 就好。反过来,如果你要的就是持续转动且速度可以随力实时变化,那 $VEL_AXIS 做不到。
5.2 与伺服焊枪、打磨、涂胶场景的配合关系
我实际应用最多的是三类场景。第一类是伺服焊枪的电极修磨和预压紧动作。焊枪在修磨时,电极帽需要以一个受控速度旋转或者进给,速度太猛会把修磨刀片打坏,速度太慢修磨效率低,MC_ProgramSpeedMotor1 正好可以配合修磨工艺包,按修磨循环参数驱动焊枪电机,并且根据修磨时的阻力变化动态降速。
第二类是打磨和抛光。这个在前面提到过,核心优势是速度与力的协同。打磨深度、进给力、砂轮线速度三者互相耦合,传统方案是固定速度调整压力,但往往会出现压力波动大、表面质量不稳定。用 FCT 速度编程,可以让压力保持恒定,速度自动适应材料硬度和表面轮廓,效果要稳定得多。
第三类是涂胶和点胶。有些涂胶系统需要外部转台匀速旋转,胶枪固定不动,胶嘴相对工件表面的线速度必须保持恒定。如果转台用传统位置运动,每圈的微小位置误差会造成线速度波动,导致胶条粗细不均。速度编程接口可以让转台在圈与圈之间平滑调整转速,补偿当前工件半径变化,这是普通位置轨迹很难做到的。
5.3 回到"Speed behaviour"这个标题:要观察的到底是什么
文章标题叫"Speed behaviour MC_ProgramSpeedMotor1()",那到底应该观察速度行为的哪些维度?我总结下来是三个:目标速度的跟随性、动态修正下的响应性、异常状态下的安全性。
跟随性指的是实际速度与目标速度的一致程度。系统带宽足够、负载变化不大时,实际速度应该长时间稳定在目标速度附近;如果出现周期性偏差,优先怀疑机械负载变化和 FCT 参数配置问题。
响应性指的是当目标速度发生变化或者力反馈突变时,速度多快能稳定到新状态。响应时间太长,工艺调整会迟钝;响应时间太短,机械冲击又明显。响应性的核心调节参数是斜坡时间、力修正系数和速度滤波时间常数,三者要搭配调整。
安全性则是指速度控制链路在故障条件下能不能快速回到安全状态。包括驱动使能丢失时能不能立即停止,力反馈超限时能不能自动降速,安全信号断开时能不能进入保护性停止。我在每次项目验收时,都会强行做一次"运行中断开使能"测试,确认 MC_ProgramSpeedMotor1 控制的轴在异常断电时不会继续滑行,这个测试必须通过才能交付。
回到实际操作层面,我个人有一个坚持了很久的习惯:任何用到 MC_ProgramSpeedMotor1 的程序,我都会在调试阶段做一张"速度设定记录表",表格里列出目标速度、实际速度、力反馈值、Override、电机电流这几项数据,每隔一段时间记录一次。这样做不是形式主义,而是因为速度行为这种问题,靠感觉判断很不靠谱,数据积累到一定量后,很多似有似无的隐患都会浮现出来。比如某个速度值下电机电流持续偏高,你就可以提前预判机械传动有问题,而不是等到电机过载报警才处理。搞调试这行,多留一组数据,少熬一次夜。