//==========================================================中间值滤波===============================================
优点:能有效克服因偶然因素引起的波动干扰;对温度、液位等变化缓慢的被测参数有良好的滤波效果
缺点:对流量,速度等快速变化的参数不宜
/*中间值滤波
* input:传入的数
* N:采集总次数
* BAN:从小到大排列后,左右两端各舍去的数量
* 注意:N > 2 * BAN
*
*/
#define N 300
#define BAN 100
uint32_t Get_MedianFiltering(uint16_t input)
{
uint16_t ValueBuff[N]={0},Valuetemp=0;
uint32_t count = 0, i=0, j=0;
uint32_t sum=0;
for(count=0;count<N;count++)
ValueBuff[count] = input;
for( j = 0 ;j< N-1 ;j ++)
{
for( i = 0 ;i< N-j ;i ++)
{
if(ValueBuff[i] > ValueBuff[i+1])
{
Valuetemp = ValueBuff[i];
ValueBuff[i] = ValueBuff[i+1];
ValueBuff[i+1] = Valuetemp;
}
}
}
for(count = BAN;count <N - BAN;count++)
sum+=ValueBuff[count];
return ((uint32_t) ((float)sum / (N - BAN * 2)));
}
//=========================================================卡尔曼滤波================================================
typedef struct
{
float LastP; //前序协方差
float Now_P; //当前方差
float Out; //滤波结果
float Kg; //卡尔曼增益
float Q; //背景白噪声
float R; //器件方差
}Kalman_Filter;
Kalman_Filter MY_Kalman_Filter = {0.02,0,0,0,0.001,0.543};
float Kalman(Kalman_Filter * efk, float input)//一维卡尔曼
{
efk->Now_P = efk->LastP + efk->Q ;
efk->Kg = efk->Now_P / (efk->Now_P + efk->R );
efk->Out = efk->Out + efk->Kg * (input - efk->Out);
efk->LastP = (1 - efk->Kg) * efk->Now_P ;
return efk->Out;
}
//=====================================================低配版卡尔曼滤波
int KalmanFilter(int inData)
{
static float prevData = 0; //先前数值
static float p = 10, q = 0.001, r = 0.001, kGain = 0; // q控制误差 r控制响应速度
p = p + q;
kGain = p / ( p + r ); //计算卡尔曼增益
inData = prevData + ( kGain * ( inData - prevData ) ); //计算本次滤波估计值
p = ( 1 - kGain ) * p; //更新测量方差
prevData = inData;
return inData; //返回滤波值
}
//=========================================================算术平均值滤波================================================
N值较大时:信号平滑度较高,但灵敏度较低
N值较小时:信号平滑度较低,但灵敏度较高
N值的选取:一般流量,N=12;压力:N=4
优点:试用于对一般具有随机干扰的信号进行滤波。这种信号的特点是有一个平均值,信号在某一数值范围附近上下波动。
缺点:测量速度较慢或要求数据计算较快的实时控制不适用。
float averageFilter(int N)
{
float sum = 0;
int i;
for(i = 0; i < N; ++i)
{
sum += HAL_ADC_GetValue(&hadc1); //数据来源
}
return sum/N;
}
//=========================================================平滑均值滤波================================================
把连续取N个采样值看成一个队列,队列的长度固定为N。每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据(先进先出原则)。把队列中的N个数据进行算术平均运算,就可获得新的滤波结果。
N值的选取:流量,N=12;压力:N=4;液面,N=4~12;温度,N=1~4
优点:对周期性干扰有良好的抑制作用,平滑度高;试用于高频振荡的系统
缺点:灵敏度低;对偶然出现的脉冲性干扰的抑制作用较差,不适于脉冲干扰较严重的场合比较浪费RAM(改进方法,减去的不是队首的值,而是上一次得到的平均值)
#define AVGNMU 5
uint8_t avg_num=0;
float MoveAvg(float newadc)
{
static float sum;
if(avg_num<AVGNMU)
{
sum+=newadc;
avg_num++;
return sum/avg_num;
}
else
{
sum -= sum/AVGNMU;
sum+=newadc;
return sum/AVGNMU;
}
}
//加速度使用低通滤波(噪声在高频),角速度使用高通滤波(噪声在低频)
低通滤波器:通常选择较小的 α,使得滤波器对低频信号响应较好。
高通滤波器:通常选择较大的 α,使得滤波器对高频信号响应较好。
float LowPassFilter(volatile short newInput,volatile short *output);
float HighPassFilter(volatile short newInput,volatile short *output);
//低通
static float Lalpha = 0.2;
//高通
static float Halpha = 0.9;
//一阶低通滤波函数
float LowPassFilter(volatile short newInput,volatile short *output)
{
*output = (*output) + Lalpha * (newInput - (*output));
return *output;
}
//一阶高通滤波函数
float HighPassFilter(volatile short newInput,volatile short *output)
{
*output = (*output) + Halpha * (newInput - (*output));
return *output;
}