1. 一阶低通滞后滤波
原理:上次数据和本次数据赋予不同的权值,来达到减小噪声的作用
优点:对周期性干扰具有良好的抑制作用,适用于波动频率较高的场合。
缺点:相位滞后,灵敏度低,滞后程度取决于a值大小,不能消除滤波频率高于采样频率的1/2的干扰信号。
F
i
n
a
l
l
y
D
a
t
a
=
(
1
−
a
)
∗
L
a
s
t
D
a
t
a
+
a
∗
N
o
w
D
a
t
a
FinallyData=(1-a)*LastData+a*NowData
FinallyData=(1−a)∗LastData+a∗NowData
#define FIRST_LAG_PROPORTION 0.4//一阶滞后滤波的参数
float First_order_lag_filter(float *LastData,float Data)
{
return (1 - FIRST_LAG_PROPORTION) * (*LastData) + FIRST_LAG_PROPORTION * Data;
}
2. 递推平均滤波(滑动平均滤波)
(2022年4月1日编辑)
方法:
- 把连续取N个采样值看成一个队列
- 队列的长度固定为N
- 每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据.(先进先出原则)
- 把队列中的N个数据进行算术平均运算,就可获得新的滤波结果
(N值的选取:流量,N=12;压力:N=4;液面,N=4~ 12;温度,N=1~4)
优点:对周期性干扰有良好的抑制作用,平滑度高,适用于高频振荡的系统
缺点:灵敏度低,对偶然出现的脉冲性干扰的抑制作用较差,不易消除由于脉冲干扰所引起的采样值偏差,不适用于脉冲干扰比较严重的场合,比较浪费RAM;
PS:以下的代码是我根据之前考核学的顺序队列写的一个测试函数,但是他做了很多多余的动作,因为我们的滤波是不需要出队的,我们队满的时候把之前的数据覆盖即可,并且因为队列长度很容易充满,所以也没必要跟踪队列长度去确保分母;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXQUEUE 12
typedef struct AQueue
{
float Value[MAXQUEUE];//顺序队列数组
char front;//队头
char rear;//队尾
size_t length;//队列长度
}AQueue;
AQueue value_buf;
float Sliding_average_filter(float data)
{
float sum=0;
char i=0;
value_buf.Value[value_buf.rear]=data;//数据入队
value_buf.rear=(value_buf.rear+1)%MAXQUEUE;//队尾指针移动到下一位
if ((value_buf.rear+1)%MAXQUEUE==value_buf.front)//如果队尾的下一位等于队头
value_buf.front=(value_buf.front+1)%MAXQUEUE;//队满则队列长度不增加,但是要出队
else
value_buf.length++;
for ( i = 0; i < value_buf.length; i++)
{
sum+=value_buf.Value[i];
}
return sum/value_buf.length;
}
实际运用中用以下代码即可
#define MAXQUEUE 12
typedef struct AQueue
{
float Value[MAXQUEUE];//顺序队列数组
char AQflag;//标记变量
}AQueue;
AQueue value_buf;
float Sliding_average_filter(float data)
{
float sum=0;
char i=0;
value_buf.Value[value_buf.AQflag]=data;//数据入队
value_buf.AQflag=(value_buf.AQflag+1)%MAXQUEUE;//队尾指针移动到下一位
for ( i = 0; i < MAXQUEUE; i++)
{
sum+=value_buf.Value[i];
}
return sum/MAXQUEUE;
}
(编辑结束)