当前位置: 首页 > news >正文

【算法】指数滑动滤波器

指数滑动滤波器

  • 作用
  • 原理
  • 特点
  • 公式
  • 代码
    • 优化升级

作用

首先这个滤波器能够将一些突变的信号对系统的影响降低,能够平滑输入信号,滤除噪声,减少测量数据的瞬间波动和干扰,就是实现输入信号不能不变,数值不会突然变大,比如你根据编码器的值控制呼吸灯的亮度,如果编码器突然拉的值很大,呼吸灯不会立刻变得很亮,会慢慢亮。

原理

原理就是不完全采样当前的输入信号,而是将输入信号的值和上一刻滤波后的输入信号做一个权重划分,然后得到最终滤波后的信号值,比如前一刻滤波后是10V,当前采样的电压是5V,假如设置前一刻的权重是90%,当前采样的信号权重是10%,则将100.9+50.1 = 9.5V,这就是滤波后的结果,不会说因为10V掉到5V,我对应的输出也立刻改变,而是先按照9.5V对应输出,如果后面保持5V,那么根据权重划分输出信号也会慢慢降低的,只是响应没那么快。

特点

特点就是响应没那么快,但是输出信号会平滑,所以这个权重的设定也非常的重要,如果历史值(也就是上一刻的滤波结果)占的权重比较大,就会导致响应非常的缓慢,如果历史值的权重比较小,就会导致信号平滑的效果不是那么好。

所以需要注意系统刚开始运行的时候,输出信号也是要缓慢变化才能达到目标值,这是因为系统第一次滤波时上一刻的滤波结果为0,如果想要在系统刚开始运行时就达到目标值附近在开始滤波,可以在进行第一次滤波时给上一刻滤波结果赋当前输入值,让系统更快速达到目标值附件。

公式

y[n]=a×x[n]+(1−a)×y[n−1]y[n] = a \times x[n] + (1 - a) \times y[n-1]y[n]=a×x[n]+(1a)×y[n1]

  • x[n] 是最新的测量值
  • y[n] 是滤波后的输出值
  • a 是滤波器“记忆权重”,越小说明当前输入影响越小,滤波越平滑(但响应慢)

代码

下面给出一段Python的案例代码:

import numpy as npdef exponential_filter(input_signal, a):"""单一输入信号的指数滑动滤波:param input_signal: 输入信号列表:param a: 滤波系数(本次输入权重),0 < a < 1:return: 滤波后的输出信号列表"""output_signal = [input_signal[0]]  # 以第一个输入作为初始滤波值for n in range(1, len(input_signal)):y_prev = output_signal[-1]x_curr = input_signal[n]y_curr = a * x_curr + (1 - a) * y_prevoutput_signal.append(y_curr)return output_signal# 模拟你的滤波系数
a_vdc = 1 / 16  # vdc权重# 示例输入信号,替换成你的采样数据
np.random.seed(0)
input_vdc = 17 + 2 * np.random.randn(100)  # 模拟带噪声电压信号filtered_vdc = exponential_filter(input_vdc, a_vdc)# 输出前10个滤波值查看
for i in range(10):print(f"原始vdc: {input_vdc[i]:.3f}, 滤波vdc: {filtered_vdc[i]:.3f}")

结果如下:

原始vdc: 20.528, 滤波vdc: 20.528
原始vdc: 17.800, 滤波vdc: 20.358
原始vdc: 18.957, 滤波vdc: 20.270
原始vdc: 21.482, 滤波vdc: 20.346
原始vdc: 20.735, 滤波vdc: 20.370
原始vdc: 15.045, 滤波vdc: 20.037
原始vdc: 18.900, 滤波vdc: 19.966
原始vdc: 16.697, 滤波vdc: 19.762
原始vdc: 16.794, 滤波vdc: 19.576
原始vdc: 17.821, 滤波vdc: 19.467

这里可以看出滤波后的值并不会由于原始vdc的值的变化而发生比较大的突变,接下来给出在单片机中C语言的实现代码

u16 DataFilter(u16 dat) {static u16 s_u16LastDat;	// 记录历史值float a = 0.9;				// 历史值权重u16 result;// 进行指数滤波计算result = a * s_u16LastDat + (1 - a) * dat;// 记录当前滤波结果用于下次计算s_u16LastDat = result;return result;
}

优化升级

虽然这样写可以,但是可以考虑一下单片机的性能问题,对单片机来说浮点运算是非常耗时的,因为有些单片机没有浮点单元(大部分都没有把),所以接下来对这段代码进行优化升级:

u16 DataFilter(u16 dat) {static u16 s_u16LastDat;	// 记录历史值u16 result;// 进行指数滤波计算,历史权重比为0.9375result = (dat >> 4) + ((s_u16LastDat * 15) >> 4);// 记录当前滤波结果用于下次计算s_u16LastDat = result;return result;
}

通过右移的方式,把乘除运算变成位移能够大幅提高运算速度,这里是如何设置权重的呢,>>4相当于➗16,所以系数a = 1/16 = 0.0625,而*15>>4相当于✖15在➗16,系数a=15/16 = 0.9375;最终的权重和还是为1的,只是将权重刚好设置成2的倍数,就能够通过位移完成计算。

最后需要提醒一下这个权重系数的设置关系整个系统的性能,需要根据实际情况选择合适的权重比。

http://www.dtcms.com/a/310288.html

相关文章:

  • 算法篇----位运算
  • 基于SAMP算法OFDM系统信道估计
  • 学习笔记090——Ubuntu 中 UFW 防火墙的使用
  • 香港正式启动稳定币牌照制度!推动中国的人民币国际化?
  • 本地浏览器设置上网代理服务
  • Linux编程: 10、线程池与初识网络编程
  • 通用障碍物调研
  • Java 大视界 -- Java 大数据机器学习模型在电商产品定价策略优化与市场竞争力提升中的应用(375)
  • 阿里云oss上传文件 普通上传和分片上传方法封装
  • Unity UI的未来之路:从UGUI到UI Toolkit的架构演进与特性剖析(7)
  • 小杰数据结构(four day)——藏器于身,待时而动。
  • PNP机器人机器人学术年会展示灵巧手动作捕捉方案。
  • 【高等数学】第七章 微分方程——第六节 高阶线性微分方程
  • C# StringBuilder类及其使用方法
  • 【LeetCode 热题 100】394. 字符串解码
  • 合并对象 递归注意对象的合并时机
  • 20257月29日-8月2日训练日志
  • Codeforces Round 1040 (Div. 2)(补题)
  • Java函数式编程之【基本数据类型流】
  • Thymeleaf 模板引擎原理
  • 删除MicroGame
  • 设计模式之职责链模式
  • Android 中 Intent 的显式和隐式使用方式
  • Alpine Linux 设置镜像的时区
  • ONLYOFFICE 深度解锁系列.14-如何在ONLYOFFICE表格中调用异步API,集成外部数据源
  • R语言基础图像及部分调用函数
  • MyEclipse启动OutOfMemoryError内存溢出
  • 笔试——Day25
  • 【数据结构入门】顺序表
  • linux81 shell通配符:[list],‘‘ ``““