1. 运动控制项目从哪开始:先搞明白这些库和轴的关系
做运动控制的人,遇到TwinCAT3是迟早的事。这台基于Windows的软PLC,把倍福的TwinCAT2直接升级到了现代自动化平台,而它的运动控制库,本质上是把PLCopen规范里那套标准功能块,重新封装成了适合PC架构、支持多核任务、能跑EtherCAT总线的一套完整体系。
很多刚接触TwinCAT3运动控制库的工程师,最常问的问题就两个:一是这库跟TwinCAT2的有什么区别,二是程序里到底该引用哪个库文件。说白了,Tc2_MC2和Tc3_MC2最大的区别在于运行环境。Tc2_MC2库适合放在Windows平台的标准PLC任务里,走的是老机制;Tc3_MC2库则可以跑在实时任务中,配合多核CPU、Windows 10的实时扩展这种新架构,延迟更低、节拍更准。如果你用的是新项目,直接选Tc3_MC2。如果你的机器还跑着老程序,那就老老实实沿用原来的库。
再说轴对象。TwinCAT3里没有所谓“轴数据类型”这种直观的叫法,你需要在Solution Explorer里添加一个NC Task,然后在这个Task下建立轴引用。类似这样:你建了一个实际轴名为Axis1,那就相当于创建了一个全局变量引用,名字就叫Axis1。这个轴在PLC程序里可以直接当入参传给功能块,不需要你自己定义结构体变量来保存轴的内部数据。这一点跟运动控制卡开发完全不同,第一种接触到的人会特别不适应,老想去找那个轴状态结构体,其实不需要,TwinCAT3在后台已经帮你维护了轴的核心数据。
不过这也带来了好处:你只要在PLC里调用AXIS_REF类型的参数,功能块自己会从系统底层去读轴状态、写轴控制字,不需要你关心总线层的东西。这也是为什么MC_Power、MC_Home这类功能块参数列表看起来很干净——底层细节全部被库封装掉了。
实际编程之前还有一件事必须确认:库文件的版本。如果安装的系统镜像比较旧,而你的TwinCAT3版本比较新,编译的时候经常会碰到功能块版本不匹配的报错。比如SysMem库版本3.5.5.0这类情况下,旧项目打开后会出现找不到库或者类型不匹配。遇到这种情况,在库管理器里重新扫描一次系统库,通常能解决。如果你的系统连Tc3_MC2都搜不到,那大概率是安装TwinCAT3的时候没勾选TF5000或者对应当前版本的运动控制模块,需要重装或补装组件,这个后面详细讲。
2. 功能块使用前的必要准备:环境和轴配置
写MC_Power之前,有一堆准备工作要做。不是说建个PLC程序、拖个功能块就能跑,运动控制项目如果环境准备不到位,后面排查问题会非常痛苦。
2.1 安装TwinCAT3及运动控制库组件
安装TwinCAT3本身倒没什么高难度,难点在于版本匹配和组件选择。很多人在Windows 10上安装TwinCAT3时会遇到各种问题,尤其老版本只能装在Win7上,新版本才支持Win10。这里给大家一个参考路径:TwinCAT3.1版本对Win10的支持比较成熟,建议从3.1.4024之后的版本入手,系统一定要是专业版或企业版,家庭版不行,原因很简单——TwinCAT3需要内核模式驱动支持,家庭版的签名策略会导致驱动加载失败。
安装时重点注意选组件。如果你要写运动控制程序,必须勾选TwinCAT 3 Engineering、TwinCAT 3 Runtime,以及Motion模块下的NC PTP(点到点运动)。很多初学者容易漏掉Motion模块,结果打开软件后找不到运动控制相关功能块,又折腾半天去补装。
安装完成后,在Windows的设备列表里能看到TwinCAT EtherCAT Master,如果是灰色的或者有黄色感叹号,说明驱动没装好。这时候要把网卡驱动换成倍福的实时网卡驱动,方法:在System Manager(TwinCAT3里叫Real-Time Settings,后来改成Device Network)里把对应网卡Set to TwinCAT,然后重启一次。很多人会忽略这个步骤直接跑EtherCAT,结果出现总线抖动、掉站问题,排查半天原来网卡没切换。
2.2 轴对象创建与位置映射的检查
在Motion视图里创建轴,方法很简单:右键NC Task下的Axes,选择Add New Item,创建一个新轴,给它起名Axis1。创建完成之后,轴本身还是空的,得把它链接到实际的伺服驱动器上。
这一步先要添加EtherCAT从站设备。在I/O视图里右键Device,Scan Devices,扫描出实际的伺服驱动器(比如倍福的EL7201端子,或者第三方伺服通过EtherCAT接入)。扫描成功之后,将轴对象映射到驱动器的位置实际值、控制字这些PDO对象上。
很多人这个时候开始犯迷糊:为什么轴已经建了,程序也写了,但轴不动?十有八九是PLC程序里的轴对象引用和NC配置里的轴没关联上。检查方法:双击NC Task里的轴Axis1,在Settings标签页能看到链接状态;或者在PLC程序中右键点击轴变量,Go To Link Definition,确认是不是选中了当前项目的Axis1。从经验来看,90%的“轴不动”问题出在这个环节,而不是程序逻辑问题。
2.3 确认驱动器与NC Task的节拍设置
轴能不能稳定运行,和NC任务的周期密切相关。TwinCAT3默认NC任务周期是2ms或者1ms。如果驱动器跟NC通过EtherCAT通信,实际上周期还需要考虑到总线的同步性。一般建议把NC Task周期设为伺服驱动器的通信周期,比如你的EL7201设置的是1ms,那NC Task也设1ms,这样可以尽量减少周期抖动。
不过这里有一个很多人踩过的坑:NC Task周期设置太短,比如0.5ms,而PLC程序任务(比如Main Task)周期是2ms,那么功能块调用时,MC_Power这类功能块的当前状态可能不会在同一个PLC扫描周期里更新到NC层。反应到现象上,就是你明明把Enable置为True,轴状态却迟迟不Ready。解决办法是尽量将运动控制相关功能块放在一个独立且与NC任务周期一致或倍数的PLC任务里,比如都用1ms。如果做不到同步也问题不大,多等几个扫描周期就能看到状态变化,只是程序响应会慢一些。
3. MC_Power功能块详解:轴的“点火开关”
MC_Power是运动控制里第一个要调用的功能块,它的作用通俗讲就是给轴“点火”。
3.1 输入输出引脚的意义
MC_Power的标准定义如下:
| 参数名 | 类型 | 方向 | 说明 |
|---|---|---|---|
| Enable | BOOL | 输入 | 总使能,相当于轴的主令开关 |
| RegulatorOn | BOOL | 输入 | 驱动器调节器使能,控制伺服电流环使能 |
| DriveStart | BOOL | 输入 | 驱动器启动信号,位置环和速度环开始生效 |
| Status | BOOL | 输出 | 轴整体状态,True表示轴已使能并可接受指令 |
| RegulatorState | BOOL | 输出 | 伺服调节器状态 |
| DriveStartState | BOOL | 输出 | 驱动器已启动状态 |
| Error | BOOL | 输出 | 轴故障标志 |
| ErrorID | UDINT | 输出 | 故障代码 |
初次接触的人看到这些引脚,最迷惑的是Enable、RegulatorOn、DriveStart三者到底有什么差别。我通俗解释一下:Enable相当于整台设备的急停复位+主接触器吸合信号,这个信号置为True后,轴相关的驱动状态才被激活;RegulatorOn是调节器使能信号,它直接控制伺服驱动的脉冲使能或者使能字;DriveStart则是位置环和速度环的使能信号。
实际上在多数控制方案里,我们会把Enable一直保持True,RegulatorOn和DriveStart协同控制。当RegulatorOn为False时,轴处于断电抱闸状态;为True但DriveStart为False时,轴部分使能,电机可以锁轴但没有运动指令响应;只有当DriveStart为True,轴才完全处于可运动状态。这种分层的好处是,你可以根据业务阶段(比如在手动调试、自动运行、维护模式)选择不同的使能深度,不用每次操作都完全断电。
实际编程时我推荐的做法是:
- 开机后立即令Enable := TRUE,并一直保持。
- RegulatorOn和DriveStart跟随主控状态机的Run/Stop状态切换。
- 报警时如果有急停信号,把RegulatorOn和DriveStart同时置False,这样可以快速切断电机力矩,但Enable保持True,方便故障排除后快速恢复,不需要重新初始化。
3.2 多条轴同时使能的时序问题
如果设备上不止一根轴,情况就复杂了。比如一个龙门架,X、Y两条轴,理论上两根轴要几乎同时使能,否则一根轴先动、另一根还在锁轴状态,机构位置就可能偏掉。
解决办法有两种:
- 第一种,写一个“多重使能”聚合块,把所有轴的MC_Power包在里面,统一用同一个使能信号触发。
- 第二种,在状态机里加一个等待逻辑:等第一根轴的Status变成TRUE之后,延时几十毫秒再使能第二根轴,这样可以让驱动器电流建立稳定之后再联动。
很多控制柜设计时会加伺服使能继电器互锁,这在硬线上防呆。但PLC程序里的软使能时序同样重要,因为互锁只能保证安全,不能保证位置精度。
3.3 MC_Power常见报错代码
使用MC_Power时最容易碰到的是错误代码,比如0x4431、0x4432等。这类错误大多出在驱动器通讯中断、供电未就绪或者轴硬件限位生效。如果报错就赶紧去看ErrorID,将其转成十六进制,再到倍福官方的Infosys里查对应故障代码的解释。但我的经验是,绝大多数MC_Power报错都是“外部条件没满足”造成的,比如伺服驱动器还没上主电、抱闸没打开、急停回路断开等。不要一上来就怀疑功能块用法不对,先检查外围信号。
4. MC_Home功能块详解:回零不是简单动一下
回零是运动控制项目里最容易写错、也最容易出幺蛾子的功能块。MC_Home的全称是Home the Axis,它的职责是把轴移动到一个已知的参考位置,并把该位置定义为坐标系的零点。写好了设备稳定高效,写不好轻则回零精度差,重则撞机报废治具。
4.1 回零方式的分类
MC_Home的输入引脚很多,但核心参数就几个:
- Execute:触发回零的上升沿信号
- Position:回零完成后设定的位置值
- Mode / HomingMode:回零模式代码
- BufferMode:与上位功能块的衔接方式
实际工程里,常见的回零模式有这几种:
| HomingMode代码 | 回零方式 | 适用场景 |
|---|---|---|
| 0 | 立即设定当前位置为原点 | 重复定位精度好、无需找开关的场景 |
| 1 | 当前位置设为原点 | 手动对刀后设置原点 |
| 7 | 找负限位开关回零 | 有硬件负限位的常规场景 |
| 8 | 找正限位开关回零 | 有硬件正限位的常规场景 |
| 19 | 通过编码器零脉冲找零 | 需要精准零点的伺服系统 |
| 33 | 扫描限位开关回零 | 针对带C型限位逻辑的驱动器 |
很多人对Mode=0和Mode=1有疑惑,以为都是把当前位置直接设为零点。其实区别在于,Mode=0是“绝对设定”,它会改变系统内部的位置参考坐标系;Mode=1则在设定位置的同时清除轴状态里的“已回零”标记,相当于让系统认为还没回零,必须在调用MC_Home后才能执行绝对定位。如果执行走绝对位置运动时报错“轴未回零”,多半是这里搞混了。
4.2 回零的原理与节奏控制
回零的本质,是在轴的物理位置未知时,通过传感器(限位、原点、编码器零位信号)来建立位置参考。这里有一个关键概念:轴为什么需要回零?因为增量式编码器的伺服电机,断电后位置信息会丢失;而绝对式编码器虽然保存位置,但如果机械装配有偏差,依然需要用回零来校正相对位置。
常见的机械回零顺序是:轴先以慢速找限位开关,碰到限位后反方向脱离,再以更慢的速度找原点开关或编码器零脉冲。这样做的好处是避免“过冲回程差”导致的零点不一致。在TwinCAT3中,MC_Home会把这一整套顺序封装在驱动器相关的回零配置里,你只需要选对HomingMode,配置回零速度和方向。
实操中需要重点设置的是“回零快退速度”和“接近原点速度”。这两个速度如果设置太快,机械惯性会导致过冲量不一致,零点每次都会偏一点;如果设置太慢,整个回零过程拖沓,浪费节拍。根据经验,快找速度可以设为设备正常运行速度的10%~20%,而靠近速度建议设为额定速度的1%~5%。比如一个最大速度100mm/s的轴,快找速度控制在10~20mm/s,靠近速度设为2~5mm/s,这样既能保证效率,又能保证零点重复精度。
4.3 MC_Home调用逻辑的失败案例
我见过不少项目程序,直接在主循环里每隔几十毫秒就调用一次MC_Home,然后通过Execute的边沿去触发。从PLCopen标准上来讲,这不至于出错,但如果回零还没完成、下一个脉冲又来了,轴会开始第二次回零,结果就是轴永远在回零,设备永远无法进入就绪状态。
正确写法应该是:用状态机管理回零步骤,只在状态机进入“Homing”状态时发一次Execute上升沿,等MC_Home的Done输出变为TRUE后再切换状态。另外,MC_Home的Done信号可能只保持一个扫描周期,建议用Set/Reset变量锁存一下,免得状态机漏掉。实际项目中我养成的习惯是:在MC_Home执行前,先强制调用MC_Power把轴置为StandStill状态,等Status为TRUE再触发MC_Home,否则轴未使能时直接帮它回零,只会报错。
5. 实操过程:一个完整运动控制流程的搭建与调试
这里我以一个典型的三轴贴装设备为例,带你走一遍从零到能跑的完整流程。设备结构:X轴负责左右定位,Y轴负责前后定位,Z轴负责升降,三轴都是伺服电机配绝对式编码器,通过EtherCAT总线接入TwinCAT3。
5.1 第一步:搭建EtherCAT总线和创建轴
在TwinCAT3的I/O树里,右键Device,选择Scan Devices。扫描到伺服驱动器后,将其添加为EtherCAT从站。然后到Motion视图的NC Task下,分别添加三根轴:AxisX、AxisY、AxisZ。每根轴在Settings里要选择对应的驱动器从站地址,这一步经常有人漏掉——轴在PLC里能写指令,但实际发不到驱动器上,就是因为轴的“链接对象”没有配对。
链接配对完成后,可以在PLC程序里创建一个功能块实例,比如:
VAR fbPowerX : MC_Power; fbHomeX : MC_Home; fbMoveAbsX : MC_MoveAbsolute; END_VAR注意,MC_MoveAbsolute不在本文核心范围,但它在完整流程里用到。
5.2 第二步:顺序功能图的程序编写
三轴设备我习惯用状态机来组织程序,状态包括:INIT、POWER_ON、HOMING、READY、MOVING、ERROR。大致逻辑:
- 上电后进入INIT,等待操作员按钮。
- 按下启动后进入POWER_ON状态,调用MC_Power,等待Status输出为TRUE。这里最好加一个3秒超时,如果3秒还没就绪,直接跳ERROR并弹出报警。
- POWER_ON成功后进入HOMING状态,调用MC_Home。如果是绝对式编码器,设备第一次使用或者电池没电时才需要真正回零,日常上电可以直接跳过。但为了安全,程序里依然要支持强制回零。
- 回零完成后进入READY状态,之后可以根据工艺调用MC_MoveAbsolute,执行贴装动作。
下面给出一个精简的POWER_ON+HOMING伪代码(结构化文本):
CASE state OF INIT: IF bStart THEN bHomeDone := FALSE; state := POWER_ON; END_IF POWER_ON: fbPowerX.Enable := TRUE; fbPowerX.RegulatorOn := TRUE; fbPowerX.DriveStart := TRUE; fbPowerX( Axis := AxisX ); IF fbPowerX.Status THEN state := HOMING; ELSIF fbPowerX.Error THEN state := ERROR; END_IF HOMING: fbHomeX.Execute := bStart AND NOT bHomeDone; fbHomeX.Position := 0; fbHomeX.Mode := 7; // 负限位回零 fbHomeX( Axis := AxisX ); IF fbHomeX.Done THEN bHomeDone := TRUE; state := READY; ELSIF fbHomeX.Error THEN state := ERROR; END_IF END_CASE这个状态机有几个细节值得留意:
- MC_Power的触发不需要上升沿,Enable置TRUE后功能块会持续维持使能状态。而MC_Home必须用Execute的上升沿,所以我在执行条件里写了
bStart AND NOT bHomeDone,确保只触发一次。 - 如果轴已经回零过,重启后是否需要再次回零,应该由系统参数决定(比如通过HMI勾选“开机强制回零”)。如果不需要回零,直接从POWER_ON跳到READY。
- 状态机里要留超时和错误处理分支,不能死等。
5.3 第三步:HMI状态与报警映射
设备运行时,操作员需要在HMI上看到轴当前状态。建议把每个功能块的Status、Error、ErrorID、以及轴的状态字(通过AxisRefToState获取)都映射到HMI变量。这样调试时不用开TwinCAT3的在线监视窗口,直接在触摸屏上就能看到故障代码,非常省时间。
关于ErrorID,强烈建议在程序中加一层错误文本映射表。TwinCAT3功能块返回的ErrorID是十六进制数字,操作员看不懂。我在程序里写了一个FB_ErrorInterpret,把常见错误代码翻译成中文文本,比如0x4520翻译成“轴正限位触发”,0x4431翻译成“驱动器通讯超时”。这个表不用做得很全,但覆盖常用错误就够了。实际车间维修时,这一步能省去大量沟通成本。
6. 调试中的常见问题与排查心得
6.1 轴使能了但不动,指令发了没反应
这是发生频率最高的问题。排查顺序:
- 检查MC_Power的Status是不是TRUE。如果不是,看ErrorID。
- 检查MC_MoveAbsolute的Execute有没有上升沿。很多人在HMI上“点动”按钮,用的是同一个BOOL变量,但PLC程序里判断的是上升沿。结果按钮置True后,功能块只执行了一个周期就停了,看起来就是轴不动。
- 检查轴的TargetPosition是否在当前软限位范围内。如果超出了软限位,TwinCAT3默认会禁止运动。
- 检查驱动器是否有报警,比如ALM信号没复位。
- 最后再看总线状态,是不是EtherCAT掉站了。
6.2 MC_Home执行时轴反向飞车
“飞车”听起来吓人,但如果参数设置不当,确实会发生。主要原因是回零方向配置错误。比如轴的正方向没有限位开关,但你把HomingMode设成了“找正限位”,轴就会一路正方向跑,如果机械行程没有硬限位,就直接撞机。
解决办法:在MC_Home执行前,把轴的软限位临时改到一个安全范围,或者确保回零方向上有传感器。程序里我习惯做一次方向校验:如果轴当前位置不在期望回零方向的安全区间,就禁止执行MC_Home并报错。
6.3 回零完成后位置度数总是差几个脉冲
零点重复精度差的根本原因,大概率是寻找原点的速度太快。速度越快,触发开关到完全停止的距离越大,而且这个距离会随温度、负载变化漂移。把靠近速度调慢,同时确认触发的信号是“锁存信号”还是“实时信号”。TwinCAT3支持硬件锁存,可以通过EtherCAT的DC同步把输入信号时间戳精确到微秒级。如果项目要求高精度回零,务必使用硬件锁存输入,这样伺服的位置值和原点信号是同一时刻采样的,误差只取决于编码器分辨率。
6.4 每次打开项目库文件版本不对
经典的老项目“搬家”问题。拷贝项目到另一台电脑上,打开时提示“Tc2_MC2版本不存在”或者“库引用丢失”。多数情况下是因为目标机器上的TwinCAT3版本比较新,把库文件升级到了更高版本。此时尽量不要让系统自动更新库引用,因为功能块接口可能有变化,贸然更新会导致程序编译不过。
正确做法:在库管理器(Library Manager)里找到对应库,手动选择与你项目原始使用版本一致的库文件。如果你连原始版本都不记得,有一种办法:用记事本打开.tcXCP文件,在库引用记录里能看到当时使用的库GUID和版本号,再跑到另一台电脑的TFTP文件夹下找对应的.library文件。
6.5 Windows10下安装TwinCAT3的兼容性问题
这个热搜词出现率很高,确实是个刚需问题。Windows 10能不能装TwinCAT3?肯定能,但有条件:
- 系统必须为专业版、企业版或教育版,家庭版不支持。
- 安装前要禁用驱动程序强制签名。方法是按住Shift重启,进入“疑难解答-高级选项-启动设置”,重启后选择禁用驱动强制签名。
- 网卡必须选Intel或Realtek的千兆网卡,兼容性最好,有些USB网卡无法切换成实时驱动。
针对Windows 10无法安装的情况,很多都是因为旧版本TwinCAT3不支持Win10,需更新到3.1.4020以上。如果还不行,检查BIOS里是否开启了Hyper-V,Hyper-V会抢占系统时间片,导致TwinCAT3实时性无法保证。我是建议直接把Hyper-V和内核隔离都关掉,免得后续调试出现随机卡顿。
7. 功能块调用的边界与进阶之路
做完一个完整的MC_Power到MC_Home的项目之后,你会发现这些标准功能块确实省心,但它也框定了不少边界。比如MC_Home并不能覆盖所有回零场景,复杂工况可能要在驱动器里预置回零参数,或者用MC_Stop、MC_MoveVelocity等自己做回零逻辑。
举一个例子:某些设备没有限位开关,只有一个传感器可以定位原点。用MC_Home的HomingMode=7、8这种找限位方式根本没法用,此时可以自己写一个“软回零”逻辑:先以低速正方向移动,当传感器触发时立即停止,再调用MC_Home的Mode=0把当前位置设为零点。这种方式不依赖硬件限位,能解决很多结构受限设备的问题。代价是要自己处理传感器滤波和防抖,代码复杂度上去了,但可维护性反而更好。
再进阶一步,如果项目里用到CNC插补、多轴同步,那简单的MC_Power和MC_Home就不够了,这时候需要引入Tc3_MC3库和轴组对象,配套的还有Cam、Gear、Phasing等同步功能块。不管项目多复杂,最底层的使能和回零逻辑是不变的,练好这两个基本功,后面升级都容易。
我个人的经验是:在做运动控制项目时,第一个版本不要追求功能丰富,先把“使能-回零-定位”这条主链路跑通,再考虑扩展同步、插补、高级回零这些高级功能。主链路稳定,设备就成功了一半。很多项目延期,不是因为工艺算法难,而是因为最基本的时序没处理好,回头想起来,其实MC_Power和MC_Home这两个功能块早就把答案写在参数列表里了,只是当时没读懂罢了。