非常感谢原作者,我在这个的基础上转换成纯整形运算。STM32F103 12位ADC先放大1000倍再运算,理论上可以保留小数点后三位的结果。
效果非常不错,运算速度也快,72M时钟 1-2uS左右(根据MDK周期数)。]uint32_t KalmanFilter(int32_t ResrcData)
{
/*-------------------------------------------------------------------------------------------------------------*/
/*
Q:过程噪声,Q增大,动态响应变快,收敛稳定性变坏
R:测量噪声,R增大,动态响应变慢,收敛稳定性变好
*/
/*-------------------------------------------------------------------------------------------------------------*/
static int32_t R = (int32_t)(128*1024);
static int32_t Q = (int32_t)4;
static uint32_t Counter1 = 0;
static uint32_t Counter2 = 0;
static int32_t x_last = 0;
static int32_t p_last; // 应赋初始估计值
int32_t x_mid;
int32_t x_now;
int32_t p_mid ;
int32_t p_now;
ResrcData *= 1024;
x_now = ResrcData - x_last;
if(x_now
{
x_now *= -1; // 取绝对值
}
if(x_now >= 32*1024) // 如果测量值连续比估计值大或小 相信测量值,加速迭代
{
Counter1++;
Counter2 = 0;
if(Counter1 > 10)
{
R = 512;;
Q = 128;
}
}
else // 数据比较稳定,加强滤波
{
Counter1 = 0;
Counter2++;
if(Counter2 > 10)
{
R = (int32_t)(128*1024);
Q = (int32_t)4;
}
}
x_mid = x_last; // x_last=x(k-1|k-1),x_mid=x(k|k-1)
p_mid = p_last + Q; // p_mid=p(k|k-1),p_last=p(k-1|k-1),Q=噪声
// kg = p_mid/(p_mid + R); //kg为kalman filter,R为噪声
// x_now = x_mid+kg*(ResrcData - x_mid);// 估计出的最优值
x_now = x_mid + (p_mid*(ResrcData - x_mid))/(p_mid + R);
// p_now = (1 - kg)*p_mid; // 最优值对应的covariance
p_now = p_mid - p_mid*p_mid/(p_mid + R); // 最优值对应的covariance
p_last = p_now; // 更新covariance值
x_last = x_now; // 更新系统状态值
x_now /= 1024;
if((x_now > 4096)||( x_now
{
x_last = ResrcData;
p_now = ResrcData;
x_now = ResrcData/1024;
}
return (u32)x_now;
}