车间上位机数据报表改造的事,我一开始差点绕远路。客户生产现场是三班倒,每班结束后都要看产量、温度、压力、电量的日报表,还要能随时调出任意一个变量的趋势曲线,用来分析设备状态和产品质量。我们用的上位机组态软件是 Kingscada,厂里又没有专门的数据库服务器,我不想为了几张报表再去单独部署一套 SQL Server。折腾了两天之后,我把方案收敛回 Kingscada 自带的历史数据引擎上:日报表和趋势曲线都直接连 KS 的历史库,通过查询任意一个变量来生成。这个思路非常适合当模板用,尤其是刚接触组态软件、想在现有工程里快速补上报表和曲线功能的自动化工程师。下面把整个思路、配置过程以及踩过的坑都摊开讲一遍。
1. 项目概述与核心思路拆解
1.1 日报表和趋势曲线,在工厂里到底解决什么问题
很多人觉得报表和曲线只是“把画面做得好看一点”,真到现场就会发现它们是两套完全不同的业务工具。
日报表解决的是管理问题。值班长要回答“今天三号车间一共产了多少吨”、“锅炉最高温度有没有超限”、“电耗比昨天高还是低”,这些不是看一眼实时画面就能回答的,必须把过去一个班次或一个自然日内变量的变化统计出来。常见的统计口径包括平均值、最大值、最小值、累计量,本质上是对历史数据做聚合运算。
趋势曲线解决的是追溯问题。设备报警、质量波动、停机原因,往往要回看事故前半小时的变量变化过程才知道发生了什么。比如某个阀门的开度在报警前突然从 80% 掉到 12%,仪表上只会闪一下报警,有了趋势曲线才能看到跌落拐点在哪一秒出现。曲线要求的是连续的时间序列回放,跟报表的聚合逻辑正好互补。
两者的共同底层是“历史数据”。Kingscada 里只要变量勾选过历史记录,工程运行时就会按设定的周期把变量值写入自带历史库。日报表和趋势曲线,本质上是这个历史库的两种对外读取方式。一旦把这条链路走通,随便新建一个变量并加入历史记录,就能在前端任意查询。
1.2 为什么优先用 KS 自带历史数据而不是先上数据库
我接触过的不少项目,一提到历史数据,第一个想法就是外接 SQL Server 或者 MySQL,再设计一个数据表,定时向里面存值。这么干不是不行,但在这个案例里完全是多余的复杂度。
KS 自带历史数据库本质上是一个面向时间序列的存储引擎,它关注的模型就是“变量 + 时间戳 + 值”。而报表和趋势曲线组件在组态环境里就已经内置了对这个存储引擎的访问接口,只要把变量名、开始时间、结束时间、统计方式填进去,就能拿到结果,不需要写复杂的 SQL 语句,也不需要维护什么连接串。
| 对比维度 | Kingscada 自带历史库 | 外接 SQL Server / MySQL |
|---|---|---|
| 部署成本 | 不需要额外安装数据库服务 | 需要单独装服务、配账号、维护连接 |
| 写入性能 | 面向高频时序数据优化 | 高频写入要自己建表、攒批次,容易卡 |
| 与组态联动 | 报表/趋势组件原生支持 | 需要写查询脚本,工作量集中在中间层 |
| 数据模型 | 天然按时间序列组织,适合趋势回放 | 关系型表要自己设计时间序列表 |
| 适用场景 | 单机或中小型系统的站内业务 | MES/ERP 集成、复杂业务报表、多端共享 |
并不是说外接数据库一无是处,如果报表要进入公司的 ERP 系统、要做复杂的跨系统关联查询、要让多个管理人员同时访问,那就合理很多。但如果是像我这个案例一样,先把车间自身的报表和曲线做出来,直接用 KS 自带历史库是最稳的路径,几乎没有额外运维负担。
这里还有一个现实考量:Kingscada 自带历史库和报表组件是同一个厂家的产品,版本兼容性经过验证,可以少踩坑。自己外接数据库,等于多了一层不可控的第三方依赖,一旦数据写不进去、时间对不上,排查链路会拉得很长。
2. 环境准备与基础配置
2.1 工程、变量定义与命名规范
先新建 Kingscada 工程,进入开发环境后,第一步不是急着拖控件,而是先把变量规划清楚。变量在工程里叫数据词典或数据字典,是所有监控、报表、曲线功能的数据源头。
变量的大类一般分三种。IO 变量对应 PLC、仪表、采集模块等外部设备,通信正常时会周期性刷新;内存变量不直接连接外部设备,通常用来存放计算值、中间结果或脚本生成的模拟数据;系统变量是软件内置的,比如当前时间、用户权限等。这个案例我用的是 KS 自带历史数据演示,现场没有真实 PLC 也没关系,核心是靠内存变量配合脚本先生成带规律的数据,再让报表和曲线去查询这些数据。
变量类型也要提前想好:整型、实型、字符串型、开关量型是最基本的。做报表和趋势曲线,实型和整型最常用,温度和压力这种连续量用实型,设备启停、开关状态用开关量,报表里可以把开关量显示成“运行/停止”。
命名规范这件事,我在实际项目里吃过亏。变量如果全用中文或者带特殊字符,后面在报表函数和曲线绑定里很容易出现格式问题。建议统一用“前缀_设备_测点”的结构,比如 Temp_React1_Temperature、Flow_Line2_Rate,简短、可读、不容易重名。一个变量要能被“任意查询”,前提是它的名字在全工程里唯一。
2.2 历史数据记录配置与容量规划
变量定义好了,不代表它就会自动保存历史。必须在变量属性里把“记录历史”或者“存储历史数据”的开关打开,工程运行时 KS 才会把该变量写入自带历史库。这个开关是新手最容易漏掉的一步,漏掉的典型症状就是报表和曲线都能配置出来,但查询结果就是空的。
存储周期直接影响数据分辨率和存储容量。默认周期常见是 1 秒,如果变量数量不多,1 秒没太大压力。但变量一旦上了几百个,每秒写入的量就很可观,磁盘空间会快速膨胀。实际项目中我是这样选的:温度、压力、流量做 1 秒存储,用于趋势追溯;电度、产量这类变化慢的计数量做 5 秒或更长的周期存储,报表统计完全够用。
历史库的存储路径也很关键。KS 默认会把历史文件放在工程目录下的特定文件夹里,建议工程文件和文件存储目录放在独立的磁盘分区,至少不要和 Windows 系统盘挤在一起。我见过一台工控机因为系统盘被历史文件写满,上位机直接卡死,最后只能删文件救急。如果磁盘空间紧张,可以设置历史存储的循环覆盖策略,比如只保留最近 30 天数据,旧数据自动清理。这个功能在大数据量项目里几乎是必开的,否则宕机只是时间问题。
还有一点要特别注意:变量类型在工程运行后不要随便改。比如原本是实型,运行了半年,突然改成整型,历史库里记录的数据格式会和曲线查询逻辑对不上,轻则曲线显示异常,重则历史数据读不出来。真要改类型,建议先把历史记录关掉、清掉旧数据,再改类型重新开记录。
3. 日报表实现:查询任意变量生成日报
3.1 报表组件与历史数据源绑定
Kingscada 的画面编辑环境里可以直接添加报表组件,不同版本的组件名称可能略有差异,但核心都围绕表格和单元格。日报表不是把一堆数字静态铺在画面上,而是要在表格单元格里填查询逻辑,让组件从历史库取数。
添加报表组件后,关键的一步是把数据源指向历史数据源,而不是实时数据源。很多人在这一步没有分清,结果报表里读出来的是“当前值”,根本没有统计意义。正确的理解是:日报表的每一格,本质上是一条按时间范围+统计方式进行聚合的查询命令,数据源选择决定这条命令去哪里查。
变量查询条件的设置也不难,但必须把格式写对。一般来说,查询字段里要指定变量名、开始时间、结束时间、统计方式。例如我要查询“1号反应釜温度”的昨日平均温度,可以构造出一个带时间参数的查询表达式,在报表单元格或报表属性里填入。需要注意日期时间的写法,Kingscada 里一般支持工程启动的当前日期为基准,用函数或表达式自动算出“昨天0点”“昨天24点”,避免每次手动改时间。
3.2 日报表的时间条件与统计维度怎么配
日报表最常见的时间范围是自然日,也就是从当天 00:00:00 到 23:59:59。如果只是写死一个固定日期,第二天报表就废了,所以一定要用日期函数动态计算。我在项目里的做法是:开始时间取 DateAddDay(CurrentDate(), -1) 拼接 00:00:00,结束时间取 DateAddDay(CurrentDate(), -1) 拼接 23:59:59。换成白话就是“昨天零点到昨天二十四点”。如果是班报表,就按交接班时间切分,早班 8 点到 16 点,中班 16 点到 24 点,逻辑一致。
统计维度按业务需求选。平均值用来衡量整体水平,比如一天的平均温度、平均压力;最大值和最小值用来做越限判断,配合报警记录就能知道哪个时段出了异常;累计值用来核算产量、能耗、流量,这类变量通常是瞬时值积分得到的。比如瞬时流量是 50 立方米/小时,一天的累计流量就是把它按时间积分,这部分不同的组态软件实现方式不同,但在报表组件里通常会直接提供“累计/积分”统计选项。
配置时还要注意数据的时间口径。有些变量上报的时间会存在几秒偏差,报表统计的边界正好切在 0 点,可能出现某天的最大值被“切”到了前一天或后一天。实用性建议是把统计区间比自然日稍微留一点余量,比如开始时间取前一天 23:59:50,结束时间取当天 00:00:10,然后把统计结果按主时间区间做人工校验。
3.3 日报表格式化、自动刷新与导出
报表查询逻辑配置好之后,还要解决显示和交付问题。表格里填出来的数字如果不做格式化,会是长长一串小数,比如 67.34384624,看着不专业。建议在单元格格式里统一保留一位或两位小数,平均值、最大值、最小值按实际精度分别设置。单位也要在表头标清楚:温度是 ℃,压力是 MPa,流量是 m³/h,否则看报表的人很容易产生误解。
日报表的刷新方式要区别对待。如果是看当天的统计数据,数据处于持续变化中,建议报表组件设置每分钟刷新一次,或者用一个循环脚本定时触发重新查询。如果是回看历史某一天的固有问题,刷新频率低一点也没关系,手动触发就够。
最后是导出。Kingscada 报表组件一般支持导出为 Excel 文件,也能调用打印功能生成纸质版存底。我在交付时通常会做一个“导出当前报表”的按钮,用一个动作脚本把表格内容输出到指定目录,文件名自动带上日期,比如“日报表_20250217.xls”。这样值班长每天只需要点一下按钮,就能把报表发到管理群,省去手抄的环节。
4. 趋势曲线实现:用历史数据画任意变量的走势
4.1 趋势曲线组件与历史数据绑定
趋势曲线在 Kingscada 里通常也是独立控件。刚开始做的时候,习惯直接把它当成实时曲线看,后来发现历史回看才是重点。趋势曲线组件一般有两种模式:实时追写模式和历史查询模式。做这个案例要用历史查询模式,让曲线直接读取历史库中的指定时间段数据,而不是只画屏幕上最近一段时间的实时波形。
历史曲线绑定和报表绑定的思路一致:曲线对象里添加一条记录,将数据源选为历史数据源,变量名选择要查询的变量,再设置时间范围。时间范围可以做成下拉选择或者按钮切换,比如“过去1小时”“过去8小时”“过去三天”,本质上都是改变查询的起止时间戳。
如果我要查询历史数据,需要在曲线启动或切换条件时触发一次查询命令,把开始时间和结束时间传给控件。这里要养成一个好习惯:开始时间和结束时间都用全局变量或表达式动态计算,不要写死。比如一键切到“昨日曲线”,就使用和日报表相同的日期函数计算出昨天 0 点到 24 点。
4.2 多曲线、Y轴与人机交互
趋势曲线一般不会只画一条变量,大多数场景是同时显示多个相关变量。比如反应釜曲线同时画温度、压力、搅拌电流三条线,方便对比三个量之间的联动关系。多曲线配置时,每个变量独立设置颜色、线宽和 Y 轴范围。颜色要选差异大的,比如蓝、红、绿,不要选相近色,否则运行界面上一团糊分不清。
Y 轴范围的设置需要格外小心。如果变量温度在 60 到 100 度之间波动,把 Y 轴固定成 0 到 500 度,曲线就会扁成一条直线,看着像停机了,实际只是量程问题。建议对每个变量设置单独的自动范围或者按经验值做上下限,前后留 10% 余量。多个量纲完全不同的变量要分左右 Y 轴,或者做归一化处理后叠加,不然一个 0.6MPa 的压力和 200 度的温度共用一个轴,压力那条线基本贴地。
运行态交互是我特别看重的一点。好的趋势曲线要支持鼠标放大、缩小、平移,还要有十字光标,鼠标划过曲线时能显示具体时间的数值。有了这些操作,故障排查时才能精准定位到分钟甚至秒级的拐点。
4.3 报表与曲线联动的人性化设计
报表和曲线不要做成两个孤立的画面,我一般会在日报表页面上加一个“显示趋势曲线”的动作:值班长选中某一行变量,点一下按钮,跳转到趋势画面,趋势画面自动以该变量名作为查询对象、以报表统计的日期作为时间范围,把对应曲线画出来。这样日报表回答了“今天平均是多少”,趋势曲线直接回答“这段变化的形成过程”,两者拼在一起才是完整的数据表达。
这个联动的实现思路不复杂:点击报表行时,把该行数据对应的变量名写入一个全局内存变量,再切换画面并触发趋势曲线控件重新绑定。曲线控件的查询函数在画面加载时读取这个全局变量,完成变量更新。别看逻辑简单,实际使用体验提升非常明显,值班长不需要每次手动输入或选择变量。
5. 实操过程与关键配置细节
5.1 从变量到历史库的完整链路
把前面讲的原理落到实际工程里,完整链路是这样走的:
- 新建工程并定义至少一个变量,比如 Temp_React1,类型选实型,勾选“记录历史数据”。
- 写一段循环脚本给变量赋值,模拟现场数据波动,没有 PLC 也能验证报表和曲线功能。
- 运行工程,让脚本持续运行一段时间,确保历史库里已经产生足够的数据。
- 在开发环境添加报表组件,绑定历史数据源,配置昨日统计查询。
- 添加趋势曲线控件,绑定历史数据源,配置昨日 0 点到 24 点的时间范围。
- 运行画面验证,确认报表数值与曲线走势吻合。
这里有一个容易被忽略的细节:历史数据是在工程运行过程中持续写入的,如果刚启动几分钟就立刻去查“昨天”的数据,自然查不到,因为昨天那个变量还没有被创建。做演示时,要么先把变量提前开历史记录并运行一段实际时间,要么把查询时间范围改成“最近 5 分钟”,用已经产生的数据验证功能。这也是用自带历史库做案例时最常遇到的认知差。
5.2 日报表查询的核心参数推荐
我以查询“1号反应釜温度昨日统计”为例,把逻辑参数整理成一张可直接抄作业的表格:
| 参数项 | 推荐配置 | 说明 |
|---|---|---|
| 查询变量 | Temp_React1 | 变量名必须和数据词典里完全一致 |
| 数据源 | 历史数据源 | 千万别用实时数据源 |
| 开始时间 | 昨日 00:00:00 | 用日期函数动态计算 |
| 结束时间 | 昨日 23:59:59 | 闭区间,包含最后一秒 |
| 统计方式 | 平均值、最大值、最小值 | 三个字段可以分别映射到三个单元格 |
| 小数位 | 1 位或 2 位 | 根据仪表精度决定 |
| 刷新方式 | 每分钟一次或手动 | 实时业务建议自动刷新 |
如果一个报表页要放多个变量,可以复制同样的查询模板,只替换变量名和时间范围,省去重复配置。这里我建议在工程里统一维护一个变量名列表,用数据库控件或脚本读取,即使后面变量数量增加,报表结构也不用大规模改。
5.3 趋势曲线的核心配置过程
趋势曲线控件配置按这几步走:
第一步,在画面工具箱找到趋势曲线组件,拖入画面并调整大小。第二步,在属性或配置窗口里添加曲线记录,数据源选历史数据源,变量选择 Temp_React1。第三步,设置时间轴格式:起始时间用动态表达式取昨日零点,结束时间取昨日 24 点,时间轴以小时或分钟显示。第四步,设置曲线颜色和线宽,实线一般用 2 像素,能见度最好。第五步,设置 Y 轴范围,温度如果平时在 70 到 95 度之间,就手动设置 60 到 100 度,并开启自动缩放。第六步,在运行态验证鼠标放大、平移功能。
多变量场景里,每个变量按同样方式追加一条曲线记录即可。注意不同变量的轴绑定不要选错,温度绑左轴,压力绑右轴,否则曲线会互相压制显示。曲线名称建议带上中文别名,比如“1号釜温度”,因为变量名本身不一定友好,显示名称要让操作工一眼看懂。
5.4 没有 PLC 时,用脚本模拟数据的小技巧
这个案例用 KS 自带历史数据演示,没有真实设备也一样能把报表和曲线跑起来。方法很简单:用一个周期脚本给内存变量写值。比如每秒执行一次的循环脚本,给 Temp_React1 赋一个围绕 80 度波动的值,温度走势可以写成正弦叠加随机噪声的形态,看起来非常接近真实工艺数据。
模拟脚本的写法大致是这个思路,具体函数名以自己工程的脚本语法为准:
// 每秒执行一次的定时脚本 Temp_React1 = 80 + 5 * sin(当前小时数 * 3.14 / 6) + 随机数 * 0.5;我特意让波动的周期和幅度接近真实温度变化,而不是写死一个常数,这样验证日报表的平均值、最大值、最小值才有意义,趋势曲线也不会是一条笔直的横线。如果脚本里写死了常数,日报表三个统计值全是同一个数,曲线也画不出变化,演示效果会大打折扣。
模拟数据跑上几小时之后,历史库里就有了足够的数据,再切报表和曲线的查询条件到对应时间段,就能看到完整效果。这个技巧在做售前演示、方案验证和新人培训时非常实用。
6. 常见问题与排查技巧实录
6.1 报表空白,查不到任何历史数据
这是最常见的故障,我十次碰见有八次是同一个原因:变量没有开历史记录,或者历史记录开了但数据还没产生足够。排查时先按这个顺序过一遍:
第一,检查变量定义里“记录历史数据”开关是否打开,没开就直接打开并重启工程。第二,检查工程是否真的运行过一段时间,历史库里有没有文件生成。第三,检查查询时间范围,如果用“昨日”但历史数据只有最近几分钟,肯定查不到。第四,检查报表数据源是否选成了实时数据源。第五,检查历史存储路径所在磁盘是否已满,写不进去。
一条条过完基本能定位。我建议在开发环境里先做一个简单测试:用历史库管理工具直接查看某个变量在哪些时间点有记录,这样能快速判断是“没存数据”还是“报表查询条件配错了”。
6.2 趋势曲线缺线、断线
趋势曲线缺线,先看变量的历史记录是否连续。如果曲线中间断了好长一段,往往是这几个原因:变量在某个时段没有被正常采集,比如设备停机;存储周期被改过,导致时间轴上的数据点密度不一致;或者历史存储循环覆盖把旧数据清理掉了。
另一个常见原因是 Y 轴范围问题,曲线显示为空,实际上是数据的值不在设定的 Y 轴范围内,曲线被“画到画面外面去了”。我排查时会把 Y 轴改成自动范围试一下,如果曲线立刻出现,那就是量程设置问题。还有变量类型对不上,查询的变量本来是字符串型,却想在曲线里显示成数值,肯定显示不出来。
6.3 系统重启后,历史数据丢了
上年末的设备重启后,历史数据丢失的案例我遇到过。后来排查发现是历史文件存储到了 Windows 临时目录或者 C 盘的小容量分区,系统清理时被当成临时文件清掉了。解决办法是把历史存储路径配置到独立的数据盘上,同时设置合理的循环覆盖天数,并做好定期备份。
另外,重启前最好先正常关闭上位机软件,让历史写入线程完成数据落盘。带电强制关机、拔电重启,最容易导致最后一段时间的历史数据文件损坏或丢失。车间环境经常停电,建议给工控机配 UPS,这是花小钱省大事的经验。
6.4 日累计值与人盘账对不上
很多项目都会在日报表里算“今日产量”“今日电量”,但统计结果经常和现场老师傅记录的累计值对不上。这个问题的核心是累计方式的口径差异。瞬时流量的累计在时间上必须是连续积分,如果存储周期是 1 秒,但历史记录中间掉了几个点,累计结果就会偏小。
解决办法是优先使用 KS 内部提供的累计量存储功能,让变量在采集侧就完成累计,日报表只读累计结果。如果只能用瞬时值积分,就要确保存储周期稳定,并且对数据缺失做补偿处理。这个坑在报表上线初期特别常见,做出来之后一定要先和现场人工台账对几天数再去固化。
6.5 报表查询速度慢
时间范围跨度大、变量多、存储周期密,报表查询就会明显变慢,点一下要卡好几秒甚至十几秒。做现场项目时,要控制单次报表查询的时间跨度和变量数量。日报表一天 86400 个点,问题不大,但如果一张报表同时查 50 个变量一年 365 天的数据,再好的组件也会累。
可以在报表功能设计上把“日查询”和“月查询”分开,或者利用历史库的降采样功能,查询时按分钟级别而不是秒级别聚合。这不是功能缺陷,而是数据量规划问题,提前预估并拆分,用户体验会好很多。
| 常见问题 | 主要原因 | 解决办法 |
|---|---|---|
| 报表空白 | 变量未开历史记录/时间范围错 | 检查记录开关与查询条件 |
| 曲线缺线 | Y轴量程不对/存储不连续 | 自动范围或调整存储周期 |
| 重启丢数据 | 存储路径被清理/非法关机 | 独立磁盘、UPS、正常关工程 |
| 日累计对不上 | 积分口径与缺失点 | 用累计量变量或做缺失补偿 |
| 查询慢 | 时间跨度大、点多 | 降采样、拆分查询、限制变量数 |
7. 项目交付与后续扩展建议
7.1 一套干净的交付物应该包含什么
项目做完不能只丢一个工程文件给客户,否则后面维护的人会骂娘。我交付时一般会整理三类东西:可运行的工程文件、使用说明文档、历史数据备份策略说明。
工程文件里覆盖变量定义表、报表页面和趋势页面模板;说明文档里写清楚哪些变量开了历史记录、存储周期多少、历史文件存在哪个目录、磁盘容量能撑多久。这些都是实际巡检和故障排查时最重要的信息。顺便把操作手册也补上:值班长如何切换日期查询、如何导出报表、如何调整曲线时间范围,每一条配截图。
7.2 从日报表向月报表、Web发布、MES对接扩展
等日报表和趋势曲线跑顺畅之后,可以继续往几个方向扩展。月报表就是把时间范围从自然日改成自然月,统计逻辑几乎不需要变,只是在日期函数上把区间放大。年报再往上推一层,同理。
如果管理人员不想进控制室看报表,可以研究一下 KS 的 Web 发布方案,把报表和趋势页面发布到内网网页,管理层在办公室用浏览器就能看。这一步要注意权限控制,现场操作用的画面和生产管理层用的画面尽量分权限,防止误操作。
如果真的到了要和 MES、ERP 对接那一步,再考虑外接数据库。但即便外接,我也建议保留 KS 自带历史库作为原始数据源,通过定时同步或者按需查询把数据转发给关系库,而不是让业务系统直接依赖上位机历史文件。这样既满足数据共享,又不破坏现场监控系统的稳定性。
最后说一点经验总结:这个案例之所以能顺利落地,核心在于没有盲目追求大而全的技术栈,而是把 Kingscada 自带的历史数据能力用到了极致。日报表和趋势曲线这两件事,只要围绕“任意变量 + 历史数据 + 时间范围”三个关键词去设计,不管变量数量怎么变,架构都是稳的。如果以后再接到类似需求,我大概率还是会先把自带历史库的方案跑通,再根据实际业务瓶颈决定要不要上外部存储。