智能车制作

 找回密码
 注册

扫一扫,访问微社区

查看: 87612|回复: 29
打印 上一主题 下一主题

mpu6050的陀螺仪的角速度换成角度算法

    [复制链接]

5

主题

19

帖子

0

精华

知名人物

Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15

积分
44704
威望
37117
贡献
7517
兑换币
84
注册时间
2014-2-27
在线时间
35 小时
毕业学校
华中科技大学
跳转到指定楼层
1#
发表于 2014-3-18 16:14:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 huster_tjs 于 2014-3-18 14:09 编辑


下面是我的读取陀螺仪数据的程序
/************************陀螺仪计算Y轴的角速度***************/
float Read_Gry(void)
{
   static float angleG;
   int read_gyro_y;
   float Angle_gyro;
   int Gyro_y_offset=0x00;                             
                                       //角速度量程见配置   本处使用2000 deg/s。scal系数为16.4 LSB

        read_gyro_y= GetData(GYRO_YOUT_H)+Gyro_y_offset; //静止时角速度Y轴输出            //Gyro_y_offset计算方法gyro静止时候N多个数据的算术均值        
        Angle_gyro= -(float)read_gyro_y/16.4; //去除零点偏移,计算角速度值,负号为方向处理
        angleG+=Angle_gyro*0.05;                          //角速度积分
        return angleG;
}

下面是测得的图像
怎么回事这个样子呢?,,,程序有什么问题没有?
我不知道时间怎么确定,,那个0.05是估计的,可不可以用调试程序测出两次调用函数时的时间间隔?
黄色是加速度计的,蓝色是陀螺仪的。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

1

主题

8

帖子

0

精华

注册会员

Rank: 2

积分
45
威望
33
贡献
8
兑换币
7
注册时间
2014-5-3
在线时间
2 小时
推荐
发表于 2014-5-3 23:59:03 | 只看该作者
你主控是用什么的,我是第一次做小车用STC12C5A60S2芯片,就是不知道什么什么结合上位机得到数据在生成参数以便在程序中中使用。上位机也不知道什么连接。下面是程序
                                                                  
/***********************************************************************
// 两轮自平衡车最终版控制程序(6轴MPU6050+互补滤波+PWM电机)
// 单片机STC12C5A60S2
// 晶振:20M
// 日期:2012.11.26 - ?
***********************************************************************/

#include <REG52.H>       
#include <math.h>     
#include <stdio.h>   
#include <INTRINS.H>

typedef unsigned char  uchar;
typedef unsigned short ushort;
typedef unsigned int   uint;

//******功能模块头文件*******

#include "DELAY.H"                    //延时头文件
#include "STC_ISP.H"            //程序烧录头文件
#include "SET_SERIAL.H"                //串口头文件
#include "SET_PWM.H"                //PWM头文件
#include "MOTOR.H"                        //电机控制头文件
#include "MPU6050.H"                //MPU6050头文件



//******角度参数************

float Gyro_y;        //Y轴陀螺仪数据暂存
float Angle_gy;      //由角速度计算的倾斜角度
float Accel_x;             //X轴加速度值暂存
float Angle_ax;      //由加速度计算的倾斜角度
float Angle;         //小车最终倾斜角度
uchar value;                 //角度正负极性标记       

//******PWM参数*************

int   speed_mr;                 //右电机转速
int   speed_ml;                 //左电机转速
int   PWM_R;         //右轮PWM值计算
int   PWM_L;         //左轮PWM值计算
float PWM;           //综合PWM计算
float PWMI;                         //PWM积分值

//******电机参数*************

float speed_r_l;        //电机转速
float speed;        //电机转速滤波
float position;            //位移

//******蓝牙遥控参数*************
uchar remote_char;
char  turn_need;
char  speed_need;

//*********************************************************
//定时器100Hz数据更新中断
//*********************************************************

