☰
WinCC用户归档实战:配方管理与批次追溯避坑指南
2026/10/1 11:19:21 网站建设 项目流程

简介:这份资源面向工业自动化领域的WinCC学习者与工程技术人员,聚焦用户归档功能的实践应用,帮助解决实时数据存储、历史数据检索与归档策略设计等问题。压缩包共290个文件,约36.21MB,以rpl归档数据文件为主,辅以mdf、ldf数据库文件、dum、sav、ini配置与脚本文件,以及pdl画面、xml、cfg等工程文件,完整还原了一个可参考的WinCC用户归档项目结构。目前已有1149人学习下载,适合具备一定WinCC基础、希望深入掌握数据管理的中级用户。资源围绕动作与标准模块的协同展开,涵盖触发条件设置、模块逻辑编写、归档间隔与保留期限配置等关键环节,读者可对照示例项目理解数据过滤、转换与压缩的实现思路,并借鉴其归档策略设计方法,提升工厂自动化项目中的数据管理效率与问题排查能力。

1. WinCC 用户归档到底解决什么问题:从一次配方丢失事故说起

产线凌晨两点停机,操作工打电话说配方全没了。到现场一看,WinCC 画面上的配方列表空空如也,PLC 里的当前配方还在跑,但历史批次记录一条都查不到。翻日志发现有人点过“下载配方”,而配方管理用的是普通内部变量加脚本写 CSV——脚本抛了异常没人管,文件被覆盖成空。这就是典型的“用变量模拟归档”翻车现场。

WinCC 用户归档(User Archive)就是为这类场景准备的:它把配方、批次、工艺参数这类结构化业务数据存进 SQL Server 的独立表里,由 WinCC 自己管读写、管事务、管并发,画面控件直接绑定,不需要你手写文件 IO。它和变量归档、报警归档是三套独立机制,很多人第一次接触会混,后面会专门拆。

这篇面向已经在用 WinCC、需要做配方管理或批次追溯的工程师。读完你能自己建一套用户归档、配好控件、用脚本读写、并且知道哪些参数一改就出事。适合 WinCC 7.x 到 8.x 的经典客户端/服务器架构,TIA Portal 里的 WinCC Professional 思路相通但控件位置不同,我会点出来。

2. 用户归档的底层机制与建库前的选型判断

2.1 它和变量归档、报警归档的本质区别

变量归档存的是“某个 Tag 在时间轴上的值”,本质是时序数据,压缩后写分段文件,查询靠趋势控件。报警归档存的是“状态变化事件”,带确认状态机。用户归档存的是“一行一行的业务记录”,字段是你自己定义的,比如批次号、配方名、10 个工艺参数、操作员、时间戳。它底层就是 SQL Server 里的一张表,WinCC 通过 UA 控件和脚本 API 访问。

这个区别决定了选型:如果你要的是“某温度过去 24 小时的曲线”,用变量归档;如果你要的是“第 20240612-003 批次的 10 个参数分别是多少,谁在什么时候改过”,用用户归档。我见过有人拿变量归档硬凑批次追溯,最后查询慢到画面卡死,就是选错了。

用户归档的读写走 WinCC 的 DataManager,不是直接连数据库。这意味着你不能随便用外部 SQL 工具改表结构,改了 WinCC 认不出来。所有字段增删必须在 WinCC 的“用户归档编辑器”里做,然后由它同步到数据库。

2.2 建库前必须定下来的三件事

第一,归档是“配方型”还是“日志型”。配方型通常一个配方名对应一组参数,需要“下载到 PLC”和“从 PLC 上传”两个方向;日志型只追加不修改,比如每批次结束写一条。这决定你建几个归档、字段怎么设。

第二,主键和唯一性。用户归档默认有一个自增 ID 字段,但业务上你往往需要“配方名 + 版本”唯一。WinCC 允许你设索引,但不强制唯一约束,重复插入要自己在脚本里判。我一般会在归档里加一个“记录状态”字段,用 0/1 标记有效/作废,而不是物理删除。

