ST怎么写模拟量滤波:Avg := (OldAvg * 0.9) + (NewVal * 0.1);

发布于 2026-03-15 04:09:32 · 浏览 2 次 · 评论 0 条

在电气自动化系统中,模拟量信号(如温度、压力、流量、电压等)常受现场电磁干扰、传感器噪声或传输线路耦合影响,导致采集值跳变、抖动。这种波动若直接用于控制逻辑(如PID调节、报警判断、趋势记录),会引发误动作、频繁启停、控制震荡甚至设备损伤。因此,对模拟量做实时滤波是工程实施中的基础且关键环节。

结构化文本语言(Structured Text,ST)作为IEC 61131-3标准定义的五大PLC编程语言之一,语法简洁、可读性强、支持浮点运算与复杂数学表达式,非常适合实现数字滤波算法。其中,一阶指数加权移动平均(First-order Exponential Weighted Moving Average,简称EWMA)因其计算量小、内存占用低、响应特性可控,成为工业现场最常用的方法。其核心公式即为:

$$ \text{Avg} := (\text{OldAvg} \times 0.9) + (\text{NewVal} \times 0.1) $$

该式看似简单,但要真正可靠、可复用、可维护地部署于真实PLC项目中,需系统解决变量声明、初始化、数据类型匹配、抗饱和处理、使能控制、参数配置化等十余个实操细节。本文将全程以ST语言为载体,不依赖任何特定品牌PLC(如西门子S7-1200/1500、罗克韦尔ControlLogix、倍福TwinCAT),仅使用IEC 61131-3通用语法,手把手带你写出一段可直接粘贴进工程、经得起长期运行考验的模拟量滤波程序。


一、理解公式背后的物理意义与工程参数

公式 Avg := (OldAvg * 0.9) + (NewVal * 0.1) 不是随意设定的系数,它对应一个明确的时间常数(Time Constant)τ,决定滤波器对突变信号的“迟滞”程度。

设采样周期为 T(单位:秒),则滤波系数 α = 0.1 与时间常数 τ 的关系为:

$$ \alpha = 1 - e^{-T/\tau} $$

α = 0.1 时,解得 τ ≈ 9.5T。这意味着:

  • 若PLC主任务扫描周期 T = 100 ms,则该滤波器的时间常数约为 950 ms
  • 输入信号发生阶跃变化后,输出需约 3τ ≈ 2.85 s 才能到达终值的 95%
  • 高频噪声(周期远小于 τ)被显著衰减,而缓慢变化的过程量得以保留。

关键结论0.1 不是固定值,而是可调参数。工程中应根据信号特性与控制要求动态配置。例如:

  • 压力变送器(响应慢、噪声小)→ α = 0.05(τ ≈ 19T,更平滑);
  • 热电偶冷端补偿(易受工频干扰)→ α = 0.2(τ ≈ 4.5T,更快响应);
  • 频繁开关负载引起的电压毛刺 → α = 0.3(τ ≈ 2.5T,强抑制)。

因此,绝不能将 0.90.1 写死在代码里。必须将其抽象为可配置变量。


二、ST程序结构设计:模块化、可复用、防错

一个健壮的滤波功能块(FB)应包含以下要素:

要素 说明 必要性
Input 原始模拟量输入(REAL) ★★★★☆
Enable 使能信号(BOOL),控制滤波是否生效 ★★★★☆
Alpha 滤波系数 α(REAL,范围 0.0–1.0) ★★★★★
Reset 复位信号(BOOL),强制清零历史值 ★★★★☆
Output 滤波后输出(REAL) ★★★★☆
OldAvg 内部保持变量,存储上一周期滤波值 ★★★★★
初始化保护 首次执行时避免 OldAvg 为未定义值(如0.0或NaN) ★★★★★

注:“必要性”星级表示该要素缺失将导致功能失效(★★★★★)或可靠性下降(★★★☆)


三、完整ST代码实现(符合IEC 61131-3,无品牌依赖)

以下代码可直接复制到支持ST的PLC编程环境(如Codesys、TIA Portal ST编辑器、Unity Pro ST视图)中,作为独立功能块(Function Block)使用。

