我的MPU6050用了互补滤波法得到x, y,z轴的角度但是很不准,平放模块时不为x轴角度不为0,程序如下 //********************************************************* // 倾角计算(卡尔曼融合) //********************************************************* void Angle_Calcu(unsigned char A,unsigned char G) { //------加速度-------------------------- //范围为2g时,换算关系:16384 LSB/g //角度较小时,x=sinx得到角度(弧度), deg = rad*180/3.14 //因为x>=sinx,故乘以1.3适当放大 Accel_x = GetData(A); //读取X轴加速度 Angle_ax = (Accel_x - 1100) /16384; //去除零点偏移,计算得到角度(弧度) Angle_ax = Angle_ax*1.2*180/3.14; //弧度转换为度, //-------角速度------------------------- //范围为2000deg/s时,换算关系:16.4 LSB/(deg/s) Gyro_y = GetData(G); //静止时角速度Y轴输出为-30左右 Gyro_y = -(Gyro_y + 30)/16.4; //去除零点偏移,计算角速度值,负号为方向处理 Angle_gy = Angle_gy + Gyro_y*0.01; //角速度积分得到倾斜角度. if(A==ACCEL_XOUT_H) ComplementFilterX(Angle_ax,Gyro_y); if(A==ACCEL_YOUT_H) ComplementFilterY(Angle_ax,Gyro_y); if(A==ACCEL_ZOUT_H) ComplementFilterZ(Angle_ax,Gyro_y); } /*//-------卡尔曼滤波融合----------------------- Kalman_Filter(Angle_ax,Gyro_y); //卡尔曼滤波计算倾角 //-------互补滤波----------------------- //补偿原理是取当前倾角和加速度获得倾角差值进行放大,然后与 //陀螺仪角速度叠加后再积分,从而使倾角最跟踪为加速度获得的角度 //0.5为放大倍数,可调节补偿度;0.01为系统周期10ms Angle = Angle + (((Angle_ax-Angle)*0.5 + Gyro_y)*0.01); */ /** * 互补滤波参数 */ float tau = 0.065, p = 0.0; // 用于计算比例 float dtc = 0.01; // 抽样时间10ms static float bias_gx = 0.0,bias_gy = 0.0,bias_gz = 0.0,gy_temp; // 零点漂移误差消除 static float fix_angle,fiy_angle,fiz_angle; /** * 互补滤波算法 * angle 为重力感应获得的角度值 * gy_speed 为角速度 */ float ComplementFilterX(float angle, float gy_sped) { bias_gx = bias_gx*0.998+gy_sped*0.002; // 消除零点误差 gy_temp = gy_sped - bias_gx; // 减去零点误差 p = tau/(tau+dtc); // 对角速度gy_temp进行高通滤波,对重力感应得到的角度angle进行低通滤波 fix_angle = p*(fix_angle+gy_temp*dtc)+(1-p)*angle; return fix_angle; } float ComplementFilterY(float angle, float gy_sped) { bias_gz = bias_gz*0.998+gy_sped*0.002; // 消除零点误差 gy_temp = gy_sped - bias_gz; // 减去零点误差 p = tau/(tau+dtc); // 对角速度gy_temp进行高通滤波,对重力感应得到的角度angle进行低通滤波 fiy_angle = p*(fiy_angle+gy_temp*dtc)+(1-p)*angle; return fiy_angle; } float ComplementFilterZ(float angle, float gy_sped) { bias_gx = bias_gx*0.998+gy_sped*0.002; // 消除零点误差 gy_temp = gy_sped - bias_gx; // 减去零点误差 p = tau/(tau+dtc); // 对角速度gy_temp进行高通滤波,对重力感应得到的角度angle进行低通滤波 fiz_angle = p*(fiz_angle+gy_temp*dtc)+(1-p)*angle; return fiz_angle; } int main(void) { Stm32_Clock_Init(9);//系统时钟设置 /*IIC接口初始化*/ I2C_MPU6050_Init(); /*陀螺仪传感器初始化*/ InitMPU6050(); //hw_tick_start(); // 定时器周期性中断,用于提供系统脉搏 while(1) { Angle_Calcu(ACCEL_XOUT_H,GYRO_YOUT_H); //Display10BitData(fix_angle); Angle_Calcu(ACCEL_YOUT_H,GYRO_ZOUT_H); //Display10BitData(fiy_angle); Angle_Calcu(ACCEL_ZOUT_H,GYRO_XOUT_H); //Display10BitData(fiz_angle); } } |
|