void Init_Timer1(void)        //10毫秒@20MHz,100Hz刷新频率
{
        AUXR &= 0xBF;                //定时器时钟12T模式
        TMOD &= 0x0F;                //设置定时器模式
        TMOD |= 0x10;                //设置定时器模式
        TL1 = 0xE5;                    //设置定时初值
        TH1 = 0xBE;                    //设置定时初值
        TF1 = 0;                    //清除TF1标志
        TR1 = 1;                    //定时器1开始计时
}



//*********************************************************
//中断控制初始化
//*********************************************************

void Init_Interr(void)         
{
        EA = 1;     //开总中断
    EX0 = 1;    //开外部中断INT0
    EX1 = 1;    //开外部中断INT1
    IT0 = 1;    //下降沿触发
    IT1 = 1;    //下降沿触发
        ET1 = 1;    //开定时器1中断
}



//******卡尔曼参数************
               
float code Q_angle=0.001;  
float code Q_gyro=0.003;
float code R_angle=0.5;
float code dt=0.01;                          //dt为kalman滤波器采样时间;
char  code C_0 = 1;
float xdata Q_bias, Angle_err;
float xdata PCt_0, PCt_1, E;
float xdata K_0, K_1, t_0, t_1;
float xdata Pdot[4] ={0,0,0,0};
float xdata PP[2][2] = { { 1, 0 },{ 0, 1 } };

//*********************************************************
// 卡尔曼滤波
//*********************************************************               
//在程序中利用Angle+=(Gyro - Q_bias) * dt计算出陀螺仪积分出的角度,其中Q_bias是陀螺仪偏差。
//此时利用陀螺仪积分求出的Angle相当于系统的估计值,得到系统的观测方程;而加速度计检测的角度Accel相当于系统中的测量值,得到系统状态方程。
//程序中Q_angle和Q_gyro分别表示系统对加速度计及陀螺仪的信任度。根据Pdot = A*P + P*A' + Q_angle计算出先验估计协方差的微分,用于将当前估计值进行线性化处理。其中A为雅克比矩阵。  
//随后计算系统预测角度的协方差矩阵P。计算估计值Accel与预测值Angle间的误差Angle_err。
//计算卡尔曼增益K_0,K_1,K_0用于最优估计值,K_1用于计算最优估计值的偏差并更新协方差矩阵P。
//通过卡尔曼增益计算出最优估计值Angle及预测值偏差Q_bias,此时得到最优角度值Angle及角速度值。


//Kalman滤波,20MHz的处理时间约0.77ms;                       

void Kalman_Filter(float Accel,float Gyro)                  
{
        Angle+=(Gyro - Q_bias) * dt; //先验估计

       
        Pdot[0]=Q_angle - PP[0][1] - PP[1][0]; // Pk-先验估计误差协方差的微分

        Pdot[1]=- PP[1][1];
        Pdot[2]=- PP[1][1];
        Pdot[3]=Q_gyro;
       
        PP[0][0] += Pdot[0] * dt;   // Pk-先验估计误差协方差微分的积分
        PP[0][1] += Pdot[1] * dt;   // =先验估计误差协方差
        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];
       
        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 * PP[0][1];

        PP[0][0] -= K_0 * t_0;                 //后验估计误差协方差
        PP[0][1] -= K_0 * t_1;
        PP[1][0] -= K_1 * t_0;
        PP[1][1] -= K_1 * t_1;
               
        Angle        += K_0 * Angle_err;         //后验估计
        Q_bias        += K_1 * Angle_err;         //后验估计
        Gyro_y   = Gyro - Q_bias;         //输出值(后验估计)的微分=角速度

}



//*********************************************************
// 倾角计算(卡尔曼融合)
//*********************************************************

