|
|
本帖最后由 ShadowWalker 于 2013-8-13 13:53 编辑
- #include "Wire.h"
- #include "I2Cdev.h"
- #include "MPU6050.h"
- MPU6050 accelgyro;
- const float Ac_xs = 16384.0; //重力加速度系数
- const float Pa_xs = 131.0; //角速度系数
- const float Ra=180/PI ; //弧度转角度系数
- double G; //重力加速度
- unsigned long T_Now=0,T_Last=0; //系统当前时间
- int Ac[3]; //读取加速度xyz
- int Pa[3]; //读取角速度xyz
- float P[3]; //真实角速度
- float C_Pa[3]; //角速度漂移xyz
- float C_Ac[3]; //加速度计漂移
- float Pa_X_Now,Pa_X_Last,Pa_Y_Now,Pa_Y_Last; //积分角速度
- float Rg[3]; //过程单位矢量
- float A[3]; //真实惯性合力分量 |A|=1
- float A_X,A_Y; //x,y与Z轴夹角
- float Gr[3]; //重力分量 |G|=1 算法输出
- float W=10; //Rg陀螺仪滤波权重
- void setup()
- {
- Wire.begin();
- Serial.begin(38400);
- accelgyro.initialize();
- for(int a=0;a<3;a++) //获取角速度偏移
- {
- for(int i=0;i<50;i++)
- {
- accelgyro.getMotion6(&Ac[0], &Ac[1], &Ac[2], &Pa[0], &Pa[1], &Pa[2]);
- C_Pa[a]=C_Pa[a]+Pa[a];
- }
- C_Pa[a]=C_Pa[a]/50;
- }
- C_Ac[2]=-0.1;
- }
- void loop()
- {
- CalculateGr();
- printdata();
- delay(20);
- }
- void printdata ()
- {
- Serial.print(acos(Gr[0])*Ra);Serial.print(",");
- Serial.print(acos(A[0])*Ra);Serial.print(",");
- Serial.println(acos(Rg[0])*Ra);
-
- }
- void CalculateGr ()
- {
- accelgyro.getMotion6(&Ac[0], &Ac[1], &Ac[2], &Pa[0], &Pa[1], &Pa[2]);
- for(unsigned char a=0;a<3;a++) //处理角速度漂移
- {
- Pa[a]=Pa[a]-C_Pa[a];
- }
- for(unsigned char a=0;a<3;a++) //得到真实加速度和角速度
- {
- A[a]=Ac[a]/Ac_xs;
- P[a]=Pa[a]/Pa_xs;
- }
- A[2]=A[2]-C_Ac[2]; //处理加速度漂移
- G=sqrt(A[0]*A[0]+A[1]*A[1]+A[2]*A[2]);
-
- if(T_Last==0) //第一次
- {
- for(unsigned char a=0;a<3;a++)
- {
- for(unsigned char b=0;b<10;b++)
- {
- accelgyro.getMotion6(&Ac[0], &Ac[1], &Ac[2], &Pa[0], &Pa[1], &Pa[2]);
- A[a]=A[a]/Ac_xs;
- A[a]=A[a]+A[a];
- }
- A[a]=A[a]/10.0;
- Gr[a]=A[a];
- }
- A_X=acos(A[0]);
- A_Y=acos(A[1]);
- T_Last=micros();
- Pa_Y_Last=Pa[1];
- Pa_X_Last=Pa[0];
- }
- if(T_Last>0)
- {
- Pa_X_Now=P[0];
- Pa_Y_Now=P[1];
- T_Now=micros();
- A_X=A_X+(Pa_Y_Now+Pa_Y_Last)*(T_Now-T_Last)/2000000.0; //XY轴角度,从陀螺仪积分
- A_Y=A_Y+(Pa_X_Now-Pa_X_Last)*(T_Now-T_Last)/2000000.0;
- if(abs(G-1)>0.05)
- {
- Rg[0]=sq(sin(A_Y))/sqrt(1+sq((cos(A_X)))*sq(tan(A_Y)));
- Rg[1]=sq(sin(A_X))/sqrt(1+sq((cos(A_Y)))*sq(tan(A_X)));
- Rg[2]=sqrt(1-sq(Rg[0])-sq(Rg[1]));
- }
-
- if(abs(G-1)>=0.03) //校正
- {
- for(unsigned char a=0;a<3;a++)
- {
- A[a]=A[a]/G;
- }
- G=sqrt(A[0]*A[0]+A[1]*A[1]+A[2]*A[2]); //此时G化为1
- for(unsigned char v=0;v<3;v++)
- {
- Rg[v]=A[v]/G;
- }
- A_X=acos(A[0]);
- A_Y=acos(A[1]);
- }
-
- for(unsigned char b=0;b<3;b++) //互补滤波
- {
- Gr[b]=(A[b]+Rg[b]*W)/(W+1);
- }
- G=sqrt(sq(Gr[0])+sq(Gr[1])+sq(Gr[2]));
- for(unsigned char b=0;b<3;b++) //再次单位化 重力矢量
- {
- Gr[b]=Gr[b]/G;
- }
- T_Last=micros();
- Pa_X_Last=P[0];
- Pa_Y_Last=P[1];
- }
- }
复制代码
参考的是http://www.geek-workshop.com/forum.php?mod=viewthread&tid=1695
真实效果:
前十来秒还行,时间一长就明显反应滞后。
各位帮忙看看怎么弄。 |
|