使用MPU6050卡尔曼滤波处理效果还好
新手,学习来了
问题:1,我快速改变板子倾角时Angle的变化正常吗?7 s3 I3 n# f! b' T: }
2,Angle正常变化的时候是应该与Angle_ax的值相近吗?7 e3 P/ Y: o4 n0 a6 B
现在情况就是,就算我是在减小倾角,只要我快速地改变,它显示的倾角都会先增大再减小,而如果我慢速改变的话,倾角就会缓慢减小而不会出现中间的角度增大5 z4 C0 Y$ t. P: R6 @$ I" w: y
/ X0 d- c- q: B, \+ K
$ s8 K8 o3 n7 V. p$ |( {
*************读取数据********************4 D/ G+ { n ?: N8 J/ k1 y
//定义MPU6050内部地址
#define SMPLRT_DIV 0x19 //陀螺仪采样率 典型值 0X07 125Hz* r# F& C6 [9 ~- C0 v
#define CONFIG 0x1A //低通滤波频率 典型值 0x00
#define GYRO_CONFIG 0x1B //陀螺仪自检及测量范围 典型值 0x18 不自检 2000deg/s$ c! |( s7 O5 D+ K! i+ |9 O6 n* R
#define ACCEL_CONFIG 0x1C //加速度计自检及测量范围及高通滤波频率 典型值 0x01 不自检 2G 5Hz
#define INT_PIN_CFG 0x37" Y3 g) ~* h9 ~
#define INT_ENABLE 0x38
#define INT_STATUS 0x3A //只读
#define ACCEL_XOUT_H 0x3B
#define ACCEL_XOUT_L 0x3C% q6 O( w' ~3 I: T
#define ACCEL_YOUT_H 0x3D# T/ ~" C# ?5 P+ c. C
#define ACCEL_YOUT_L 0x3E' l/ R& e; V! W$ Z- h' r) ~
#define ACCEL_ZOUT_H 0x3F( }3 ^% B- t5 c" c" ^# A( l
#define ACCEL_ZOUT_L 0x40& M6 f# h7 ?" u1 ^' X
#define TEMP_OUT_H 0x41
#define TEMP_OUT_L 0x42/ J( a/ {8 l/ K
#define GYRO_XOUT_H 0x43
#define GYRO_XOUT_L 0x44 ! E( R6 l$ X3 D4 D0 Q
#define GYRO_YOUT_H 0x45
#define GYRO_YOUT_L 0x46
#define GYRO_ZOUT_H 0x47% Q1 q1 K. N" b/ I5 ~& q' R
#define GYRO_ZOUT_L 0x48: T5 x0 F, B; t% b! z
//读取寄存器原生数据 X/ i" V; t2 Z, y" @ e
, D; B& S. x; W, @
MPU6050_Raw_Data.Accel_X = (buf[0]<<8 | buf[1]);. H/ p! Z. f0 z1 c4 r
MPU6050_Raw_Data.Accel_Y = (buf[2]<<8 | buf[3]);
MPU6050_Raw_Data.Accel_Z = (buf[4]<<8 | buf[5]); $ s) ~6 e; h- }2 I- u) a3 \7 a
MPU6050_Raw_Data.Temp = (buf[6]<<8 | buf[7]); ( z& g- ?- V! `3 {
MPU6050_Raw_Data.Gyro_X = (buf[8]<<8 | buf[9]);
MPU6050_Raw_Data.Gyro_Y = (buf[10]<<8 | buf[11]);
MPU6050_Raw_Data.Gyro_Z = (buf[12]<<8 | buf[13]);% {. I j! e( a3 ]2 V4 J l
+ g' i/ o! U2 a) d* Q) y1 d$ }) R
, B r/ l4 T8 K, {* ^8 u# f% n
//将原生数据转换为实际值,计算公式跟寄存器的配置有关% `5 G! G5 @; Q! b, C/ ^/ n
MPU6050_Real_Data.Accel_X = -(float)(MPU6050_Raw_Data.Accel_X)/8192.0; 0 Q/ e9 ]8 P+ Z% t5 [
MPU6050_Real_Data.Accel_Y = -(float)(MPU6050_Raw_Data.Accel_Y)/8192.0;
MPU6050_Real_Data.Accel_Z = (float)(MPU6050_Raw_Data.Accel_Z)/8192.0; 7 [; R# X$ H+ z; ]! E9 ?
MPU6050_Real_Data.Gyro_X=-(float)(MPU6050_Raw_Data.Gyro_X - gyroADC_X_offset)/65.5;
MPU6050_Real_Data.Gyro_Y=-(float)(MPU6050_Raw_Data.Gyro_Y - gyroADC_Y_offset)/65.5;
MPU6050_Real_Data.Gyro_Z=(float)(MPU6050_Raw_Data.Gyro_Z - gyroADC_Z_offset)/65.5;
}
* Z! z" Y' v4 N; d; U, C& U
* o& ^3 j+ S. [
//******卡尔曼参数************, j# N( r7 e1 O4 y& `
const float Q_angle=0.001;
const float Q_gyro=0.003;) g2 I. c; I6 `
const float R_angle=0.5;
const float dt=0.01; //dt为kalman滤波器采样时间;2 v1 w K7 j* ~/ w. r4 M
const char C_0 = 1; U) G# R& k3 T: b/ L; ]
float Q_bias, Angle_err;% f/ |1 l; ]1 w" F4 K, g" f. C
float PCt_0, PCt_1, E;
float K_0, K_1, t_0, t_1;: _$ P+ ?# M, f% Q, v; m
float Pdot[4] ={0,0,0,0};6 u/ R/ \& X: {
float PP[2][2] = { { 1, 0 },{ 0, 1 } };
" v) P4 u) b4 O- `& V: B; v
/*****************卡尔曼滤波**************************************************/! G' T2 `* D' g* O( i4 N0 x
void Kalman_Filter(float Accel,float Gyro)
{
Angle+=(Gyro - Q_bias) * dt; //先验估计
/ x( x, \* ~ E! ~$ k3 K6 h
Pdot[0]=Q_angle - PP[0][1] - PP[1][0]; // Pk-先验估计误差协方差的微分
Pdot[1]= -PP[1][1]; h; A9 B0 E1 W: D: {
Pdot[2]= -PP[1][1];
Pdot[3]=Q_gyro;
PP[0][0] += Pdot[0] * dt; // Pk-先验估计误差协方差微分的积分$ d3 y) x" v2 `7 N1 E
PP[0][1] += Pdot[1] * dt; // =先验估计误差协方差0 ~, R4 }: N, o
PP[1][0] += Pdot[2] * dt;
PP[1][1] += Pdot[3] * dt;
Angle_err = Accel - Angle; //zk-先验估计
PCt_0 = C_0 * PP[0][0];
PCt_1 = C_0 * PP[1][0];
- {8 @+ Q/ D* v o! {3 u- a O: N
E = R_angle + C_0 * PCt_0; D* Y I4 A# j# B3 U
K_0 = PCt_0 / E;
K_1 = PCt_1 / E;* S# H$ H7 m+ x7 v+ h C8 X
t_0 = PCt_0;
t_1 = C_0 * PP[0][1];
PP[0][0] -= K_0 * t_0; //后验估计误差协方差
PP[0][1] -= K_0 * t_1;
PP[1][0] -= K_1 * t_0;8 d1 T& }/ i$ W3 {* Q9 f
PP[1][1] -= K_1 * t_1;
Angle += K_0 * Angle_err; //后验估计4 }4 j+ Z; @' l: E8 V
Q_bias += K_1 * Angle_err; //后验估计+ J# u: s" }5 G' L
Gyro_y = Gyro - Q_bias; //输出值(后验估计)的微分=角速度
}
% E. b& _# |3 _) [4 b2 a0 Q2 s
******************倾角计算*****************' m: `* X6 X' D
void Angle_Calculate(void)# b' @1 h" J2 P% e- x. I
{
. w$ y. ^5 {9 f0 L
/****************************加速度****************************************/
Accel_x = MPU6050_Real_Data.Accel_X; //读取X轴加速度
Angle_ax = Accel_x*1.2*180/3.14; //弧度转换为度
# I* L* H) X6 r& ~
/****************************角速度****************************************/
Gyro_y = MPU6050_Real_Data.Gyro_Y; , B- `( o) k: r3 T" O5 T# w T
时间dt,所以此处不用积分9 O( Q7 X: p6 I/ Q
/***************************卡尔曼融合*************************************/4 K' G* Z z2 W3 Y% Q
Kalman_Filter(Angle_ax,Gyro_y); //卡尔曼滤波计算倾角0 s, o& W- h1 m2 u3 U
* y5 z# s7 h% x3 s& z- u4 A