void Angle_Calcu(void)         
{
        //------加速度--------------------------

        //范围为2g时,换算关系:16384 LSB/g
        //角度较小时,x=sinx得到角度(弧度), deg = rad*180/3.14
        //因为x>=sinx,故乘以1.3适当放大

        Accel_x  = GetData(ACCEL_XOUT_H);          //读取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(GYRO_YOUT_H);              //静止时角速度Y轴输出为-30左右
        Gyro_y = -(Gyro_y + 30)/16.4;         //去除零点偏移,计算角速度值,负号为方向处理
        //Angle_gy = Angle_gy + Gyro_y*0.01;  //角速度积分得到倾斜角度.       

       
        //-------卡尔曼滤波融合-----------------------

        Kalman_Filter(Angle_ax,Gyro_y);       //卡尔曼滤波计算倾角


        /*//-------互补滤波-----------------------

        //补偿原理是取当前倾角和加速度获得倾角差值进行放大,然后与
    //陀螺仪角速度叠加后再积分,从而使倾角最跟踪为加速度获得的角度
        //0.5为放大倍数,可调节补偿度;0.01为系统周期10ms       
               
        Angle = Angle + (((Angle_ax-Angle)*0.5 + Gyro_y)*0.01);*/
                                                                                                                          
}  



//*********************************************************
//电机转速和位移值计算
//*********************************************************

void Psn_Calcu(void)         
{
       
        speed_r_l =(speed_mr + speed_ml)*0.5;
        speed *= 0.7;                                  //车轮速度滤波
        speed += speed_r_l*0.3;       
        position += speed;                          //积分得到位移
        position += speed_need;
        if(position<-6000) position = -6000;
        if(position> 6000) position =  6000;

         
}


static float code Kp  = 7.0;       //PID参数
static float code Kd  =0.22;            //PID参数
static float code Kpn = 0.004;      //PID参数
static float code Ksp =0.1;            //PID参数

//*********************************************************
//电机PWM值计算
//*********************************************************

void PWM_Calcu(void)         
{
   
        if(Angle<-40||Angle>40)               //角度过大,关闭电机
        {  
          CCAP0H = 0;
      CCAP1H = 0;
          return;
        }
        PWM  = Kp*Angle + Kd*Gyro_y;          //PID:角速度和角度
        PWM += Kpn*position + Ksp*speed;      //PID:速度和位置
        PWM_R = PWM + turn_need;
        PWM_L = PWM - turn_need;
        PWM_Motor(PWM_L,PWM_R);
         
}




//*********************************************************
//手机蓝牙遥控
//*********************************************************

void Bluetooth_Remote(void)         
{

        remote_char = receive_char();                                   //接收蓝牙串口数据

        if(remote_char ==0x02) speed_need = -80;           //前进
        else if(remote_char ==0x01) speed_need = 80;   //后退
             else speed_need = 0;                                           //不动

    if(remote_char ==0x03) turn_need = 15;                   //左转
        else if(remote_char ==0x04) turn_need = -15;   //右转
             else turn_need = 0;                                           //不转
         
}


/*=================================================================================*/

//*********************************************************
//main
//*********************************************************
void main()
{

        delaynms(500);           //上电延时
        Init_PWM();               //PWM初始化
    Init_Timer0();     //初始化定时器0,作为PWM时钟源
        Init_Timer1();     //初始化定时器1
        Init_Interr();     //中断初始化
        Init_Motor();           //电机控制初始化
        Init_BRT();                   //串口初始化(独立波特率)
        InitMPU6050();     //初始化MPU6050
        delaynms(500);           

        while(1)
        {
          
         Bluetooth_Remote();

        }
}


/*=================================================================================*/

//********timer1中断***********************

void Timer1_Update(void) interrupt 3
{
  
   TL1 = 0xE5;                    //设置定时初值10MS
   TH1 = 0xBE;
   
   //STC_ISP();                    //程序下载
   Angle_Calcu();                  //倾角计算
   Psn_Calcu();                    //电机位移计算
   PWM_Calcu();                    //计算PWM值
   
   speed_mr = speed_ml = 0;         

}


//********右电机中断***********************

void INT_L(void) interrupt 0
{

   if(SPDL == 1)  { speed_ml++; }                 //左电机前进
   else                      { speed_ml--; }                 //左电机后退
   LED = ~LED;

}


