简介《TwinCAT 2.0 从入门到精通最后版本》是一份面向Beckhoff CX、CPxxxx、Cxxxx系列控制器用户及TwinCAT 2软件使用者的实践型PDF教程适合已具备一定自动化基础、需要完成系统配置、PLC编程、硬件接线与通讯调试的工程师查漏补缺。内容由有近15年倍福技术经验的作者整理重点分享项目开发中的常见错误、使用窍门与排错思路并涉及EtherCAT、K-Bus、ADS、Modbus、TcpIp通讯及掉电保持、数据存储、配方、PID等功能模块对从入门到独立实施项目较有参考价值。资源包仅含1个PDF文件大小约5.55MB便于在电脑或移动设备上检索阅读。目前已有213人学习下载适合希望系统掌握TwinCAT 2操作细节、减少摸索时间的读者。1. 把 PC 当 PLC 用TwinCAT 2.0 从入门到精通绕不开的那道坎翻 TwinCAT 2.0 从入门到精通的人十个里有八个是奔着“让程序跑起来”去的结果真正卡住的地方往往不是语法。指令表、梯形图、结构文本这些东西干过两年 PLC 的人一周就能上手可一旦设备开始偶发丢帧、输入读两次值不一样、换个笔记本就连不上控制器很多人就懵了。反直觉的结论在这里用 TwinCAT 这类 PC-based 控制系统你写的从来不只是 PLC 程序而是在一台跑着 Windows 的通用计算机上为一组硬实时任务分配 CPU 时间、内存布局和通讯通道。绝大多数现场“玄学”问题最后都能追到三个地方——时间怎么切、内存怎么排、数据怎么走。把这三件事想通剩下的都是查手册能解决的细节。2. 实时性一台跑 Windows 的 PC凭什么敢承诺 1ms 的控制周期普通 Windows 不是实时系统。它要照顾界面响应、驱动、后台服务中断延迟动辄几毫秒到几十毫秒抖动不可预测。把这样的系统直接拿来做运动控制等于把设备安全交给调度器的心情。所以第一件要想清楚的事是TwinCAT 到底把实时性藏在了哪一层。2.1 实时核插在哪一层Windows 与硬件之间那道夹层常见的实现思路是在 Windows 的硬件抽象层之下插入一个实时扩展。中断先到实时核实时核判断这个中断归谁归实时任务的立刻处理归 Windows 的才转发上去。这样 Windows 依然是个正常的 Windows可以装软件、开远程桌面、跑数据库但它的调度抖动影响不到实时侧。这带来一个非常关键的推论实时性能不是靠软件“优化”出来的而是靠隔离出来的。当实时任务和 Windows 抢同一个 CPU 核时实时任务靠更高的中断优先级抢占代价是 Windows 侧会变慢当 CPU 有多个核时通常的做法是把实时任务绑到指定核上让 Windows 只在剩下的核上活动。所以你会看到老工程师在调试时反复强调“关掉杀毒”“关掉自动更新”“别在控制器上装输入法”——这些不是迷信它们每一个都会往实时核所在的那颗 CPU 上扔中断。TwinCAT 2 时代的控制器大多是这样一台机器主板、CPU、内存、一块 CF 卡或硬盘加上预装的 Windows 和运行时。它既是控制器又是电脑这个双重身份是它所有优点和一半坑的来源。2.2 分时多任务Base Time、任务周期和优先级怎么互相咬合实时核提供了一个最小的时间刻度通常叫 Base Time一般取 1ms 或更小比如 50μs、100μs取决于硬件和实时网卡的能力。所有 PLC 任务的周期必须是这个刻度的整数倍——这一点经常被忽略有人把任务周期设成 1.5ms然后疑惑为什么实际跑出来是 2ms。在 PLC 运行时内部任务Task是可以有多个的。每个任务有自己的周期、优先级和看门狗时间。优先级高的任务先执行同一优先级按时间片轮转。这里的设计动机很朴素一套设备里急停逻辑和温度采集显然不该有相同的实时要求把它们塞进同一个大循环里等于让最慢的那段代码拖累最快的那段。参数含义设错的典型后果Base Time实时核的最小时间刻度任务周期不是它的整数倍实际周期被向上取整Task Cycle该任务的执行周期设得过小固定开销占比飙升CPU 负载虚高Priority任务优先级低优先级任务被长期饿死看门狗报警Watchdog单次执行超时判据设得过大卡死也发现不了设得过小正常抖动也报错一个容易被低估的点是周期不是越小越好。每个周期都有固定开销——上下文切换、过程映像拷贝、与 IO 的一次数据交换。周期从 2ms 缩到 1ms可用时间只多了一倍但固定开销可能翻倍甚至更多结果就是负载曲线陡增反而更容易丢拍。我见过不少人为了“更快的响应”把周期一路往下调最后设备抖得比原来还厉害这就是典型的没算清开销账。2.3 怎么判断这套系统还“实时”抖动、负载和看门狗实时性不是二值属性它是一个分布。标称 1ms 的周期如果 99.9% 的调用是 1.00ms、0.1% 是 3ms那这套系统在大多数场合能用但在高速位置比较或者高速计数场景就会翻车。所以判断手段要能看见“最坏情况”而不是平均值。最直接的办法是在任务里自己打点记录相邻两次调用的时间差统计最小值和最大值。下面这段是示意实现用运行时提供的系统时间函数拼出来的探针(* 周期性任务里调用的周期探针只关心最坏情况不关心平均值 *) PROGRAM PRG_CycleProbe VAR nLastMs : DINT; (* 上次执行的系统时间单位 ms *) nDeltaMs : DINT; (* 本次与上次的间隔 *) nMinMs : DINT : 10000; (* 观测到的最小间隔初值给一个大数 *) nMaxMs : DINT; (* 观测到的最大间隔这就是抖动上界 *) nOverRun : UDINT; (* 间隔明显超出设定周期的次数 *) END_VAR nDeltaMs : TIME_TO_DINT(TIME()) - nLastMs; (* 取当前毫秒时间并做差 *) nLastMs : TIME_TO_DINT(TIME()); IF nDeltaMs nMinMs THEN nMinMs : nDeltaMs; END_IF IF nDeltaMs nMaxMs THEN nMaxMs : nDeltaMs; END_IF IF nDeltaMs 2 THEN nOverRun : nOverRun 1; END_IF (* 周期设为 1ms 时的判据 *)参数含义需要说清楚nDeltaMs在理想情况下恒等于任务周期nMaxMs才是真正值钱的那个数它代表系统被抢占得最惨时延迟了多久nOverRun是累计的越界次数看它增长的速度比看单次数值更有意义。判据 2里的 2 要按你的实际周期改——周期设 1ms 时2ms 已经说明错过一拍周期设 10ms 时这个判据就该放宽到 12 左右。另外注意TIME()的分辨率是毫秒级想看到亚毫秒抖动得换用更高精度的计时接口或者干脆用示波器、Scope 这类外部工具。除了探针还有几个现成的观测口运行时状态里能看到每个任务的 CPU 负载和实际周期System Manager 里能看到实时以太网的丢帧计数和从站看门狗状态事件消息窗口会记下每一次看门狗触发。真正稳的系统这些数字应该是平的——负载曲线没有尖峰丢帧计数一直是零事件窗口里干干净净。3. 过程映像与 ADS一个变量从代码走到物理端子中间过了几道手程序里写bStart : TRUE;端子上的继电器合上中间发生了什么很多人答得出来“链接了一下”但说不清链接的本质是一张表也说不清为什么同一个输入变量在一次扫描里读两遍值一定一样。搞明白这条链路变量链接、地址重分配、ADS 通讯这些事就串成一条线了。3.1 过程映像为什么程序里的输入输出不能直连端子最朴素的做法是每次读输入变量都去问一次总线。但这样有两个致命问题一是慢每次访问都是一次总线事务二是不一致同一个逻辑判断里读了两次同一个输入中间从站刷新了前后值就不一样逻辑直接错乱。所以所有 PLC 都走过程映像任务开始前运行时把输入通道的数据批量拷贝到一块内存输入映像区程序执行期间只读这块内存任务结束时把输出映像区批量刷到输出通道。这个过程叫一次扫描周期。它带来的直接推论是——程序里读到的输入永远是本周期开始那一刻的快照输出写下去也不会立刻生效要等本周期结束。这个设计不是妥协是必需品。它保证了一次扫描内的数据一致性也让 IO 访问退化成纯内存操作速度差异是数量级的。副作用是如果你在一个周期里改了输出又立刻去读它读到的只是映像区里的值不是端子上的真实状态。要确认输出真的到位得等下一个周期或者通过总线回读。3.2 变量链接与地址重分配一张映射表的生与死System Manager 里那一步“链接变量”本质上是在配置文件中写下一条记录源是谁、目标是谁、多长、什么类型。编译之后这些记录会变成运行时可读的映射表运行时按表把映像区里的字节搬到总线帧里去。这套机制最反直觉的地方在于地址是自动分配的。你在 PLC 里声明变量时不写地址编译器按声明顺序和类型长度依次分配%I*和%Q*。好处是不用管地址冲突坏处是——加一个变量、删一个变量、甚至改一下声明顺序后面所有变量的地址可能整体平移。提示这就是为什么“上传、下载和比较”这件事在 TwinCAT 里格外重要。PLC 程序可以单独上传下载硬件配置也可以单独上传下载两者还能做比较。工程上遇到“程序没改但设备行为变了”的情况第一步永远是比对而不是猜。映射表还有个隐式约束长度和类型必须匹配。把一个 16 位通道链接到一个INT上没问题链接到DINT上高位就是垃圾数据把两个BOOL打包进同一个字节这是常见做法省带宽链接时就得分清楚哪一位对哪一个变量。这类错误编译期不一定报跑起来就是“某个位老是被别的东西带着动”。3.3 ADS 与 AMS NetID一条带门牌号的内部总线PLC 运行时、NC、IO 扫描、Scope、上位机这些东西各自是独立的进程或设备它们之间要交换数据走的就是 ADS。可以把 ADS 理解成一套跑在 TCP/IP 之上的设备间寻址协议它靠 AMS NetID 定位设备靠端口号定位设备里的某个服务。NetID 的形态通常是“IP 地址加两个端口段”比如192.168.1.10.1.1端口号则区分具体服务PLC 运行时、NC、IO 各占一个固定的口。这个设计的巧妙之处在于同一套寻址方式既能访问本机进程也能跨网段访问另一台控制器代码层面几乎无差别。你笔记本上的编程环境能改控制器里的变量靠的就是它。ADS 通讯有两种风格差别很大。一种是按地址读写快但脆——地址一变通讯就错位另一种是按符号名读写运行时去符号表里查慢一点但稳定改程序不影响到对方。工程上还有一种更省资源的做法叫通知Notification客户端订阅一个变量值变了服务端主动推而不是客户端拼命轮询。对于要显示几百个变量曲线的场景轮询和订阅的负载差着数量级。3.4 现场总线在栈里的位置EtherCAT、K-Bus 和串口的差别同样是“接 IO”不同总线在软件栈里的位置完全不同这决定了它们的实时能力和调试方式。EtherCAT 走的是实时以太网要用专用的实时网卡数据帧在从站之间“穿过”而不是逐站存储转发所以周期可以做到很短并且能和 PLC 任务严格同步——任务跑一拍总线也走一帧。它的诊断信息很丰富从站的丢帧、CRC 错误、看门狗状态都能读出来这也是为什么老工程师会反复强调“先看 EtherCAT 诊断再看程序”。K-Bus 是背板总线走的是模块之间的 E-bus通常挂在耦合器后面。它的实时性不如 EtherCAT但对本地扩展模块足够配置上更简单扫描一下就把模块认出来了。串口和 TcpIp 则完全是另一个世界。它们是异步的没有周期概念没有帧边界数据什么时候到、到多少都不确定。软件栈里它们通常跑在较低优先级的任务或者独立线程上和实时任务的节奏对不齐。这解释了一个非常常见的现象PLC 逻辑写得再对串口通讯该丢数据还是丢——因为它压根不在实时通路上。4. 掉电保持、配方与数据存储断电之后哪些数据还认得回家的路设备断电重启有的数据必须还在累计产量、机械零点偏移、标定系数有的数据丢了无所谓当前温度、中间计算状态。这两类数据在存储介质上的待遇完全不同混为一谈就是给自己埋雷。4.1 保持型变量到底存在哪三层结构从快到慢大致可以分成三层。第一层是普通内存。断电即失容量大随便写。 第二层是保持区。变量声明成保持型之后运行时会在关机流程里把它落盘启动时再读回来。速度介于内存和文件之间容量有限。 第三层是持久化区。需要显式落盘通常落在控制器的存储介质上容量大但写一次的开销也大。关键机制在于什么时候写。保持区的写入不是在每次赋值时发生的——如果那样性能会崩介质寿命也撑不住。它通常发生在受控关机或者周期性回写时。这就带来一个非常现实的结论没有 UPS 或足够储能电容的控制器长时断电时保持区是有可能丢的。短时掉电靠电容撑一下长时断电就得靠关机流程走完。(* 保持变量 写入节流别让每次累加都去碰保持区 *) VAR RETAIN nTotalCount : UDINT; (* 掉电保持由运行时负责回写 *) END_VAR VAR nBuffer : UDINT; (* 内存缓冲正常运行时只累加这个 *) tLastSave : TIME; END_VAR nBuffer : nBuffer 1; IF TIME() - tLastSave T#10S THEN nTotalCount : nBuffer; (* 每 10 秒才同步一次到保持区 *) tLastSave : TIME(); END_IF这段逻辑的用意是控制写入频率。nBuffer是纯内存操作随便加nTotalCount每 10 秒才被写一次既保证了断电最多丢 10 秒的计数又不会让保持区被高频写穿。参数T#10S怎么定取决于你能接受丢多少——产量统计丢 10 秒可以接受机械零点偏移别说 10 秒一次都不该丢后者应该做成“标定时才写、写完立刻同步”的路径。4.2 配方为什么不该塞进保持区容量、寿命和可编辑性配方数据的特点很鲜明条数多、每一条都不小、需要人能改、需要版本可追溯。这三个特点和保持区的三个限制正好顶上了——容量上限、写入寿命、以及“存进去就不好拿出来看”。所以工程上常见的做法是把配方落到文件运行时按需加载到内存。文件系统的优势是可读、可备份、可拷贝、可以用文本编辑器打开看代价是读写慢需要自己做缓存和校验。这里有个典型的坑配方文件如果直接按结构体二进制整体写盘换一台机器、换一个编译版本读回来就可能错位。原因在下一节和第 5 章都会讲到——结构体在内存里不是紧凑排列的。4.3 控制器当 PC 用备份、桌面接管和 Boot 目录的代价因为控制器本质是台 Windows 机器你能做的事很多远程桌面连进去、装个软件、改个桌面、甚至用它上网。这份自由是要付代价的。代价之一是实时性。前面说过任何在实时核所在 CPU 上产生中断的东西都会影响抖动远程桌面这种高频刷新的操作影响尤其明显。代价之二是可维护性。工程交付时最值钱的不是程序是那份能让设备三年后还能恢复原状的备份。整机镜像比“拷一份工程文件”可靠得多因为它连操作系统、驱动、授权一起带走了。我一般建议在做完调试、设备验收之前做一次完整备份并把备份和当时的程序版本号一起归档。代价之三是启动配置的脆弱性。运行时启动时会去读一个固定的启动目录里面放着启动时要加载的配置。这个目录被误删、被误改表现就是“设备开机后什么都没了”或者“配置回退到上一个版本”。它不是一个你日常会去看的目录所以出事的时候最难想到。5. 避坑与排查那些手册不会写、但现场一定会遇到的事下面这几条每一条都是“现象看起来像 A其实是 B”的典型。按现场出现的频率排不按重要性排。5.1 配置与授权三类“程序明明没错却不干活”现象一程序下载成功、运行指示灯也正常但输出端子一动不动。原因只下载了 PLC 程序没有把硬件配置激活。PLC 程序跑在一块“空的”配置上变量链接关系不存在映像区里的值永远传不到总线上。 解决养成固定顺序——先激活配置再下载 PLC最后切到运行。看到“配置已修改但未激活”的提示就当红灯处理别忽略。现象二换了一台笔记本就连不上控制器同一根网线、同一个网段也不行。原因ADS 通讯靠 AMS NetID 寻址新机器上没有到目标控制器的路由记录或者 NetID 和目标对不上。 解决先在本地添加路由确认本机 NetID 与控制器 NetID 不在同一网段冲突再测连通性。这一步是纯配置问题跟程序无关别去翻代码。现象三设备跑了半小时或几天突然停机重启又正常。原因授权是试用状态有运行时长限制。 解决查授权状态别只看有没有报警。这类问题的迷惑性在于它不报“授权错误”而是表现为“运行超时”——因为授权到期后系统会按超时处理。5.2 实时与通讯两类“偶发”故障的根因现象四周期偶尔丢一拍看门狗报警改程序改逻辑都没用。原因任务周期不是 Base Time 的整数倍实际周期被向上取整和预期对不上或者 Windows 侧有程序在抢 CPU、抢中断。 解决先把周期改成整数倍再排查控制器上跑的非必要进程杀毒、更新、远程桌面、屏幕保护最后看任务负载是否长期贴着上限跑。三件事按顺序做别一上来就怀疑代码。现象五串口或 TcpIp 收到的数据偶尔粘连、偶尔截断换个时间跑又好了。原因TcpIp 是字节流没有消息边界的概念一次“读”读到的可能是半个包也可能是两个半包串口靠超时断帧超时设短了断不干净设长了响应慢。 解决自己在应用层定帧——帧头、长度字段、校验、帧尾收不全就等下一批。别指望底层替你分好包这不是配置问题是协议本身的性质。现象六BOOL类型的输出改了一个另一个跟着动。原因多个BOOL被打包进同一个字节以节省带宽链接时位映射错了或者地址重分配后映射表没更新。 解决检查变量链接表里每一位的对应关系改动过变量声明之后重新走一遍链接和激活别指望它自动修好。5.3 变量与数据对齐引起的错位现象七结构体整体写入文件读回来数值全乱或者换台机器就乱。原因结构体在内存里按对齐规则排列不是紧凑的。TYPE ST_Channel : STRUCT nIndex : INT; (* 2 字节 *) bValid : BOOL; (* 1 字节编译器通常补 1 字节使其后成员对齐 *) rValue : REAL; (* 4 字节必须落在 4 字节边界上 *) nCount : DINT; (* 4 字节 *) END_STRUCT END_TYPE按字段长度加起来是 11 字节但实际占用通常是 12 字节因为rValue需要 4 字节边界中间被插了一个填充字节。如果你把这个结构体当字节数组整体写盘再在另一个编译配置下读回来填充规则一变后面每个字段的偏移全错。解决办法有两个要么逐字段序列化自己控制字节序和长度要么显式定义打包结构把填充字节摆到明面上。注意这类问题最阴的地方在于它“平时是好的”。开发机上读得出来换台机器就读不出来加个字段之前一切正常加完就坏。凡是涉及结构体落盘、跨设备传结构体、按字节拷贝变量的地方都要按这条查一遍。6. 设计取舍两段式工程、单核实时核以及这套资料为什么值得留在硬盘里TwinCAT 2 最被人诟病的设计是“两段式”PLC 程序在一个工具里写、编译、下载硬件配置在另一个工具里做、激活两边通过一个中间文件对接。新人第一次用会觉得割裂——为什么不能像别的那样一个工程搞定这个割裂是有历史理由的。把 PLC 逻辑和硬件拓扑拆开意味着同一套 PLC 程序可以配不同的硬件配置也意味着硬件工程师和软件工程师可以并行工作而不互相踩脚。代价是版本管理变复杂程序和配置各自有版本对不上就是一堆说不清的怪现象。这也是为什么“上传下载和比较”这两个动作被反复强调——它是这套架构下唯一的后悔药。TwinCAT 3 换了个思路挂到一个通用 IDE 的外壳上PLC 工程成为解决方案里的一个节点硬件配置、PLC、运动控制、C 模块都在同一棵树里语言层面补上了面向对象的那一套方法、接口、继承都有了64 位支持让大内存场景不再是天花板。这是一次彻底的现代化。维度TwinCAT 2TwinCAT 3工程组织PLC 与配置分离两段式单一解决方案节点化编程范式以功能块 动作Action为主支持方法、接口、继承扩展方式库文件库 C 模块 更细的运行时拆分适用场景存量设备维护、老控制器、已验证的成熟机台新项目、复杂架构、需要长期演进的产品但取舍不在于谁更先进。存量设备不会因为新版本发布就停机一套跑了八年的机台它的价值在于“已知的稳定”而不是“最新的特性”。而 TwinCAT 2 里那些概念——任务周期、Base Time、过程映像、变量链接、ADS 寻址、保持区——在 3 里一个都没消失只是换了位置。把 2 里的这套心智模型建起来切到 3 基本是换界面不是换脑子。这也是这类非官方资料的价值所在。官方手册告诉你每个参数是什么但它不会告诉你“这个参数设错了会在现场表现成什么样”。一份从 2010 年写起、每年更新、最后拆成十几个单章分别维护的文档它记录的不是知识是坐标——哪条路上有坑、坑有多深、绕过去要多久。我自己的习惯是任何一台要交付的设备在验收前强制走一遍“三件套”——整机镜像备份、程序和配置各存一份带版本号的归档、把当时的授权状态截图存档。这三样东西平时看起来多余出事的时候能省掉一整夜的排查。从那以后我每次接手别人调了一半的机台第一件事也不是看程序而是先确认这三样在不在。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?