標(biāo)題: STM32代碼MPU6050的姿態(tài)結(jié)算,摘用cleanfight的姿態(tài)解算代碼 [打印本頁(yè)]

作者: chrain5    時(shí)間: 2018-1-20 10:53
標(biāo)題: STM32代碼MPU6050的姿態(tài)結(jié)算,摘用cleanfight的姿態(tài)解算代碼
STM32代碼MPU6050的姿態(tài)結(jié)算,摘用cleanfight的姿態(tài)解算代碼,,,效果可以

單片機(jī)源程序如下:
  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姿態(tài)數(shù)據(jù)
  17. Attitudat_Struct Gyro_Offset;  //陀螺儀零漂數(shù)據(jù)
  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);        //得到加速度傳感器數(shù)據(jù)
  24.   MPU_Get_Gyroscope(&Gyro_X,&Gyro_Y,&Gyro_Z);        //得到陀螺儀數(shù)據(jù)
  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);        //得到陀螺儀數(shù)據(jù)
  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++)//滑動(dòng)平滑濾波
  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. …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼

所有資料51hei提供下載:
imu.zip (3.66 KB, 下載次數(shù): 176)



作者: home8976    時(shí)間: 2018-8-22 14:33
過(guò)來(lái)看看
作者: lyjpla    時(shí)間: 2019-10-4 21:45
謝謝!非常有參考價(jià)值

作者: 楓葉-嵌入式    時(shí)間: 2019-10-6 11:25
這個(gè)資料很不錯(cuò),正需要
作者: 18519187648    時(shí)間: 2022-9-17 17:09
你這怎么用啊,一些參數(shù)都沒(méi)寫(xiě)說(shuō)明
作者: lm7298    時(shí)間: 2022-9-19 15:35
資料很不錯(cuò),正好需要,感謝




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1