边缘预处理
概述
云端带宽昂贵、延迟不可控, 现场决策又要求毫秒级响应, 所以原始数据不应直接上云。DarraRT 在 PLC 侧与 Service 侧共同实现边缘预处理: 过滤噪声、聚合降频、死区压缩、规则决策, 让本地先处理 90% 的事, 只把关键信息发到云端或 MES。
典型带宽压缩比: 原始 10Hz × 500 点 = 5000 点/s, 经过死区 + 1 分钟均值后, 降到约 8 点/s, 流量节省 600 倍。
适用场景
| 场景 | 原始输入 | 边缘处理 | 输出 |
|---|---|---|---|
| 温度监控 | 10Hz 采样 | Kalman 去噪 + 死区 | 1Hz 上云 |
| 振动分析 | 1kHz ADC | FFT + 均值 + P95 | 1 分钟汇总 |
| 计件生产 | 光电脉冲 | 防抖 + 累加 | 每班次/每小时产量 |
| 报警判定 | 温度/压力 | 规则引擎 | 本地停机 + 推送 |
| 预测维护 | 电流/扭矩 | 滑动窗特征 | 特征向量上云 |
架构图
┌──────────────────── PLC ─────────────────────┐
│ OB1 (10ms) │
│ ├── 采集 → MW 区 │
│ ├── 过滤 (Kalman / 中值 / 低通) │
│ ├── 规则引擎 (IF-THEN 快速决策) │
│ └── 写回控制输出 │
│ │
│ OB20 (1s 周期中断) │
│ ├── 聚合 (avg / min / max / P95) │
│ ├── 死区判定 (与上次发送值比较) │
│ └── 写入 DB_Upload │
└────────────────────┬──────────────────────────┘
│ 共享内存
┌──────────▼───────────┐
│ Service 网关 │
│ (调度 / 压缩 / 重试) │
└──────────┬───────────┘
▼ MQTT / HTTP
云平台
前置条件
- PLC 项目启用 OB20 周期中断 (默认 100ms, 支持降到 10ms)
- 变量表中目标变量标注
Archive = True - Service 端开启 EdgeProcessor 模块
详细步骤
1. 过滤: Kalman 去噪
工业现场的传感器读数往往带高斯白噪声, Kalman 滤波在已知过程方差 Q 与观测方差 R 的情况下给出最优估计。
FUNCTION_BLOCK FB_Kalman1D
VAR_INPUT
rawValue : REAL;
Q : REAL := 0.001; // 过程噪声
R : REAL := 0.5; // 观测噪声
END_VAR
VAR_OUTPUT
filtered : REAL;
END_VAR
VAR
xEst : REAL; // 状态估计
pEst : REAL := 1.0; // 估计方差
k : REAL; // 卡尔曼增益
initDone : BOOL;
END_VAR
IF NOT initDone THEN
xEst := rawValue;
initDone := TRUE;
END_IF;
// 预测: x = x (假设常值模型), p = p + Q
pEst := pEst + Q;
// 更新
k := pEst / (pEst + R);
xEst := xEst + k * (rawValue - xEst);
pEst := (1.0 - k) * pEst;
filtered := xEst;
其他滤波器选型:
| 滤波 | 适用 | 缺点 |
|---|---|---|
| 中值滤波 (5/7 点) | 尖峰毛刺 | 延迟半个窗口 |
| 低通 IIR (α=0.1) | 平滑缓变信号 | 响应滞后 |
| 滑动均值 | 固定噪声 | 窗口内激烈变化会被抹平 |
| Kalman | 最优 (已知模型) | 调参复杂 |
2. 聚合: 窗口统计
OB20 每秒计算一次上一窗口的 min / max / avg / P95。
FUNCTION_BLOCK FB_WindowStats
VAR_INPUT
newSample : REAL;
windowSize : INT := 600; // 600 个样本 = 1min@10Hz
END_VAR
VAR_OUTPUT
avg : REAL;
min : REAL;
max : REAL;
p95 : REAL;
END_VAR
VAR
buf : ARRAY[0..999] OF REAL;
idx : INT;
count : INT;
END_VAR
buf[idx] := newSample;
idx := (idx + 1) MOD windowSize;
IF count < windowSize THEN count := count + 1; END_IF;
// 仅在窗口满时计算
IF count = windowSize THEN
// ... 遍历 buf 求 min/max/avg/p95 (省略)
END_IF;
3. 压缩: 死区 / 摆动门
死区算法: 只有当新值相对上次发送值的绝对变化超过阈值, 才发送。
IF ABS(newValue - lastSent) > deadband THEN
uploadValue := newValue;
lastSent := newValue;
uploadFlag := TRUE;
END_IF;
更精细的摆动门 (Swing Door) 算法能保证重建误差 < epsilon, 压缩率比死区高 2-5 倍, 详见 Historian 章节。
4. 本地决策: 规则引擎
规则引擎把"IF...THEN" 抽象成可配置表, 非程序员也能改。
# rules.yaml
rules:
- id: overtemp_stop
when: "DB1.temperature > 80"
then:
- action: set_var
path: Q0.0
value: FALSE
- action: alarm
level: fatal
message: "超温紧急停机 T={{DB1.temperature}}℃"
cooldown_s: 60
- id: pressure_warn
when: "DB1.pressure > 1.5 and DB1.pressure < 1.8"
then:
- action: log
level: warn
message: "压力接近上限"
- id: predictive_wear
when: "stats.current.p95 > 12.0 and stats.current.avg > 9.0"
then:
- action: mqtt_publish
topic: factory/line1/alert/wear
payload: '{"current_p95": {{stats.current.p95}}}'
规则引擎在 Service 中解析并挂到 PLC 的变量订阅上, 本身不进入 PLC 扫描周期, 以免影响确定性。 确实需要进入扫描周期的硬停机规则 (如超温), 应该作为 SCL 代码写进 OB1, 规则引擎只做软告警和数据面决策。
5. OB1 / OB20 周期配合
// OB1 (10ms 周期, 决定性高)
temp_raw := IO_Read_AI(1);
temp_filtered := FB_Kalman1D(rawValue := temp_raw);
// 硬规则: 必须在 OB1 立即响应
IF temp_filtered > 85.0 THEN
Q_Heater := FALSE;
StartAlarm(ALARM_OVERTEMP);
END_IF;
// OB20 (1s 周期中断, 不影响 OB1)
stats := FB_WindowStats(newSample := temp_filtered);
IF ABS(stats.avg - lastSentTemp) > 0.5 THEN
DB_Upload.temp_avg := stats.avg;
DB_Upload.temp_p95 := stats.p95;
DB_Upload.ts := SystemTime_Ms();
lastSentTemp := stats.avg;
END_IF;
参数调优表
| 参数 | 默认 | 调优依据 |
|---|---|---|
| Kalman Q | 0.001 | 信号越平稳越小 |
| Kalman R | 传感器方差 | 查数据手册 |
| 滑动窗大小 | 600 (@10Hz=1min) | 按报表周期 |
| 死区阈值 | 精度的 2 倍 | 满足统计需求即可 |
| OB20 周期 | 1000 ms | 高频 10-100ms, 低频可 5000 |
| 规则冷却 | 60 s | 防止频繁触发 |
排错
| 现象 | 原因 | 措施 |
|---|---|---|
| OB1 超时 | 在 OB1 跑聚合了 | 把聚合挪到 OB20 |
| 云端数据抖动大 | 死区太小 / 滤波弱 | 加大死区或换 Kalman |
| 报警漏触发 | 规则在软引擎, 扫描周期没进 | 硬停机改成 SCL 代码进 OB1 |
| P95 一直 0 | 窗口没填满 | 等 count = windowSize 才有值 |
高级技巧
- 自适应死区: 值越大死区越大, 按量程的 0.1% 动态调整
- 特征工程: 滑动窗输出
mean/std/kurtosis/fft_peak给云端 ML 模型用 - 多级聚合: 1s → 1min → 1h, 逐级降采样上云, 本地保留高分辨率
- 事件驱动: 状态变化才发, 稳态不发
- 时间对齐: 所有聚合窗以整秒/整分对齐, 方便跨点合并