1. 课程导入与版本治理全景

TwinCAT 项目从第一次新建 PLC 工程,到最终交付产线、进入多年维护期,期间会经历无数次修改:工艺参数调整、I/O 点表扩充、库函数升级、TwinCAT 版本迁移、硬件更换。每一次修改都会在工程目录里留下痕迹——可能是被覆盖的 .tpy 库文件、被替换的 .tsproj 工程文件、被重新编译的 .tmc 描述文件,也可能是散落在工程师个人电脑上的多个"最终版""最终版2""最终版_改"文件夹。当现场设备在凌晨两点停机,而你需要确认"当前运行的到底是哪一版程序"时,版本治理的价值就会以最直接的方式显现出来。

本节不急于给出工具清单,而是先建立一张全景地图:TwinCAT 项目生命周期中版本痛点出现在哪里、治理要达成什么目标、治理范围覆盖哪些对象、整体框架由哪几层构成。后续章节将逐层展开,本节负责让这些层次各就各位。

一、版本痛点:它们不是"管理问题",而是工程问题

很多团队把版本混乱归因于"工程师习惯不好",但真正的原因往往藏在 TwinCAT 工程结构本身。TwinCAT 3 的一个解决方案(Solution)通常包含 System 工程、PLC 工程、C++ 模块、HMI 工程以及若干库引用,它们分别以 .tsproj、.plcproj、.vcxproj 等文件存在,并通过相对路径互相引用。这意味着:单独复制一个 PLC 工程目录,往往无法还原出可编译的完整工程。版本治理首先要承认这个事实,而不是假设"把文件夹拷走就等于备份"。

典型的痛点可以归纳为四类。第一类是版本标识缺失:工程里没有可读的版本号,只能靠文件名或提交时间猜测。第二类是依赖关系隐式化:PLC 工程引用了某个自定义库,但库的版本没有记录在工程中,换一台电脑编译就可能链接到不同版本的库。第三类是运行版本与源版本脱节:现场控制器里跑的是编译后的 .tpy 或下载到目标机的运行代码,而源工程可能已经被修改过多次,二者无法对应。第四类是环境版本漂移:TwinCAT 3.1.4024 与 3.1.4026 在部分库行为和编译选项上存在差异,同一份源码在不同 XAE 版本下可能产生不同结果。

这四类痛点有一个共同特征:它们不会在开发阶段立刻暴露,而是在交付、复现、回滚、审计这些时刻集中爆发。因此版本治理的目标不是"让开发更规范"这种模糊表述,而是可检验的:任意一个已交付版本,都能被唯一标识、被完整重建、被准确对应到现场运行状态。

二、治理目标与治理范围

把上述目标拆开,可以得到三个可操作的治理目标。其一是可标识:每个受控版本有唯一且可读的标识,例如 V1.3.0-20240612,并能关联到具体的变更说明。其二是可重建:给定一个版本标识,能够在干净的开发环境中还原出可编译、可下载的完整工程,包括库、依赖和编译配置。其三是可追溯:从现场运行版本能反查到源版本、变更记录和责任人。

治理范围则需要明确边界。TwinCAT 项目中需要纳入版本治理的对象至少包括:PLC 源代码(.TcPOU、.TcDUT、.TcGVL 等)、库文件与库引用、System 工程配置(I/O 映射、任务配置、EtherCAT 拓扑)、HMI 工程、以及编译产物与下载记录。相对地,.compiled、_Boot 等中间目录通常不纳入版本控制,但需要在构建流程中明确其生成规则,避免"把编译产物当源码提交"这类常见错误。

判断一个文件是否应纳入版本控制,可以用一个简单问题检验:如果删掉它,能否仅凭仓库中的其他内容重新生成?能重新生成的,通常不纳入;不能重新生成的,必须纳入。

三、整体框架:四层治理结构

版本治理不是单一工具能解决的问题,它需要四层协同。最底层是工程结构层,负责让工程本身具备可版本化的形态,例如统一的目录约定、明确的库引用方式、可参数化的编译配置。第二层是版本控制层,负责记录变更历史,通常使用 Git 或 SVN,并配合 .gitignore 排除中间产物。第三层是版本标识与构建层,负责把源码状态转换为可识别的版本号和可交付的构建产物,例如通过脚本在编译前写入版本信息。第四层是交付与追溯层,负责把版本号、构建产物、现场运行状态关联起来,形成可查询的记录。

这四层的关系可以用下面的结构图表示。图中同时标出了每层对应的典型对象和常见失效点,便于在后续章节中逐层排查。

TwinCAT 版本治理四层框架 自下而上:结构 → 控制 → 标识 → 追溯 第四层 · 交付与追溯层 对象:版本号、构建产物、下载记录、现场运行版本 常见失效:现场版本无法反查源版本;交付包缺少库依赖 第三层 · 版本标识与构建层 对象:版本号规则、编译脚本、构建产物命名、变更说明 常见失效:版本号手工填写导致不一致;构建环境未固定 第二层 · 版本控制层 对象:Git/SVN 仓库、分支策略、提交规范、.gitignore 常见失效:中间产物误提交;库文件未纳入或未锁定版本 第一层 · 工程结构层 对象:目录约定、库引用方式、编译配置、解决方案结构 常见失效:工程依赖绝对路径;库引用指向本地目录 可追溯 可标识 可重建 可版本化 下层为上层提供基础;上层失效时,应优先回查下层是否稳固

四、一个具体场景:从"找不到版本"到"可追溯"

假设某包装设备使用 TwinCAT 3 控制,PLC 工程中引用了自研的 PackLib 库。某天客户反馈"封切动作偶尔延迟 200ms"。团队手上有三个工程文件夹:PackLine_v2、PackLine_v2_new、PackLine_备份,但无法确定现场运行的是哪一个。

如果已经建立上述四层框架,处理方式会完全不同。第一层保证工程目录结构统一,三个文件夹本不该存在;第二层保证每次修改都有提交记录,可以查到"延迟 200ms"相关改动;第三层保证每次交付都有版本号,例如 V2.4.1-20240520,并记录该版本使用的 PackLib 版本为 1.2.0;第四层保证现场控制器中写入的版本信息与交付记录一致。此时排查路径是:读取现场版本号 → 在仓库中找到对应提交 → 查看该提交与上一版本的差异 → 定位到 PackLib 中封切延时参数的修改。整个过程不需要猜测,也不需要逐个文件夹比对。

这个场景说明,版本治理的收益不是"看起来更规范",而是把排查时间从数小时压缩到数分钟。它也说明四层框架中任何一层缺失,都会让追溯链条断裂:没有版本号就无法定位提交,没有提交记录就无法查看差异,没有统一的工程结构就无法保证重建结果一致。

五、本课程的组织方式

后续章节将按照四层框架逐层展开。工程结构层会讨论目录约定、库引用方式和编译配置的可版本化改造;版本控制层会讨论 Git 在 TwinCAT 工程中的具体用法,包括 .gitignore 的编写、库文件的处理策略和分支模型;版本标识与构建层会讨论版本号规则、自动化构建脚本和变更记录;交付与追溯层会讨论交付包结构、现场版本写入和追溯查询。每一层都会给出可操作的示例,而不是停留在原则层面。

在进入具体操作之前,建议先做一次现状盘点:打开你当前负责的 TwinCAT 工程,回答三个问题——它有没有明确的版本号?它能否在一台干净电脑上被完整重建?现场运行的版本能否反查到源工程?这三个问题的答案,就是本课程要解决的起点。