FUNCTION_BLOCK FB_AnalogFilter
VAR_INPUT
    Input   : REAL;         // 原始模拟量(如PT100转换后的℃值)
    Enable  : BOOL := TRUE; // 默认启用滤波
    Alpha   : REAL := 0.1;  // 默认滤波系数(α=0.1 → τ≈9.5T)
    Reset   : BOOL := FALSE;// 复位请求(上升沿有效)
END_VAR

VAR_OUTPUT
    Output  : REAL;         // 滤波后输出
END_VAR

VAR
    OldAvg  : REAL := 0.0;  // 静态变量:保持上一周期滤波值
    bReset  : BOOL := FALSE;// 内部复位标志(检测上升沿)
    bFirst  : BOOL := TRUE; // 首次执行标志(确保OldAvg安全初始化)
END_VAR

// ===== 步骤1:检测Reset上升沿 =====
bReset := Reset AND NOT bReset;
bReset := bReset OR (NOT Reset AND bReset); // SR触发器防抖(可选,增强鲁棒性)

// ===== 步骤2:复位处理 =====
IF bReset THEN
    OldAvg := Input; // 复位时直接加载当前值,避免突变
    bFirst := TRUE;
ELSIF bFirst THEN
    // 首次执行:用Input初始化OldAvg,避免0.0导致初始偏差
    OldAvg := Input;
    bFirst := FALSE;
END_IF;

// ===== 步骤3:使能判断与滤波计算 =====
IF Enable THEN
    // 关键:先检查Alpha有效性,防止除零或溢出
    IF (Alpha >= 0.0) AND (Alpha <= 1.0) THEN
        Output := (OldAvg * (1.0 - Alpha)) + (Input * Alpha);
        OldAvg := Output; // 更新历史值供下周期使用
    ELSE
        // Alpha越界:直通原始值,并可选置位诊断位(此处省略)
        Output := Input;
    END_IF;
ELSE
    // 使能关闭:直通原始值,OldAvg保持不变(维持状态)
    Output := Input;
END_IF;

四、关键细节逐行解析(为什么这么写?)

  1. VAROldAvg := 0.0 的初始化含义
    := 是IEC 61131-3的初始赋值操作符,仅在功能块首次实例化时执行一次。后续每次调用,OldAvg 保持上周期结束时的值(即“静态变量”行为)。这是实现递归滤波的基础。

  2. bFirst := TRUE 与首次赋值逻辑
    PLC上电后,某些平台可能将REAL变量初始化为NaN(非数字)。若直接执行 (NaN * 0.9) + (Input * 0.1),结果仍为NaN,导致整个滤波链失效。bFirst 标志确保第一周期用 Input 安全填充 OldAvg,彻底规避NaN风险。

  3. Reset 上升沿检测的双稳态写法

    bReset := Reset AND NOT bReset;
    bReset := bReset OR (NOT Reset AND bReset);

    这是经典的SR触发器(置位-复位锁存器)ST实现。它将瞬时 Reset 信号锁存为一个持续周期的 bReset 脉冲,确保复位动作只执行一次,避免因 Reset 信号持续多个周期导致反复覆盖 OldAvg

  4. Alpha 越界保护的必要性
    若误将 Alpha 设为 1.5,则 (1.0 - Alpha) 为负数,滤波器变为发散型(输出振荡放大);若设为 -0.2,则 1.0 - Alpha = 1.2,同样导致不稳定。该判断是工业代码的必备防御措施。

  5. Enable = FALSEOldAvg 保持不变的设计意图
    当滤波被禁用(如维护模式),输出直通 Input,但 OldAvg 不更新。一旦重新启用,滤波从上次保存的状态继续,避免输出跳变。这是平滑切换的关键。


五、工程部署建议(不止于代码)

1. 参数配置方式

  • 在HMI或上位机中,为每个滤波实例提供 Alpha 设置框,标注对应 τ/T 值(如“α=0.1 → 平滑时间≈9.5个扫描周期”);
  • 对同一类传感器(如所有PT100),在项目库中预设典型 Alpha 值,减少现场调试工作量。

