OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3999|回复: 5

STM32F103C8T6+MPU6050+kalman滤波

[复制链接]

3

主题

6

帖子

0

精华

初级会员

Rank: 2

积分
65
金钱
65
注册时间
2016-12-12
在线时间
12 小时
发表于 2016-12-12 17:22:40 | 显示全部楼层 |阅读模式
为了其他人不在走弯路,第一次发帖分享一下自己的经验,不喜勿喷,本人菜鸟一枚!
原子哥的iic,一开始who_am_i读数和其他数据都是0,这个可以确定iic不通,搞了两天才发现是自己马虎直接复制别人错误代码造成的

模拟iic用的是sda-PB6,scl-PB7,原子哥的本来是PB11 PB12,我改了之后用了网友的这段代码:
#define SDA_IN()  {GPIOB->CRH&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
#define SDA_OUT() {GPIOB->CRH&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}

更改后:
#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}

终于见到久违的who_am_i:0x68
然后遇到的第二个问题是kalman滤波前的角度计算,网上的程序很多都很乱,小白看不懂
东平西凑后确定了这么一段求pitch和roll的代码:
[mw_shl_code=c,true]//角度计算
void Angle_Calcu(void)         
{
        //不自测,+-2000°/s
        //范围为2g时,换算关系:16384 LSB/g
        //deg = rad*180/3.14

        Accel_x = GetData(ACCEL_XOUT_H); //x轴加速度值暂存
        Accel_y = GetData(ACCEL_YOUT_H); //y轴加速度值暂存
        Accel_z = GetData(ACCEL_ZOUT_H); //z轴加速度值暂存
        Gyro_x  = GetData(GYRO_XOUT_H);  //x轴陀螺仪值暂存
        Gyro_y  = GetData(GYRO_YOUT_H);  //y轴陀螺仪值暂存
        Gyro_z  = GetData(GYRO_ZOUT_H);  //z轴陀螺仪值暂存
        Temperature = GetData(TEMP_OUT_H); //x轴加速度值暂存
        Temperature =(((double) Temperature )/340+36.53);  // 读取计算出温度
       
//        printf(" AX=%f   AY=%f   AZ=%f  \n",Ax,Ay,Az);
       
        Ax = (Accel_x-300)/16384.0;
        Ay = (Accel_y-500)/16384.0;
        Az = (Accel_z-366)/16384.0;
       
        Gx=(Gyro_x+55)/ 16.4;
        Gy=(Gyro_y-24)/ 16.4;
        Gz=(Gyro_z-6)/ 16.4;
       
//        printf(" AX=%f   AY=%f   AZ=%f  \n",Ax,Ay,Az);
//        printf(" GX=%f   GY=%f   GZ=%f  \n",Gx,Gy,Gz);
//        printf("temp-%f",Temperature);
       
        //用加速度计算三个轴和水平面坐标系之间的夹角
        //加速度计读出来的原始数据为 Ax Ay Az,假设绕Y为俯仰pitch 绕X为横滚roll。
  //俯仰角= —atan2(AX, AZ )  横滚角=atan2(AY, AZ)
        Angle_x_temp = (atan2(Ax,Az)) * 180 / Pi;
        Angle_y_temp = (atan2(Ay,Az)) * 180 / Pi;
       
        Pitch=Kalman_Filter(Angle_x_temp, Gy);       
        Roll=Kalman_Filter(Angle_y_temp, Gx);
       
        printf(" P=%f   R=%f  \n",Pitch,Roll);
//        printf(" AX=%f   AY=%f   AZ=%f  \n",Ax,Ay,Az);
//        printf(" GX=%f   GY=%f   GZ=%f  \n",Gx,Gy,Gz);

} [/mw_shl_code]
前两个问题解决了,又冒出来一个,串口打印的pitch和roll居然是一个数值,变化相同,但数值没问题

未滤波的角度和角速度都正常
后来确定了是kalman的问题,仔细想想,终于恍然大悟,kalman是网上复制的他的参数是全局变量,被重复使用了,串口打印的结果自然也就是来自同一个变量
把全局变量都放进函数内,变成局部变量,生命周期变短,用一次销毁一次,完美解决
终于见到了久违的pitch和roll
下面是卡拉曼滤波:
[mw_shl_code=c,true]float Kalman_Filter(float angle_m, float gyro_m)//angleAx 和 gyroGy
{
       
       
                                       
                                //卡尔曼滤波参数与函数
                                float dt=0.001;//注意:dt的取值为kalman滤波器采样时间
                                float angle, angle_dot;//角度和角速度
                                float P[2][2] = {{ 1, 0 },
                                                                                                 { 0, 1 }};
                                float Pdot[4] ={ 0,0,0,0};
                                float Q_angle=0.001, Q_gyro=0.005; //角度数据置信度,角速度数据置信度
                                float R_angle=0.5 ,C_0 = 1;
                                float q_bias, angle_err, PCt_0, PCt_1, E, K_0, K_1, t_0, t_1;

       
        angle+=(gyro_m-q_bias) * dt;
        angle_err = angle_m - angle;
        Pdot[0]=Q_angle - P[0][1] - P[1][0];
        Pdot[1]=- P[1][1];
        Pdot[2]=- P[1][1];
        Pdot[3]=Q_gyro;
        P[0][0] += Pdot[0] * dt;
        P[0][1] += Pdot[1] * dt;
        P[1][0] += Pdot[2] * dt;
        P[1][1] += Pdot[3] * dt;
        PCt_0 = C_0 * P[0][0];
        PCt_1 = C_0 * P[1][0];
        E = R_angle + C_0 * PCt_0;
        K_0 = PCt_0 / E;
        K_1 = PCt_1 / E;
        t_0 = PCt_0;
        t_1 = C_0 * P[0][1];
        P[0][0] -= K_0 * t_0;
        P[0][1] -= K_0 * t_1;
        P[1][0] -= K_1 * t_0;
        P[1][1] -= K_1 * t_1;
        angle += K_0 * angle_err; //最优角度
        q_bias += K_1 * angle_err;
        angle_dot = gyro_m-q_bias;//最优角速度

        return angle;
}
[/mw_shl_code]

现在准备把姿态角显示到4.06匿名上位机看一下kalman滤波效果和3d姿态
但是看了上位机上下载下来的下位机通信协议代码有点头疼,有谁写了简单的给共享一下,先在这里谢谢了!

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

5

主题

19

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2016-7-29
在线时间
10 小时
发表于 2016-12-13 23:44:27 | 显示全部楼层
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
4
金钱
4
注册时间
2017-7-25
在线时间
1 小时
发表于 2017-7-25 08:40:54 | 显示全部楼层
楼主,我用F4试了你的,有点抖得再细细调一调
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
4
金钱
4
注册时间
2017-7-25
在线时间
1 小时
发表于 2017-7-25 16:17:49 | 显示全部楼层
楼主,有错,不应该每次都重新定义
回复 支持 反对

使用道具 举报

10

主题

42

帖子

0

精华

初级会员

Rank: 2

积分
93
金钱
93
注册时间
2017-8-25
在线时间
13 小时
发表于 2017-9-28 00:17:20 | 显示全部楼层
楼主可否把整个工程发一下
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2018-5-8
在线时间
2 小时
发表于 2018-5-11 23:24:51 | 显示全部楼层
kalman滤波协方差不是每次都重新定义吧,你好好看看
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-14 10:46

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表