//********左电机中断***********************

void INT_R(void) interrupt 2
{

   if(SPDR == 1)  { speed_mr++; }                 //右电机前进
   else                      { speed_mr--; }                 //右电机后退
   LED = ~LED;

}



回复 支持 1 反对 0

使用道具 举报

93

主题

1166

帖子

0

精华

跨届大侠

Rank: 10Rank: 10Rank: 10

积分
7879

论坛元老奖章在线王奖章活跃会员奖章优秀会员奖章论坛骨干奖章

QQ
威望
4108
贡献
2161
兑换币
2705
注册时间
2013-8-14
在线时间
805 小时
2#
发表于 2014-3-18 17:03:26 | 只看该作者
节俭一下 看样子很好。
回复 支持 反对

使用道具 举报

5

主题

19

帖子

0

精华

知名人物

Rank: 15Rank: 15Rank: 15Rank: 15Rank: 15

积分
44704
威望
37117
贡献
7517
兑换币
84
注册时间
2014-2-27
在线时间
35 小时
毕业学校
华中科技大学
3#
 楼主| 发表于 2014-3-18 18:58:56 | 只看该作者
头上两只角 发表于 2014-3-18 17:03
节俭一下 看样子很好。

节俭一下是什么意思。我这个应该怎么把陀螺仪的数据调下来?
回复 支持 反对

使用道具 举报

1

主题

8

帖子

0

精华

注册会员

Rank: 2

积分
45
威望
33
贡献
8
兑换币
7
注册时间
2014-5-3
在线时间
2 小时
5#
发表于 2014-5-4 00:03:21 | 只看该作者
回复 支持 反对

使用道具 举报

1

主题

8

帖子

0

精华

注册会员

Rank: 2

积分
45
威望
33
贡献
8
兑换币
7
注册时间
2014-5-3
在线时间
2 小时
6#
发表于 2014-5-4 00:04:37 | 只看该作者
陀螺仪图片

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

注册会员

Rank: 2

积分
30
威望
18
贡献
10
兑换币
9
注册时间
2014-5-15
在线时间
1 小时
毕业学校
哈理工
7#
发表于 2014-5-15 21:10:32 | 只看该作者
张ZJS 发表于 2014-5-4 00:04
陀螺仪图片

你好  我想问一下测MPU6050的Y轴角速度零点偏移怎么测得
回复 支持 反对

使用道具 举报

2

主题

27

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1341
威望
643
贡献
412
兑换币
292
注册时间
2012-7-14
在线时间
143 小时
8#
发表于 2014-8-26 16:16:26 | 只看该作者
楼主问题解决没有?这个要继续变化的,另外时间久了,积分误差会变大
回复 支持 反对

使用道具 举报

2

主题

8

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1253
威望
458
贡献
241
兑换币
230
注册时间
2012-7-24
在线时间
277 小时
9#
发表于 2014-8-29 17:30:09 | 只看该作者
我也想问一下角速度零点偏移怎么测得
回复 支持 反对

使用道具 举报

1

主题

48

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
372
威望
199
贡献
107
兑换币
125
注册时间
2013-11-25
在线时间
33 小时
毕业学校
高琦
10#
发表于 2014-12-19 21:17:41 | 只看该作者
张ZJS 发表于 2014-5-3 23:59
你主控是用什么的,我是第一次做小车用STC12C5A60S2芯片,就是不知道什么什么结合上位机得到数据在生成参数 ...

Kalman_Filter(Angle_ax,Gyro_y);       //卡尔曼滤波计算倾角
这个计算的那个轴的角度呢?然后你MPU6050怎么安装的?
回复 支持 反对

使用道具 举报

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

本版积分规则

关于我们|联系我们|小黑屋|亿加合和智能车制作 ( 黑ICP备2022002344号

GMT+8, 2024-5-6 11:17 , Processed in 0.185807 second(s), 32 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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