2. 诊断与监控

  • 在功能块中增加 Status 输出(如 BOOL 数组),标记 AlphaOutOfRangeNaNDetected 等状态;
  • OldAvgInputOutput 同时映射至HMI趋势图,直观对比滤波效果。

3. 多通道批量处理

若需同时滤波10路温度信号,不要复制10次功能块代码。正确做法:

  • 声明数组:arrTempRaw : ARRAY[1..10] OF REAL;
  • 实例化单个功能块:FB_Filter10 : FB_AnalogFilter;
  • 循环调用:
    FOR i := 1 TO 10 DO
        FB_Filter10(Input := arrTempRaw[i], Alpha := 0.1, Enable := TRUE);
        arrTempFiltered[i] := FB_Filter10.Output;
    END_FOR;

4. 与硬件滤波协同

ST软件滤波不能替代前端硬件措施:

  • 传感器屏蔽线必须单点接地;
  • 模拟量输入模块应启用内置的50/60Hz陷波(如S7-1200的“Filter frequency”设置);
  • 强干扰环境加装信号隔离器。
    软件滤波是硬件滤波的补充,而非替代。

六、性能验证方法(现场必做)

编写测试用例,在真实PLC中验证滤波器行为:

  1. 阶跃响应测试

    • 给定 Input25.0 突变至 35.0(Δ=10.0);
    • 记录 Output 每周期值;
    • 验证第1周期:Output = 25.0×0.9 + 35.0×0.1 = 26.0
    • 第2周期:26.0×0.9 + 35.0×0.1 = 26.9
    • 依此类推,确认收敛曲线符合 Output = 35.0 - 10.0×e^(-n×0.1)(n为周期数)。
  2. 抗噪能力测试

    • 叠加±0.5℃随机噪声到稳定30.0℃信号;
    • 观察 Output 波动幅度是否压缩至±0.05℃以内(理论衰减比≈α=0.1)。
  3. 边界压力测试

    • Alpha := 0.0Output 应恒等于初始 OldAvg(直通关闭);
    • Alpha := 1.0Output 应恒等于 Input(无滤波);
    • Input := NANOutput 应保持上一有效值(不传播NaN)。

七、常见错误及修正方案

错误现象 根本原因 修正动作
滤波输出缓慢爬升,始终追不上 Input OldAvg 未正确更新(如漏写 OldAvg := Output; 检查代码末尾赋值语句
上电后输出为0或极大值 OldAvg 初始值未保护,遇NaN 强制添加 bFirst 初始化逻辑
Reset 一次后,后续再按无效 bReset 未在执行后清零 IF bReset THEN ... END_IF; 块内末尾添加 bReset := FALSE;
HMI显示 Output 跳变 Enable 信号在切换瞬间抖动 Enable 输入前增加100ms硬件消抖或软件延时滤波

八、进阶:自适应滤波(可选扩展)

当过程动态特性变化大(如加热阶段 vs 恒温阶段),固定 Alpha 效果不佳。可升级为自适应版本:

// 计算输入变化率
Delta := ABS(Input - OldAvg);
// 动态调整Alpha:变化大时增大Alpha(快响应),变化小时减小Alpha(强滤波)
IF Delta > 0.5 THEN
    Alpha := 0.25;
ELSIF Delta < 0.05 THEN
    Alpha := 0.05;
ELSE
    Alpha := 0.1;
END_IF;

此逻辑需谨慎评估CPU负载——每毫秒级任务中避免过多分支计算。


九、总结:一条可落地的黄金准则

所有模拟量进入控制逻辑前,必须经过显式、参数化、带诊断的滤波;滤波系数 Alpha 必须作为可配置参数暴露给调试人员,严禁硬编码;首次运行与复位场景必须有确定性初始化,杜绝NaN与不确定状态。

这一准则不是理想主义,而是数十年工业现场故障分析沉淀出的血泪经验。当你写下 Avg := (OldAvg * 0.9) + (NewVal * 0.1) 时,你写的不仅是一行数学表达式,更是一道守护系统稳定性的逻辑闸门。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文