1 ADC采样模型
假设ADC采样的值已经为稳定状态,设
时刻ADC采样值为
,则
时刻ADC采样值为
,假设
时刻的采样值为
,则有:
2 卡尔曼滤波算法
我们知道卡尔曼滤波算法的公式如下:
由于相关系数都为1,于是可以得出如下公式:
3 C语言代码
用C实现的代码如下:
unsigned long kalman_filter(unsigned long ADC_Value)
{
float x_k1_k1,x_k_k1;
static float ADC_OLD_Value;
float Z_k;
static float P_k1_k1;
static float Q = 0.0001;
static float R = 0.005;
static float Kg = 0;
static float P_k_k1 = 1;
float kalman_adc;
static float kalman_adc_old=0;
Z_k = ADC_Value;
x_k1_k1 = kalman_adc_old;
x_k_k1 = x_k1_k1;
P_k_k1 = P_k1_k1 + Q;
Kg = P_k_k1/(P_k_k1 + R);
kalman_adc = x_k_k1 + Kg * (Z_k - kalman_adc_old);
P_k1_k1 = (1 - Kg)*P_k_k1;
P_k_k1 = P_k1_k1;
ADC_OLD_Value = ADC_Value;
kalman_adc_old = kalman_adc;
return kalman_adc;
}
4 如何优化
用以上的代码实现的滤波算法,通常要么滞后严重,要么滤波效果不明显,在这里给出两种优化方案。
方案一:在采样值与优化值相差大于某值时采用一阶滞后滤波算法,小于该值时采用卡尔曼滤波算法;
方案二:比较一段时间内的ADC采样值与优化值差值,若一直处于某个范围如(6~30),采用一阶滞后滤波算法,反之采用卡尔曼滤波算法。
以下代码是方案一的优化代码,其优化效果可见我另一篇博文https://blog.csdn.net/moge19/article/details/80915432:
unsigned long kalman_filter(unsigned long ADC_Value)
{
float x_k1_k1,x_k_k1;
static float ADC_OLD_Value;
float Z_k;
static float P_k1_k1;
static float Q = 0.0001;
static float R = 5;
static float Kg = 0;
static float P_k_k1 = 1;
float kalman_adc;
static float kalman_adc_old=0;
Z_k = ADC_Value;
if (abs(kalman_adc_old-ADC_Value)>=10)
{
x_k1_k1= ADC_Value*0.382 + kalman_adc_old*0.618;
}else
{
x_k1_k1 = kalman_adc_old;
}
x_k_k1 = x_k1_k1;
P_k_k1 = P_k1_k1 + Q;
Kg = P_k_k1/(P_k_k1 + R);
kalman_adc = x_k_k1 + Kg * (Z_k - kalman_adc_old);
P_k1_k1 = (1 - Kg)*P_k_k1;
P_k_k1 = P_k1_k1;
ADC_OLD_Value = ADC_Value;
kalman_adc_old = kalman_adc;
return get_int_num(kalman_adc);
}