资讯动态

西门子S7-1200/1500模拟量滤波功能块:设计、SCL实现与参数整定

发布时间:2026/10/18 1:44:04 来源:尧图企业网站定制
做模拟量滤波这件事大多数搞工控的兄弟都躲不开。尤其是当现场一路4-20mA压力变送器的信号跳得像心电图、热电偶温度在PID画面上来回抖的时候你第一个念头往往就是“写个滤波程序把它按住”。不过等真动手写问题就来了滤波算法怎么选、时间常数取多少、电压电流热电偶要不要分开处理、S7-1200和S7-1500能不能共用一套代码。我最近整理的这个西门子PLC模拟量滤波功能块就是为了解决这些乱七八糟的现场问题而设计的。它通用S7-1200与S7-1500支持电压、电流及热电偶等多种信号类型选择把最常用的滤波算法封装成一个可复用的函数块拿到项目里改几个参数就能用。如果你正在被模拟量信号抖动、超调、误报警这些问题折磨或者正准备封装一套自己的模拟量处理库这篇文章应该能帮你少走不少弯路。我会把功能块的接口设计、滤波算法原理、SCL代码实现、参数整定方法以及现场排查经验一次讲清楚纯干货没有废话。1. 整体设计与方案选型1.1 为什么不用模块自带的平滑功能不少刚接触S7-1200/1500的朋友会问模拟量输入模块自带平滑滤波为什么还要自己写这里面的坑只有真正被它坑过的人才懂。西门子S7-1200/1500的模拟量输入模块确实自带了平滑功能比如SM1231模块可以在组态时选择“无”“低”“中”“高”四档平滑。这个平滑本质上是内部做移动平均对周期性噪声有一定抑制作用。但它的问题也很明显第一档位粒度太粗只有四档可选没有时间常数概念现场想要“稍微平滑一点”或者“再平滑一点”根本做不到第二模块平滑是全通道统一的不能针对不同通道配置不同滤波力度第三也是最关键的模块平滑的算法不透明你无法精确知道它对信号滞后了多少万一影响PID响应你连推算都无从下手。自己做滤波功能块本质上是要把“滤波”这个动作从硬件模块手里拿回来做成软件层面的可控资源。这样每个通道都能独立设置滤波参数算法公开透明滞后多少算得出来还能加入断线检测、量程归一化等额外逻辑。1.2 选FB不选FC的三个理由很多初学者在TIA Portal里创建程序时纠结选FB还是FC。滤波这种场景我的建议是果断选FB也就是函数块。第一个理由是FB自带背景数据块Instance DB。滤波算法需要记忆上一次的滤波输出值、滑动平均的历史缓冲区、初始化状态等变量。这些数据如果放在FC里要么用全局DB处处小心地管理要么用静态变量不好搞很容易在多次调用时互相干扰。FB的背景数据块天然为每个通道实例提供了私有的数据空间调用一个通道就建一个实例互不干扰干净利落。第二个理由是FB支持多实例编程。假设一台设备有16路模拟量输入你只需要创建一个FB然后在程序中声明16个FB实例或者用多实例静态调用每个实例维护各自通道的滤波状态调用代码写起来非常整洁。第三个理由是代码复用性。SCL写的FB不仅S7-1200能用S7-1500也能用代码几乎零移植成本。如果以后从1200升级到1500直接复制项目粘贴FB就完事了不需要重新开发。1.3 信号类型归一化的核心思路电压、电流、热电偶三种信号虽然来源不同但到了功能块内部处理逻辑可以收敛成一个统一模型原始值进来先做质量判断和量程归一化然后进入滤波算法最后输出滤波后的工程量。这个思路很像手机拍照的“ISP流水线”。不管镜头拍的是白天还是夜景进到处理器里都是先做降噪、白平衡、色彩校正这一套统一处理再输出成片。模拟量滤波也是这个逻辑先把不同信号类型统一成一个抽象的“百分比量程”滤波只在“0~100%”这个统一量纲上运算之后需要工程值时再反算回去。这样做的最大好处是滤波参数比如时间常数在不同信号类型之间可以统一标定不需要因为换了信号类型而重新推导滤波系数。当然热电偶和电压电流在细节上有区别这个在后面第2部分会展开讲。1.4 滤波算法怎么选一阶惯性 vs 滑动平均 vs 中值滤波接手一个滤波需求前先别急着写代码先搞清楚噪声长什么样。工业现场的模拟量噪声大致可以分为三类。第一类是高频随机噪声比如变频器干扰、电磁感应产生的毛刺信号在真实值附近快速上下抖动。这种噪声用一阶惯性滤波也叫一阶低通滤波效果最好计算量极小实时性高。第二类是周期性脉冲噪声比如电机换向、继电器动作引起的尖峰。这种噪声用中值滤波效果好但在PLC里实现排序逻辑稍显笨重而且对实时性有影响。第三类是缓慢漂移叠加的噪声比如信号在真实值基础上叠加了工频干扰的纹波。这种用滑动平均移动平均效果不错但滑动平均的缺点是会明显增大信号滞后窗口越大滞后越严重。我做的这个功能块把一阶惯性滤波和滑动平均两种算法都放进去了通过一个FilterMode参数切换。为什么没做中值滤波主要是出于通用性考虑。中值滤波在PLC里要维护一个排好序的数组S7-1200的小型CPU上做大数据量排序不划算而且绝大多数现场噪声场景用一阶惯性和滑动平均就能解决。真遇到罕见的多尖峰脉冲工况我一般建议在信号源侧加硬件滤波器或者屏蔽处理而不是过分依赖软件去兜底。算法适用场景参数滞后特性计算量一阶惯性高频随机噪声时间常数τ可控和τ正相关极小滑动平均周期纹波噪声窗口长度N固定滞后约N/2个周期小中值滤波脉冲尖峰噪声窗口长度N滞后较小较大未集成2. 功能块接口设计与信号类型处理2.1 接口变量怎么定义一个功能块好不好用接口设计占了七分。我的理念是接口宁多勿少参数要能覆盖现场绝大多数场景同时有默认值意识让调用者不至于面对一堆输入手足无措。核心输入变量包括RawValue原始模拟量值REAL类型单位是ADC转换后的整数比如0~27648或者已经转换为工程量比如温度值由用户根据自己组态方式决定。我在设计时更推荐先把原始值在OB1里转换成工程量再进入滤波块这样滤波块的调试界面看起来更直观。SignalTypeINT类型0代表电压信号1代表电流信号2代表热电偶信号。这个参数决定功能块内部要不要做断线检测以及量程上下限的默认处理方式。LoRange和HiRange量程上下限。对于电压和电流信号这两个值对应传感器量程的工程单位最低值和最高值。对于热电偶默认对应温度下限和上限。FilterModeINT类型0代表不滤波1代表一阶惯性滤波2代表滑动平均。TimeConst一阶惯性滤波的时间常数单位秒。这个参数决定滤波力度稍后在第3部分详细说推导。WindowSize滑动平均窗口长度INT类型范围建议2~64。窗口太长会导致严重滞后。SampleTime采样周期TIME类型。这个参数是滤波系数计算的依据设计上建议用循环中断OB30来调用功能块确保采样周期恒定。ManReset手动复位信号。当传感器检修、量程更换后需要清除滤波历史数据防止旧的滤波值影响新量程的启动阶段。输出变量包括FilteredValue滤波后的工程量输出。Active滤波是否生效的状态位。Status状态字用位表示不同报警状态。比如第0位表示断线报警第1位表示量程超限第2位表示输入无效。Quality信号质量百分比方便上位机做趋势图质量标识。2.2 电压、电流、热电偶三种信号的处理差异这三种信号在PLC内部的读取层面就已经有区别处理逻辑也要区别对待。电压信号0~10V或-10V~10V和电流信号0~20mA或4~20mA在S7-1200/1500的模拟量模块中ADC转换后都是整数范围通常是0~27648或者-27648~27648。这两种信号的量程转换逻辑完全一致都是线性的工程值 (ADC值 / 27648) × (量程上限 - 量程下限) 量程下限。唯一需要注意的差异在断线检测——4~20mA的标准做法是当电流低于约3.6mA时判定为断线这个阈值需要单独处理而电压信号的断线判断比较难做通常依赖模块自身的诊断位。热电偶信号就复杂一些。热电偶不是线性的其毫伏信号与温度的关系是非线性的必须经过冷端补偿和线性化查表才能得到温度工程量。好消息是S7-1200/1500的专用热电偶模块比如SM1231 TC已经在硬件内部完成冷端补偿和线性化CPU侧读到的就已经是温度工程量不需要在程序里做查表。所以热电偶场景下功能块收到的RawValue其实已经是温度值比如23.5摄氏度的REAL量程转换阶段可以直接跳过直接进入滤波阶段。但要特别注意热电偶模块在断线时会输出一个特殊值通常是一个很大的正数或负数程序里必须把这个特殊值识别出来绝不能把它当作正常温度去滤波。2.3 量程归一化和工程值转换的实现细节尽管三种信号原始形式不同但到了功能块内部我统一先把它映射到“0~100%”的归一化空间再滤波。以4~20mA信号为例假设量程对应0~100kPa那么工程值0kPa对应4mA、100kPa对应20mA。第一步先把电流或模块原始值换算成百分比值百分比 (当前值 - 量程下限) / (量程上限 - 量程下限) × 100。然后滤波算法只对百分比做运算输出的滤波百分比再反算回应工程值。这样做的好处是——滤波系数尤其是一阶惯性滤波的系数K的计算与信号量纲无关。不管你接的是0~10V对应0~50MPa还是4~20mA对应-40~150摄氏度只要采样周期相同同一个时间常数就能给出同样的滤波效果。这个特性对现场调试非常友好不需要为了不同量程的不同信号去重新算K值。当然也有例外如果设备功率很大信号跳变的剧烈程度和量程范围有关这时候可能需要对K做微调。但总体原则不变归一化空间让滤波参数具备跨项目复用能力我在多个项目中都是这么用的。3. 滤波算法原理与SCL实现3.1 一阶惯性滤波的数学推导与系数计算一阶惯性滤波本质上是模拟RC低通滤波器的离散化实现。它的连续域传递函数是H(s) 1 / (1 τ·s)其中τ是时间常数单位秒。对应到数字域标准的一阶低通离散形式为Y(n) Y(n-1) K × [X(n) - Y(n-1)]其中K是滤波系数取值范围0~1。K越大滤波越弱、跟随越快K越小滤波越强、滞后越大。K的准确计算公式是K 1 - exp(-Ts / τ)其中Ts是采样周期τ是时间常数。举例来说采样周期Ts100ms时间常数τ1秒那么K 1 - exp(-0.1/1) ≈ 0.0952。这意味着每一个采样周期滤波输出只向新输入值靠近9.52%。经过大约5个时间常数5秒输出才基本稳定到新输入值附近。很多初学者图省事直接把K写成固定值0.1或者0.2这在采样周期固定的情况下凑合能用但只要采样周期一变比如从OB1调用改为OB30调用滤波力度就完全变了。正确的做法是通过TimeConst和SampleTime实时计算K值这样即使调用周期改了滤波的时间响应特性依然一致。我在功能块里每次调用都重新算KK : 1.0 - EXP(-SampleTime_sec / TimeConst)特别注意SampleTime_sec需要从TIME类型换算成秒。TIME类型在SCL里直接参与浮点运算会出问题需要先转换成LREAL再除以1000.0。提示EXP指令在S7-1200/1500的SCL中可以直接调用但在S7-1200的部分老固件里浮点指令执行时间稍长如果程序扫描周期很紧建议把K值提前算好存到DB里而不是每个周期都算。实测下来S7-1511以上CPU完全没有压力。3.2 滑动平均的实现路径与边界处理滑动平均算法的思想很朴素维护一个长度为N的环形缓冲区每次采样把新值放进去把最旧的值丢掉然后输出缓冲区所有值的平均值。滑动平均对周期性噪声的抑制效果非常好尤其适合工频50Hz纹波叠加在信号上的场景。窗口长度N的选择有讲究N太小抑制不够N太大滞后严重。经验值是在采样周期100ms的情况下N取10~20比较合适对应1~2秒的平均窗口。实现上环形缓冲区用带索引的数组来写缓冲区长度我在功能块里固定为64实际可用长度由WindowSize参数控制。每次调用先把当前值写入Index位置然后Index加1并取模回绕。求平均值时把缓冲区前WindowSize个值累加后除以WindowSize。边界处理有几个容易踩坑的点。第一个是初始化阶段缓冲区还没填满时如果直接对未初始化的元素求平均输出会出现一段“从0爬升到真实值”的过程启动时会看到输出曲线异常。解决方法是加一个InitDone标志在缓冲区未填满时只对已填充的数据求平均。第二个是窗口尺寸改变时要重新初始化缓冲区否则旧窗口和新窗口的数据混在一起输出会出现跳变。我设计了ManReset引脚专门用于应对这种参数变更后的复位需求。还有一个细节是累加溢出问题。虽然窗口最多64个值但如果量程范围很大且REAL精度足够一般不会溢出。但在S7-1200的小型CPU上要留意累加运算使用了LREAL还是REALREAL的精度大约7位有效数字累加大数加小数时精度会丢严重时输出会有微小锯齿。稳妥做法是先累加再除以窗口长度且使用LREAL累加更保险。3.3 核心SCL代码实现说了这么多直接给出核心代码。这个功能块我命名为FB_AI_Filter接口和逻辑都按上文设计来实现。FUNCTION_BLOCK FB_AI_Filter { S7_OptimizedAccess : TRUE } VERSION : 0.1 VAR_INPUT RawValue : REAL; // 原始值工程量或ADC值由用户保证一致性 SignalType : INT; // 0电压, 1电流, 2热电偶 LoRange : REAL; // 量程下限工程单位 HiRange : REAL; // 量程上限工程单位 FilterMode : INT; // 0不滤波, 1一阶惯性, 2滑动平均 TimeConst : REAL : 1.0; // 一阶惯性滤波时间常数单位秒 WindowSize : INT : 10; // 滑动平均窗口长度 SampleTime : TIME : T#100MS; // 采样周期调用周期 ManReset : BOOL : FALSE; // 手动复位 END_VAR VAR_OUTPUT FilteredValue : REAL; // 滤波后的工程值 Active : BOOL; // 滤波激活指示 Status : WORD; // 状态字位0断线, 位1量程超限 END_VAR VAR LastValue : REAL; // 上一周期的滤波输出一阶惯性用 History : ARRAY[0..63] OF LREAL; // 滑动平均环形缓冲区 Index : INT; // 当前写指针 InitDone : BOOL; // 初始化完成标志 FillCount : INT; // 缓冲区已填充数量 Sum : LREAL; // 累加器 NormValue : REAL; // 归一化后的百分比值0~100 NormFiltered : REAL; // 归一化后的滤波值0~100 TempK : REAL; // 一阶滤波系数K SampleTimeSec : LREAL; // 采样周期秒 END_VAR功能块主逻辑// 1. 采样周期换算 SampleTimeSec : TIME_TO_LREAL(SampleTime) / 1000.0; IF SampleTimeSec 0.0 THEN SampleTimeSec : 0.1; // 防御性赋值 END_IF; // 2. 手动复位逻辑 IF ManReset THEN LastValue : 0.0; Index : 0; FillCount : 0; Sum : 0.0; InitDone : FALSE; FOR i : 0 TO 63 DO History[i] : 0.0; END_FOR; Active : FALSE; Status : 16#0000; END_IF; // 3. 信号有效性判断与断线识别 Status : 16#0000; IF (SignalType 1) AND (RawValue 3.6) THEN // 4~20mA信号电流低于3.6mA判定断线 Status : Status OR 16#0001; Active : FALSE; FilteredValue : 0.0; RETURN; END_IF; IF (SignalType 2) AND (RawValue 1.0E35) THEN // 热电偶模块断线通常输出极大值 Status : Status OR 16#0001; Active : FALSE; FilteredValue : 0.0; RETURN; END_IF; // 4. 量程归一化工程值 - 百分比0~100 IF HiRange LoRange THEN NormValue : (RawValue - LoRange) / (HiRange - LoRange) * 100.0; ELSE NormValue : 0.0; Status : Status OR 16#0002; END_IF; // 5. 超量程检查信号低于下限或高于上限但没断线 IF (NormValue -10.0) OR (NormValue 110.0) THEN Status : Status OR 16#0002; END_IF; // 6. 滤波主分支 CASE FilterMode OF 1: // 一阶惯性滤波 TempK : 1.0 - EXP(-SampleTimeSec / TimeConst); IF NOT InitDone THEN // 首次启动用当前值初始化避免从0爬升 LastValue : NormValue; InitDone : TRUE; END_IF; NormFiltered : LastValue TempK * (NormValue - LastValue); LastValue : NormFiltered; Active : TRUE; 2: // 滑动平均滤波 History[Index] : NormValue; Index : Index 1; IF Index 64 THEN Index : 0; END_IF; IF FillCount WindowSize THEN FillCount : FillCount 1; END_IF; Sum : 0.0; FOR i : 0 TO (FillCount - 1) DO // 从当前Index位置往前回溯FillCount个值 pos : (Index - 1 - i 64) MOD 64; Sum : Sum History[pos]; END_FOR; NormFiltered : Sum / FillCount; Active : TRUE; ELSE // 不滤波直通 NormFiltered : NormValue; Active : FALSE; END_CASE; // 7. 反算工程值百分比 - 工程值 FilteredValue : NormFiltered / 100.0 * (HiRange - LoRange) LoRange;这段代码里量程归一化、滤波、工程值反算三层逻辑非常清晰。你可能会注意到我在滑动平均的累加循环里用了(Index - 1 - i 64) MOD 64来计算位置这是一种从最新值往前回溯的写法避免每次判断越界的麻烦。MOD运算在整数上很好用64是缓冲区长度和数组声明对应。3.4 采样周期的稳定化为什么建议用循环中断滤波效果好不好有一个前提经常被忽略采样周期必须稳定。如果功能块在OB1里被调用而OB1的扫描周期受程序量影响波动很大比如某段程序执行快时循环10ms下次执行慢时循环30ms那么自定义的SampleTime参数就和实际调用周期不一致滤波系数K必然不准滤波效果自然不稳定。解决这个问题的最优做法是使用循环中断OBCyclic Interrupt OB。在S7-1200/1500中OB30默认周期是100ms可以修改为50ms、25ms等。把FB_AI_Filter的调用放在OB30里每个采样周期的间隔时间就是严格固定的SampleTime参数设置成和OB周期一致即可。选采样周期时也要考虑信号本身的频率特征。根据奈奎斯特采样定理采样频率至少要是信号最高频率的2倍工程上通常取5~10倍。对于温度信号这种变化很慢的过程量100ms甚至200ms采样都足够。对于转速、压力等快变量建议50ms甚至20ms采样。S7-1214C自带AI输入最多扩展到多个模块时CPU在OB30里能轻松处理几十个通道的滤波运算不会有性能压力。4. 实操组态、接线与调试4.1 硬件组态与模拟量模块设置先看硬件侧。S7-1200 CPU本身集成了模拟量输入比如S7-1214C集成2路0~10V输入也可以通过信号板SB1231扩展或者通过SM1231模块扩展AI通道。S7-1500则主要通过ET200MP系列的AI模块比如SM1231的1500版本或ET200SP的AI模块来扩展。组态时最重要的一个原则模块量程要和传感器信号类型严格匹配。比如接4~20mA的变送器模块通道的测量范围必须组态为4~20mA而不是0~20mA接K型热电偶要确认通道组态为K型且冷端补偿启用。这里如果配错后面调试时要么读到满量程要么信号完全不对排查起来非常头大。组态画面里通常还需要设置“诊断”参数把断线诊断使能打开。模块检测到断线后会向CPU发送诊断中断CPU侧的逻辑可以通过读取模块诊断信息或者检查读到的ADC值来判断。我在前面代码里直接通过电流阈值3.6mA做断线判断属于软件断线检测方案不依赖模块诊断中断通用性更强。接线层面的注意事项我也提一嘴模拟量信号线必须使用屏蔽双绞线屏蔽层在PLC侧单端接地千万避免两端接地形成地环路信号线远离变频器输出线和大电流动力电缆穿管走线时差距保持至少20厘米以上。很多棘手的信号抖动问题根源不在软件滤波而在接线不规范滤波程序只能兜底治标不治本。4.2 在TIA Portal中创建FB并调用创建功能块的步骤简单过一遍。在TIA Portal的项目树中选中“程序块”右键选择“添加新块”类型选择“函数块”编程语言选择SCL名称填写FB_AI_Filter。把上面的代码粘贴进去编译一次看看有没有语法问题。然后在OB30如果没有可以添加一个新的循环中断OB设置周期为100ms里面调用。先添加一个背景数据块实例比如命名为“AI_Filter_Channel1”然后调用它AI_Filter_Channel1( RawValue : Sensor_Value_1, // 从AI模块读取并转换后的原始工程值 SignalType : 1, // 电流信号 LoRange : 0.0, HiRange : 100.0, // 量程0~100kPa FilterMode : 1, TimeConst : 2.0, // 时间常数2秒 WindowSize : 10, SampleTime : T#100MS, // 与OB30周期一致 ManReset : Reset_AI1 );如果现场有多个通道就建多个实例。在S7-1200上每个实例对应一个背景DB占用一点数据区空间实例多了要注意CPU的DB容量上限。S7-1500的容量大得多16路甚至几十路通道都不是问题。注意TIA Portal的版本会影响SCL语法兼容性。V15以上版本对LREAL、REAL混合运算的自动转换更友好。如果用的版本较老可能需要显式加上类型转换指令比如REAL_TO_LREAL、LREAL_TO_REAL编译报错时按提示逐个处理就行。4.3 在线调试与波形观察功能块写好后调试才是重头戏。我的调试步骤基本是固定的。先把FilterMode设为0直通观察原始信号的波形。在TIA Portal的监控表或使用PLC变量的趋势曲线功能把RawValue加进趋势图运行几分钟观察噪声的幅度和频率特征。这一步很重要目的是摸清噪声底细方便后续选择滤波算法和设定参数。然后把FilterMode切到1一阶惯性TimeConst从0.1秒开始慢慢增大。每改一次参数观察滤波后曲线直到噪声幅度被压到可接受范围。判断滤波是否“过头”有个标准看被滤波的信号在真实值变化时跟随延迟是否导致控制品质下降。比如压力信号在阀门动作后1秒内应该响应新设定值如果滤波让它3秒才反应过来这就需要减小时间常数。最后用阶跃测试验证。给传感器一个阶跃输入比如直接切换量程校准器记录滤波输出从变化开始到稳定到目标值63.2%的时间这个时间应该约等于设置的时间常数τ。如果实测偏差过大检查SampleTime设置是否正确是否真的用了循环中断。4.4 参数整定的工程经验关于参数整定我给几条经过实测总结的经验。温度信号热电偶、热电阻这类信号本身惯性大噪声以小幅高频抖动为主。时间常数取1~5秒比较合适。我曾在一个反应釜温度测点上用τ3秒波动从±1.5℃压到了±0.2℃以内完全够用。压力信号取决于负载波动频率。管道压力通常噪声较大但响应要求也高。τ取0.2~1秒是比较折中的范围。如果要求在快变工况下跟踪性能好宁可残留一点噪声也不要滞后太多。流量信号差压式流量计的输出天生带有较强的湍流脉动τ取0.5~2秒配合滑动平均模式也常用。流量测量对滞后要求相对宽松因为流量本身波动大、规律性弱平滑后更适合累积计算。液位信号液位变化相对缓慢但容易受到进料冲击产生毛刺。滑动平均窗口取10~20效果不错但要注意液位是积分对象过强的滤波倒不会破坏稳定性反而会让真实变化被抹平导致误判断所以τ一般不超过2秒。电机的电流反馈如果信号用于过流保护逻辑绝对不能过度滤波。保护信号的滤波时间常数超过200毫秒就可能带来保护动作延迟风险非常危险。这种场景建议直接关闭滤波或者在信号源上用硬件方式处理。5. 常见问题与排查技巧实录5.1 滤波后输出发散或震荡这多半是K值计算出了问题。常见原因有两个一是TimeConst设置成了0除零导致K值计算异常二是SampleTime设置成了0。我在代码里做了防御性处理但如果你改过代码把防御去掉这些情况就会爆发。排查方法是先在监控表里看TempK的值。正常情况下TempK在0到1之间如果看到TempK等于1意味着完全不滤波全直通或者大于1意味着过冲放大就要检查时间常数和采样周期这两个输入。另外还要注意EXP(-SampleTimeSec / TimeConst)在TimeConst非常小比如0.0001秒时K会非常接近1此时滤波几乎不起作用表现出来也和“发散”类似。还有一种容易忽略的情况TimeConst和SampleTime的量纲不对。TIME类型如果传成了T#100S而不是T#100MSSampleTimeSec就是100秒K值几乎为0滤波输出几乎不跟随输入看起来像信号“卡死”了。这类问题要看监控表的SampleTime实际值才能发现。5.2 量程不匹配导致滤波后跳变现场最常见的跳变原因是模块组态量程和功能块中输入的量程上限下限不一致。比如传感器量程0~100kPa但模块组态成0~20mA功能块里LoRange和HiRange却填了0~100kPa此时ADC读满量程时工程值换算出来是100百分比110%以上就会触发超量程状态位但滤波输出本身可能不跳。真正的跳变场景通常是信号在量程边缘来回切换时超量程限幅逻辑没有做导致百分比进到110%或-10%之外反算出来就是超出工程范围的怪异数值。处理办法是在功能块里加限幅逻辑。我提供的代码里只做了超量程报警没有强制限幅。如果需要硬限幅可以在反算工程值之前加上IF NormFiltered 100.0 THEN NormFiltered : 100.0; ELSIF NormFiltered 0.0 THEN NormFiltered : 0.0; END_IF;这样输出严格限制在量程范围内不会出现怪值。上位机显示的曲线也更漂亮。5.3 热电偶断线后滤波输出异常热电偶断线时模块通常会输出一个很大的正数或负数取决于模块品牌和具体型号。如果功能块没有检测这个值就直接进入滤波器滤波输出会被拉向最大值或者最小值然后再慢慢恢复这个过程中会触发超限报警严重时还会干扰控制逻辑。我的代码里用IF RawValue 1.0E35来判断断线这个阈值来自西门子热电偶模块断线时输出的典型值。但不同模块的输出特征不同有的模块在断线时输出的是-2000℃或9999℃需要根据具体模块手册来调整判断阈值。稳妥的写法是把阈值做成一个输入参数让用户根据实际模块来配置。另外热电偶断线检测的报警要做好记录。现场热电偶断线是高频故障尤其是振动环境下的热电偶探头松脱、引线断裂屡见不鲜。状态字的断线位一定要传到上位机或者HMI故障列表方便维护人员快速定位。5.4 扫描周期不稳定导致滤波不均匀如果你图省事把FB放在OB1里调用而OB1扫描周期因为其他程序的执行时间不同而变化你就会发现滤波效果时好时坏甚至滤波曲线锯齿感明显。这里有个实际案例。某项目上OB1里写了一段上位机通信处理通信偶尔占用长执行时间导致OB1循环周期在15ms到80ms之间跳动。滤波功能块在OB1里调用虽然代码里按SampleTime50ms计算K但实际调用间隔忽长忽短滤波输出就出现了肉眼可见的“抖动阶梯”。解决办法不是改滤波参数而是改调用位置。把功能块挪到OB30循环中断中设置固定周期50ms问题立刻消失。这也是我强烈建议使用循环中断的原因。如果你的CPU资源紧张OB30的周期设置得长一些比如200ms只要信号采样需求满足滤波效果照样稳定。5.5 快速排查速查表现象可能原因排查/解决办法滤波输出完全不跟随输入TimeConst过大或SampleTime过大导致K≈0检查两参数确认TIME单位是否正确滤波后仍有大噪声时间常数太小滤波力度不足增大TimeConst观察曲线变化滤波后响应明显滞后TimeConst过大或窗口N过大减小TimeConst/WindowSize平衡噪声抑制和响应速度启动时输出从0爬升初始化逻辑没有用首值填充检查InitDone逻辑首次采样应直接置为当前值某个通道滤波失效背景DB被意外覆盖或ManReset常置1检查ManReset信号是否被错误绑定热电偶断线后输出满量程断线阈值判断不对查看模块手册调整断线判断阈值滤波值出现锯齿累加使用REAL导致精度丢失改用LREAL累加调参没有效果功能块实际调用周期与SampleTime不一致确认是否在OB30中调用SampleTime是否与OB周期一致最后再分享一个实操中的小经验滤波功能块这个项目做完后我在好几个现场都实际跑过。说实话软件滤波永远是最后的兜底手段而不是首选手段。我在一个物料输送系统上遇到过一路料位信号跳动非常剧烈开始以为是干扰又是加屏蔽又是改滤波参数最后排查发现是雷达料位计的安装角度偏了物料下料时雷达波打在料堆斜坡上产生了虚假回波。把安装角度纠正后信号比什么滤波都干净。所以在项目交付时我都会给现场的电气维护人员强调一句话滤波可以平滑信号但掩盖不了源头故障。如果某个测点的信号突然变得异常脏第一反应应该是检查传感器、接线、安装环境而不是试图用更大的时间常数把故障信号“强行压平”。滤波参数要留有余地一旦时间常数大到了掩盖真实故障特征的程度系统会变得迟钝安全隐患也随之而来。这个功能块后续还可以继续扩展比如加入智能限幅、阶跃检测自适应切换滤波强度甚至接入自整定逻辑根据实时噪声特征自动调整时间常数。如果后面有时间我会把这些高级功能逐步补上做个更完善的版本分享出来。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