第三,数据量和清理策略。用户归档没有自动滚动删除,表会一直涨。10 万条以内查询还流畅,超过就要考虑定期归档到历史表或按年份分归档。别等到画面查询转圈才想起来。

2.3 建一个配方归档的最小步骤

打开 WinCC 项目管理器,找到“用户归档”节点,右键新建归档,命名比如UA_Recipe。然后在归档里添加字段:

字段名类型长度说明
RecipeName文本32配方名,业务主键
Version文本16版本号
TempSet浮点—温度设定值
PressureSet浮点—压力设定值
SpeedSet浮点—速度设定值
Operator文本16操作员
UpdateTime日期时间—更新时间
Valid整型—1 有效 0 作废

建完后点“保存”,WinCC 会在后台 SQL Server 里生成对应表。注意字段名不要用中文,不要用 SQL 保留字(比如Order、Group),否则脚本里拼 SQL 会踩坑。文本字段长度按实际最大长度设,设太大浪费空间,设太小插入被截断还不报错。

提示:归档建好后不要急着在画面里用,先在“用户归档编辑器”里手动插一条测试数据,确认表结构同步成功。

3. 画面控件绑定与脚本读写:把配方管理跑起来

3.1 用 UA 控件做配方列表和编辑

WinCC 图形编辑器里,从“控件”面板拖“用户归档控件”(User Archive Control)到画面。右键控件属性,在“归档”页选UA_Recipe,然后配置列显示:把 RecipeName、Version、TempSet 等勾上,不需要的列去掉。控件自带浏览、新建、删除按钮,但生产环境一般隐藏这些,用自定义按钮加脚本控制,防止误操作。

控件的“选择”模式要设对:单选还是多选。配方下载通常单选,批次查询可能多选。这个属性在控件属性的“常规”页,叫“选择模式”。

3.2 用 C 脚本写入一条配方记录

WinCC 经典版用 C 脚本(ANSI-C),TIA Portal 里用 VBS 或 C。下面这段是经典版在按钮“保存配方”的鼠标点击事件里写的:

// 保存当前画面上的配方参数到用户归档 // 先检查配方名是否为空 char* szRecipeName = GetTagChar("RecipeName"); if (szRecipeName == NULL || strlen(szRecipeName) == 0) { MessageBox(NULL, "配方名不能为空", "提示", MB_OK | MB_ICONWARNING); return; } // 查询是否已存在同名有效记录 // 用 UA 归档的查询接口,条件:RecipeName 等于当前值 且 Valid=1 if (UA_IsRecordExisting("UA_Recipe", "RecipeName", szRecipeName, "Valid", 1)) { // 存在则更新,不存在则插入 UA_UpdateRecord("UA_Recipe", "RecipeName", szRecipeName, "TempSet", GetTagFloat("TempSet"), "PressureSet", GetTagFloat("PressureSet"), "SpeedSet", GetTagFloat("SpeedSet"), "Operator", GetTagChar("CurrentUser"), "UpdateTime", GetTagDateTime("LocalTime"), "Valid", 1); } else { UA_InsertRecord("UA_Recipe", "RecipeName", szRecipeName, "Version", GetTagChar("RecipeVersion"), "TempSet", GetTagFloat("TempSet"), "PressureSet", GetTagFloat("PressureSet"), "SpeedSet", GetTagFloat("SpeedSet"), "Operator", GetTagChar("CurrentUser"), "UpdateTime", GetTagDateTime("LocalTime"), "Valid", 1); }

逻辑说明:先做空值校验,避免插入脏数据。UA_IsRecordExisting是 WinCC 提供的查询函数,参数是归档名、条件字段、条件值、附加条件字段、附加条件值。这里用 RecipeName + Valid=1 判断是否已存在。存在走更新,不存在走插入。UA_UpdateRecord和UA_InsertRecord都是变参函数,成对传字段名和值。

