C语言实现滑动平均滤波器

前言

使用电机速度做闭环控制时,发现传感器的数据受到了高频噪声的影响,于是想先对其进行滤波处理。

原理

滑动平均滤波器本质是一个低通滤波器,可以看成FIR滤波器的一个特例。其时域表达为

y ( k ) = 1 N ∑ i = 0 N − 1 x ( k + i ) y(k)=\frac{1}{N} \sum_{i=0}^{N-1} x(k+i) y(k)=N1i=0N1x(k+i)
,其中N为滤波器长度。

代码

代码比较简单,我就没有注释。大概思想就是设置一个滤波器长度的数组,然后不断更新数组内容,再求平均就可以了。写的时候发现其实用队列写应该会更快,但是我懒了一把,因为单片机性能够用所以就算了,如果有写出来的,欢迎一起讨论哈。

/*滑动平均滤波器长度*/
#define MVF_LENGTH 8
float moving_average_filtre(float xn)
{
  static int index = -1;
  static float buffer[MVF_LENGTH];
  static float sum = 0;
  float yn = 0;
  int i = 0;
  if(index == -1)
  {
	//初始化
    for(i = 0; i <MVF_LENGTH; i++)
    {
      buffer[i] = xn;
    }
    sum = xn*MVF_LENGTH;
    index = 0;
  }
  else
  {
    sum -= buffer[index];
    buffer[index] = xn;
    sum += xn;
    index++;
    if(index >= MVF_LENGTH)
    {
      index = 0;
    }
  }
  yn = sum/MVF_LENGTH;
  return yn;
}

讨论

滑动平均滤波器的长度选择也是个值得讨论的问题。太短的话消除了不了高频噪声,太长的话延迟比较严重。
参考文章里给出了滤波器长度与系统截止频率的经验公式:
N = 0.443 ∗ f s / f c o \mathrm{N}=0.443* \mathrm{f}_{\mathrm{s}} / \mathrm{fco} N=0.443fs/fco

其中,fs为采样频率,fco为截至频率。推导的过程简单讲就是假设输入信号为正弦信号,且将离散信号变为连续信号之后,对输出信号进行傅里叶变换,进而得到他们的关系。
在这里插入图片描述
滑动平均滤波器频率响应

图片来源:https://www.cnblogs.com/pingwen/p/6670675.html

改进

最近又看到一个改进的计算公式,可以节省计算时间,原理很简单,学而不思则罔啊。

改进后的公式为:

y ( k ) = y ( k − 1 ) + 1 N ( x ( k ) − x ( k − N ) ) y(k)=y(k-1)+\frac{1}{N} (x(k)-x(k-N)) y(k)=y(k1)+N1x(k)x(kN)

参考文章

截止频率和MAF滤波器长度关系

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值