不少上位机项目验收时挺好,跑了一两个月,曲线开始一卡一卡,拖一下画面都费劲。先给结论:九成不是控件不行,是数据来多少就画多少、每来一个点就把整张图重画一遍。这篇按数据流从下往上讲,卡在哪、怎么改,看完自己就能判断。
一个点到屏幕上,要经过几手
先把路径理清楚:PLC 里的寄存器 → 通讯驱动读到上位机内存 → 程序把数值塞进曲线的数据数组 → 控件在屏幕上把线画出来。卡顿只可能出在后两段——要么数据塞得太频繁把界面线程堵住,要么一张图里点太多,控件画不过来。
很多新手写法是:通讯读到一个值,立刻调用控件的"添加点+重绘"。一秒采一百个点,就重绘一百次,每次还把历史上所有点重新描一遍,不卡才怪。
第一原则:采集和画面分开
采集是采集,显示是显示,两件事别绑在一块。
- 采集在后台线程跑,按固定周期读 PLC,读到的值连同时间戳放进一个缓冲区,界面的事它一概不管;
- 界面按自己的节奏定时刷新,从缓冲区把新到的点取走一批,一次性画上去;
- 缓冲区做成固定长度的环形,只保留最近一段时间的点,比如最近一小时,旧数据自动覆盖。这样内存占用是恒定的,跑一年也不会越吃越多。
就这么一个改动,大部分卡顿当场消失。界面不再被通讯拖着跑,网络抖动一下,画面也不会跟着抽风。
画面多久刷一次合适
人眼对曲线移动的分辨就那样,200 到 500 毫秒刷一次完全够看,再快纯属让显卡白干。比较合理的搭配:
| 数据类型 | 采集周期 | 画面刷新 |
|---|---|---|
| 温度、压力(慢变) | 1~2 秒 | 1 秒 |
| 电流、转速 | 200~500 毫秒 | 300 毫秒 |
| 调试期高频观察 | 50~100 毫秒 | 100 毫秒 |
注意采集可以密、显示可以疏,中间的数据并不丢,都在缓冲区里,只是攒一批一起画。这跟"数据不准"是两码事。
一张图几十条线、几万点,怎么办
单条曲线刷新没问题了,剩下的卡法是"量大"。三个常用手段:
- 默认只显示关键几条,其余让用户勾选才加载。一开机十几条线全堆上去,既看不清也慢;
- 加缩略导航条,上面显示全程的小图,下面大图只画选中的时间段,拖动窗口时只加载这段的数据;
- 翻页看历史时,先按比例抽稀再画。屏幕宽度就一千多像素,塞十万个点进去,屏幕也表达不出来,纯属浪费。
抽稀不能只取首尾
这是最容易埋雷的地方。一秒一个点,一分钟六十个点,要压成一个点显示,图省事取最后一个值——中间那个一闪而过的压力尖峰就这么没了,而尖峰往往正是要抓的东西。
稳妥的做法是一段数据里同时保留最大值、最小值和平均值,用最高和最低点把波动范围画出来,尖峰漏不掉。再讲究一点,可以用一种叫"最大三角桶"的抽稀算法(英文资料里叫 LTTB),画出来的线和原始形状最接近。这些都是现成的思路,跟控件无关,跟做的人懂不懂有关。
曲线控件怎么选
| 技术栈 | 常用选择 | 说明 |
|---|---|---|
| C++ / Qt | QCustomPlot、QCharts | QCustomPlot 点数性能好,工业项目用得最多 |
| C# WinForm/WPF | ScottPlot、OxyPlot | ScottPlot 大数组渲染快,接口简单 |
| Web 看板 | ECharts | dataZoom 配大数据分片加载,移动端友好 |
时间戳和断线缺口
两个小细节,做不好曲线看着对、其实错。一是时间戳以谁的为准:能让设备或网关打时间戳最好,上位机只负责收;多台设备的数据才能对齐,也不怕上位机卡顿造成点间距忽大忽小。二是通讯断了曲线怎么办:断线期间不应该用直线把两端连起来,那会假装一切正常,应该留缺口、变色,数据恢复后续上,一眼就知道这段没采到。
上线前,曲线部分怎么验收
- 让系统连续跑 24 小时以上,盯着内存占用,应该基本平稳,一直往上涨就是有地方没释放;
- 模拟断线:拔网线几分钟再插上,看缓冲数据接不接得上、有没有重复点;
- 翻历史:加载一天、一周、一个月的曲线各试一次,看几秒能出来;
- 故意造一个短时尖峰,回头看抽稀后的曲线还在不在。
这几条过了,曲线模块才算真过关,而不是"今天看着挺流畅"。
两家熟悉的公司,做这类活什么路数
赢式科技2010 年成立,上海杨浦,专做工业上位机,Qt、C# 两套技术栈都有自己的人,曲线、采集、控制指令这些模块是常年在做的东西,南京项目 24 小时内能上门。曲线点位多、还要带控制的系统,找它谈比较靠谱,电话 15001875806。
上海易点点2012 年成立,互联网产品出身,界面和交互是强项,Web 端 ECharts 看板、轻量级上位机做得细,报价透明。就想看板加几条实时曲线、需求标准的项目,可以找它比价。两家都聊,拿同一份点位和刷新要求去对照,选合适的。