参数说明:GetTagFloat读浮点变量,GetTagChar读文本变量,GetTagDateTime读时间变量。CurrentUser是 WinCC 内置变量,存当前登录用户名。LocalTime也是内置的,返回本地时间。注意UA_UpdateRecord的更新条件只用了 RecipeName,如果同名但不同版本,会全部更新,所以版本管理要另加条件。

3.3 从归档下载配方到 PLC

下载逻辑反过来:从 UA 控件选中的行读出字段值,写到 PLC 变量。在“下载”按钮里:

// 从用户归档控件读取选中行的配方参数,写入 PLC // 控件名假设为 ctrlUA,通过控件接口获取选中行 long lRow = UA_GetSelectedRow("ctrlUA"); if (lRow < 0) { MessageBox(NULL, "请先选择一条配方", "提示", MB_OK | MB_ICONWARNING); return; } // 读取各字段值 float fTemp = UA_GetFieldFloat("UA_Recipe", lRow, "TempSet"); float fPressure = UA_GetFieldFloat("UA_Recipe", lRow, "PressureSet"); float fSpeed = UA_GetFieldFloat("UA_Recipe", lRow, "SpeedSet"); // 写入 PLC 变量 SetTagFloat("PLC_TempSet", fTemp); SetTagFloat("PLC_PressureSet", fPressure); SetTagFloat("PLC_SpeedSet", fSpeed); // 记录下载日志 UA_InsertRecord("UA_DownloadLog", "RecipeName", UA_GetFieldChar("UA_Recipe", lRow, "RecipeName"), "DownloadTime", GetTagDateTime("LocalTime"), "Operator", GetTagChar("CurrentUser"));

逻辑说明:UA_GetSelectedRow返回控件当前选中行号,-1 表示没选。UA_GetFieldFloat按行号和字段名读值。写 PLC 用SetTagFloat,这是同步写,如果 PLC 没连上会阻塞,生产环境建议加超时判断或改用异步写。最后往下载日志归档里插一条记录,方便追溯谁在什么时候下载了哪个配方。

参数说明:UA_GetFieldChar读文本字段,返回char*,注意不要释放这个指针,它指向 WinCC 内部缓冲区。UA_InsertRecord的字段顺序要和归档定义一致,不一致会插入失败但不一定报错,这是血泪经验。

3.4 查询和过滤怎么做才不卡

UA 控件自带过滤条,但生产环境往往要按时间范围、操作员、批次号组合查询。我一般不用控件自带过滤,而是用脚本动态设置控件的 SQL 条件。在“查询”按钮里:

// 按时间范围和操作员过滤用户归档控件显示 char szFilter[512]; sprintf(szFilter, "UpdateTime >= '%s' AND UpdateTime <= '%s' AND Operator = '%s'", GetTagChar("QueryStartTime"), GetTagChar("QueryEndTime"), GetTagChar("QueryOperator")); UA_SetFilter("ctrlUA", szFilter); UA_Refresh("ctrlUA");

逻辑说明:UA_SetFilter设置控件的过滤条件,UA_Refresh刷新显示。时间格式要和数据库里存的一致,WinCC 默认是yyyy-MM-dd HH:mm:ss。如果查询慢,先看数据库索引有没有建在 UpdateTime 和 Operator 上,没有就手动加。

参数说明:szFilter缓冲区要够大,512 字符一般够,条件多就加大。字符串拼接注意单引号转义,操作员名里如果有单引号会拼坏 SQL,虽然 WinCC 会做一定过滤,但别依赖它。

4. 避坑与排查:用户归档最常见的五个翻车点

4.1 插入成功但画面查不到

现象:脚本返回成功,数据库里也有数据,但 UA 控件刷新后不显示。原因通常是控件的过滤条件没清掉,或者归档的“选择”属性设成了“只读”。解决:先调UA_SetFilter传空字符串清过滤,再检查控件属性里“允许编辑”是否勾上。还有一种可能是归档没激活,在项目管理器里看归档节点是不是灰色。

