找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7625|回复: 5
打印 上一主题 下一主题
收起左侧

STM32代码MPU6050的姿态结算,摘用cleanfight的姿态解算代码

  [复制链接]
跳转到指定楼层
楼主
STM32代码MPU6050的姿态结算,摘用cleanfight的姿态解算代码,,,效果可以

单片机源程序如下:
  1. #include "imu.h"
  2. #include "imu.h"
  3. #include  "math.h"
  4. #include "flycontro.h"

  5. #define SPIN_RATE_LIMIT 20

  6. #ifndef sq
  7. #define sq(x) ((x)*(x))
  8. #endif
  9. #define sin_approx(x)   sinf(x)
  10. #define cos_approx(x)   cosf(x)
  11. #define atan2_approx(y,x)   atan2f(y,x)
  12. #define acos_approx(x)      acosf(x)
  13. #define tan_approx(x)       tanf(x)
  14. // Use floating point M_PI instead explicitly.
  15. #define M_PIf       3.14159265358979323846f




  16. Attitudat_Struct Accel,Gyro,Angle; //MPU姿态数据
  17. Attitudat_Struct Gyro_Offset;  //陀螺仪零漂数据
  18. short Accel_X,Accel_Y,Accel_Z,Gyro_X,Gyro_Y,Gyro_Z;
  19. void MPU_GetAngleDat(void)
  20. {
  21.   int  Accel_Xtemp,Accel_Ytemp,Accel_Ztemp,Accel_Xtempout,Accel_Ytempout,Accel_Ztempout;
  22. /// static float Yawerr=0,lastYawerr=0;
  23.   MPU_Get_Accelerometer(&Accel_X,&Accel_Y,&Accel_Z);        //得到加速度传感器数据
  24.   MPU_Get_Gyroscope(&Gyro_X,&Gyro_Y,&Gyro_Z);        //得到陀螺仪数据
  25.   
  26.         Accel_Xtemp  = Accel_X;
  27.         Accel_Ytemp  = Accel_Y;
  28.         Accel_Ztemp  = Accel_Z;

  29.   Prepare_Data(&Accel_Xtemp,&Accel_Ytemp,&Accel_Ztemp,&Accel_Xtempout ,&Accel_Ytempout,&Accel_Ztempout);

  30.         Accel.X = Accel_Xtempout;     ////8192
  31.         Accel.Y = Accel_Ytempout;
  32.   Accel.Z = Accel_Ztempout;        
  33.        
  34.         Gyro.X = (Gyro_X - Gyro_Offset.X) ;
  35.         Gyro.Y = (Gyro_Y - Gyro_Offset.Y) ;
  36.         Gyro.Z = (Gyro_Z - Gyro_Offset.Z) ;

  37. }


  38. u8 Gyro_calibration(void)
  39. {
  40. //u16 i;
  41. //short  Gyro_X,Gyro_Y,Gyro_Z;
  42. static long int GyroofsetX=0,GyroofsetY=0,GyroofsetZ=0;
  43. static u16 i= 0;
  44. //        for(i=0;i<1000;i++)
  45. //         {
  46. // MPU_Get_Gyroscope(&Gyro_X,&Gyro_Y,&Gyro_Z);        //得到陀螺仪数据
  47.     GyroofsetX+=Gyro_X;
  48.                 GyroofsetY+=Gyro_Y;
  49.                 GyroofsetZ+=Gyro_Z;
  50.           i++;
  51. //                delay_ms(5);
  52. //   }
  53. //       
  54.         if(i==1000)
  55.         {
  56.    i=0;
  57.    Gyro_Offset.X = GyroofsetX/1000;
  58.    Gyro_Offset.Y = GyroofsetY/1000;
  59.    Gyro_Offset.Z = GyroofsetZ/1000;
  60.          GyroofsetX=GyroofsetY=GyroofsetZ=0;
  61.                 return 1;
  62.         }

  63.         return 0;
  64. }


  65. void Prepare_Data(int *accx,int *accy,int *accz,int *accoutx,int *accouty,int *accoutz)
  66. {  
  67.         static uint8_t         filter_cnt=0;
  68.         static int16_t        ACC_X_BUF[FILTER_NUM],ACC_Y_BUF[FILTER_NUM],ACC_Z_BUF[FILTER_NUM];
  69.         int32_t temp1=0,temp2=0,temp3=0;
  70.         uint8_t i;       
  71.         ACC_X_BUF[filter_cnt] = *accx;
  72.         ACC_Y_BUF[filter_cnt] = *accy;
  73.         ACC_Z_BUF[filter_cnt] = *accz;
  74.         for(i=0;i<FILTER_NUM;i++)//滑动平滑滤波
  75.         {
  76.                 temp1 += ACC_X_BUF[i];
  77.                 temp2 += ACC_Y_BUF[i];
  78.                 temp3 += ACC_Z_BUF[i];
  79.         }
  80.         *accoutx = temp1 / FILTER_NUM;
  81.         *accouty = temp2 / FILTER_NUM;
  82.         *accoutz = temp3 / FILTER_NUM;
  83.         filter_cnt++;
  84.         if(filter_cnt==FILTER_NUM)        filter_cnt=0;

  85. }












  86. float q0 = 1.0f, q1 = 0.0f, q2 = 0.0f, q3 = 0.0f;    // quaternion of sensor frame relative to earth frame
  87. static float rMat[3][3];

  88. float dcmKiGain = 0.005;
  89. float dcmKpGain = 2.0;

  90. static float invSqrt(float x)
  91. {
  92.     return 1.0f / sqrtf(x);
  93. }

  94. void imuMahonyAHRSupdate(float dt, float gx, float gy, float gz,
  95.                                                                                                         bool useAcc, float ax, float ay, float az,
  96.                                                                                                         bool useMag, float mx, float my, float mz,
  97.                                                                                                         bool useYaw, float yawError)
  98. {
  99.     static float integralFBx = 0.0f,  integralFBy = 0.0f, integralFBz = 0.0f;    // integral error terms scaled by Ki
  100.     float recipNorm;
  101.     float hx, hy, bx;
  102.     float ex = 0, ey = 0, ez = 0;
  103.     float qa, qb, qc;
  104.    
  105.     // Calculate general spin rate (rad/s)
  106.     float spin_rate = sqrtf(sq(gx) + sq(gy) + sq(gz));
  107.           float ez_ef;
  108.     // Use raw heading error (from GPS or whatever else)
  109.     if (useYaw) {
  110.         while (yawError >  M_PIf) yawError -= (2.0f * M_PIf);
  111.         while (yawError < -M_PIf) yawError += (2.0f * M_PIf);

  112.         ez += sin_approx(yawError / 2.0f);
  113.     }

  114.     // Use measured magnetic field vector  
  115.     recipNorm = sq(mx) + sq(my) + sq(mz);
  116.     if (useMag && recipNorm > 0.01f)
  117.                         {
  118.         // Normalise magnetometer measurement ?????????
  119.         recipNorm = invSqrt(recipNorm);
  120.         mx *= recipNorm;
  121.         my *= recipNorm;
  122.         mz *= recipNorm;
  123.                                 // For magnetometer correction we make an assumption that magnetic field is perpendicular to gravity (ignore Z-component in EF).
  124.                                 // This way magnetic field will only affect heading and wont mess roll/pitch angles

  125.                                 // (hx; hy; 0) - measured mag field vector in EF (assuming Z-component is zero)
  126.                                 // (bx; 0; 0) - reference mag field vector heading due North in EF (assuming Z-component is zero)
  127.         hx = rMat[0][0] * mx + rMat[0][1] * my + rMat[0][2] * mz;
  128.         hy = rMat[1][0] * mx + rMat[1][1] * my + rMat[1][2] * mz;
  129.         bx = sqrtf(hx * hx + hy * hy);

  130.         // magnetometer error is cross product between estimated magnetic north and measured magnetic north (calculated in EF)
  131.         ez_ef = -(hy * bx);

  132.         // Rotate mag error vector back to BF and accumulate
  133.         ex -= rMat[2][0] * ez_ef;
  134.         ey -= rMat[2][1] * ez_ef;
  135.         ez += rMat[2][2] * ez_ef;
  136.     }

  137.     // Use measured acceleration vector ?????????
  138.     recipNorm = sq(ax) + sq(ay) + sq(az);
  139.     if (useAcc && recipNorm > 0.01f)
  140.                         {
  141.         // Normalise accelerometer measurement ?????????
  142.         recipNorm = invSqrt(recipNorm);
  143.         ax *= recipNorm;
  144.         ay *= recipNorm;
  145.         az *= recipNorm;

  146.         // Error is sum of cross product between estimated direction and measured direction of gravity
  147.         ex += (ay * rMat[2][2] - az * rMat[2][1]);
  148.         ey += (az * rMat[2][0] - ax * rMat[2][2]);
  149.         ez += (ax * rMat[2][1] - ay * rMat[2][0]);
  150.     }

  151.     // Compute and apply integral feedback if enabled
  152.     if(dcmKiGain > 0.0f) {   //imuRuntimeConfig->dcm_ki
  153.         // Stop integrating if spinning beyond the certain limit????,??????????
  154.         if (spin_rate < DEGREES_TO_RADIANS(SPIN_RATE_LIMIT)) {
  155.        //     float dcmKiGain = dcm_ki;
  156.             integralFBx += dcmKiGain * ex * dt;    // integral error scaled by Ki
  157.             integralFBy += dcmKiGain * ey * dt;
  158.             integralFBz += dcmKiGain * ez * dt;
  159.         }
  160.     }
  161.     else {
  162.         integralFBx = 0.0f;    // prevent integral windup
  163.         integralFBy = 0.0f;
  164.         integralFBz = 0.0f;
  165.         }

  166.     // Calculate kP gain. If we are acquiring initial attitude (not armed and within 20 sec from powerup) scale the kP to converge faster
  167.     //   dcmKpGain =  dcm_kp ;//* imuGetPGainScaleFactor();

  168.     // Apply proportional and integral feedback??????
  169.     gx += dcmKpGain * ex + integralFBx;
  170.     gy += dcmKpGain * ey + integralFBy;
  171.     gz += dcmKpGain * ez + integralFBz;

  172.     // Integrate rate of change of quaternion??????
  173.     gx *= (0.5f * dt);
  174.     gy *= (0.5f * dt);
  175.     gz *= (0.5f * dt);

  176.     qa = q0;
  177.     qb = q1;
  178.     qc = q2;
  179.     q0 += (-qb * gx - qc * gy - q3 * gz);
  180.     q1 += (qa * gx + qc * gz - q3 * gy);
  181.     q2 += (qa * gy - qb * gz + q3 * gx);
  182.     q3 += (qa * gz + qb * gy - qc * gx);
  183.     // Normalise quaternion
  184.     recipNorm = invSqrt(sq(q0) + sq(q1) + sq(q2) + sq(q3));
  185.     q0 *= recipNorm;
  186.     q1 *= recipNorm;
  187.     q2 *= recipNorm;
  188.     q3 *= recipNorm;

  189.     // Pre-compute rotation matrix from quaternion
  190.     imuComputeRotationMatrix();
  191. #if 0         
  192. //                 Angle.Y = asin(-2 * q1 * q3  + 2 * q0* q2)* 57.3 ; // pitch  
  193. //          Angle.X = atan2( 2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll
  194. //          Angle.Z = atan2(2 * q1 * q2  + 2 * q0 * q3, -2 * q2*q2 - 2 * q3* q3 + 1)* 57.3; // yaw
  195. #else         
  196.          imuUpdateEulerAngles(&Angle.X,&Angle.Y,&Angle.Z);
  197. #endif

  198. }

  199. void imuComputeRotationMatrix(void)
  200. {
  201.     float q1q1 = sq(q1);
  202.     float q2q2 = sq(q2);
  203.     float q3q3 = sq(q3);

  204.     float q0q1 = q0 * q1;
  205.     float q0q2 = q0 * q2;
  206. ……………………

  207. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
imu.zip (3.66 KB, 下载次数: 176)


评分

参与人数 2黑币 +55 收起 理由
fanwangxing + 5
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏5 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:388895 发表于 2018-8-22 14:33 | 只看该作者
过来看看
回复

使用道具 举报

板凳
ID:206977 发表于 2019-10-4 21:45 | 只看该作者
谢谢!非常有参考价值
回复

使用道具 举报

地板
ID:618028 发表于 2019-10-6 11:25 | 只看该作者
这个资料很不错,正需要
回复

使用道具 举报

5#
ID:1045035 发表于 2022-9-17 17:09 | 只看该作者
你这怎么用啊,一些参数都没写说明
回复

使用道具 举报

6#
ID:1041367 发表于 2022-9-19 15:35 | 只看该作者
资料很不错,正好需要,感谢
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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