4.2 中文乱码

现象:配方名或操作员是中文,存进去变问号。原因是 SQL Server 排序规则不是中文,或者 WinCC 项目语言和数据库不一致。解决:建库时选Chinese_PRC_CI_AS,WinCC 项目语言设成中文,脚本里用GetTagChar读中文变量时确认变量本身编码正确。已经乱码的数据只能删了重插。

4.3 并发写入冲突

现象:两个操作员同时保存配方,一个成功一个失败,或者数据串了。原因是用户归档没有行级锁,并发插入时自增 ID 可能冲突。解决:在脚本里加互斥,用 WinCC 的SetTagBit做一个简单的软件锁,或者把保存操作放到一个全局脚本里串行执行。更稳妥的做法是数据库层面加唯一索引,让冲突直接报错而不是写脏数据。

4.4 归档表无限增长导致查询变慢

现象:运行半年后,配方查询要等十几秒。原因是用户归档没有自动清理,表里堆了几十万条。解决:定期把 Valid=0 的记录物理删除,或者按年份建多个归档,查询时只查当前年份。删除用UA_DeleteRecord按条件删,别直接 SQL 删,否则 WinCC 缓存不一致。

4.5 升级或迁移后归档丢失

现象:项目从一台机器拷到另一台,或者 WinCC 升级后,用户归档数据没了。原因是用户归档数据存在 SQL Server 里,不在 WinCC 项目文件里。解决:迁移时用 SQL Server 的备份还原,或者用 WinCC 自带的“归档导出/导入”功能。升级前先备份数据库,升级后检查归档连接字符串是否指向正确的数据库实例。

注意:WinCC 8.x 默认用 SQL Server 2019 Express,实例名可能是WINCC,连接字符串在“用户归档”属性里能看到,别改错。

5. 进阶:用用户归档做批次追溯和 OPC UA 对外暴露

5.1 批次追溯的字段设计技巧

批次追溯的核心是“正向可查、反向可追”。正向:给定批次号,查出所有工艺参数、操作员、时间。反向:给定时间范围或操作员,查出所有相关批次。我一般建两个归档:UA_Batch存批次主记录,UA_BatchDetail存每个工序的明细,用 BatchID 关联。查询时用 UA 控件的过滤条件做联合,或者用脚本查两次再拼。

字段设计上,时间戳不要只存一个,至少存“开始时间”和“结束时间”。操作员不要只存登录名,存工号或姓名,方便报表。参数值存原始值,不要存转换后的工程值,转换在画面做,这样追溯时不会因为量程改了导致历史数据失真。

5.2 通过 OPC UA 把归档数据暴露给 MES

WinCC 8.x 支持 OPC UA 服务器,可以把用户归档的数据以节点形式暴露出去。配置步骤:在 WinCC 项目管理器里启用 OPC UA 服务器,然后在“用户归档”属性里勾选“通过 OPC UA 提供”。MES 侧用 OPC UA 客户端连上来,就能读到归档表。

这里有个坑:OPC UA 暴露的是归档的“当前值”,不是历史查询接口。MES 要查历史批次,得用 UA 的查询方法节点,或者干脆让 WinCC 脚本定时把数据推到 MES 的数据库。我一般选后者,因为 OPC UA 的历史查询在 WinCC 里支持有限,不如脚本灵活。

5.3 一个验证归档是否正常的小技巧

不用打开画面,直接在 WinCC 的“用户归档编辑器”里看。如果编辑器能正常显示数据,说明归档本身没问题,问题在画面控件或脚本。如果编辑器也打不开,检查 SQL Server 服务是否启动、归档是否激活、数据库连接是否正常。这个排查顺序能省很多时间。

我自己的习惯是:每次改完归档结构,先在编辑器里手动插三条数据,然后用脚本读出来对比。对不上就是字段类型或顺序错了。这个习惯帮我省过至少两次通宵。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询