当前位置:   article > 正文

MPU6050 卡尔曼滤波算法 四元数欧拉姿态解算 STM32 CubeMX HAL库 MDKkeil5 零基础移植_mpu 卡尔曼 四元数

mpu 卡尔曼 四元数

1.在 cubemx 开启 IIC 并设置好对应的 IIC 引脚

2.generate code 生成代码

(记得生成单个 c. h.文件)!!!!!!

3.复制以下的全部代码 新建分别保存放到 Inc Src 文件夹

每个字都是有用的!!!!!!

请全部复制!!!!!!!!!

每个字都是有用的!!!!!!

请全部复制!!!!!!!!

MPU6050.h

这是.h 文件中存放的内容

定义了结构体用于存放粗数据和处理后的数据 

使用时我们只需要关心 MPU6050_t 这个结构体类型

  1. /*
  2.  * mpu6050.h
  3.  *
  4.  *  Created on: Nov 13, 2019
  5.  *      Author: Bulanov Konstantin
  6.  */
  7. #ifndef INC_GY521_H_
  8. #define INC_GY521_H_
  9. #endif /* INC_GY521_H_ */
  10. #include <stdint.h>
  11. #include "i2c.h"
  12. // MPU6050 structure
  13. typedef struct
  14. {
  15.     int16_t Accel_X_RAW;
  16.     int16_t Accel_Y_RAW;
  17.     int16_t Accel_Z_RAW;
  18.     double Ax;
  19.     double Ay;
  20.     double Az;
  21.     int16_t Gyro_X_RAW;
  22.     int16_t Gyro_Y_RAW;
  23.     int16_t Gyro_Z_RAW;
  24.     double Gx;
  25.     double Gy;
  26.     double Gz;
  27.     float Temperature;
  28.     double KalmanAngleX;
  29.     double KalmanAngleY;
  30. } MPU6050_t;
  31. // Kalman structure
  32. typedef struct
  33. {
  34.     double Q_angle;
  35.     double Q_bias;
  36.     double R_measure;
  37.     double angle;
  38.     double bias;
  39.     double P[2][2];
  40. } Kalman_t;
  41. uint8_t MPU6050_Init(I2C_HandleTypeDef *I2Cx);
  42. void MPU6050_Read_Accel(I2C_HandleTypeDef *I2Cx, MPU6050_t *DataStruct);
  43. void MPU6050_Read_Gyro(I2C_HandleTypeDef *I2Cx, MPU6050_t *DataStruct);
  44. void MPU6050_Read_Temp(I2C_HandleTypeDef *I2Cx, MPU6050_t *DataStruct);
  45. void MPU6050_Read_All(I2C_HandleTypeDef *I2Cx, MPU6050_t *DataStruct);
  46. double Kalman_getAngle(Kalman_t *Kalman, double newAngle, double newRate, double dt);

MPU6050.c

这其中包含了数据处理的函数

每个字都是有用的!!!!!!

请全部复制!!!!!!!!

每个字都是有用的!!!!!

请全部复制!!!!!!!!

关于DEFINE 这关乎数据的读取 请全部复制!!!!!!

  1. /*
  2. * mpu6050.c
  3. *
  4. * Created on: Nov 13, 2019
  5. * Author: Bulanov Konstantin
  6. *
  7. * Contact information
  8. * -------------------
  9. */
  10. #include <math.h>
  11. #include "mpu6050.h"
  12. #define RAD_TO_DEG 57.295779513082320876798154814105
  13. #define WHO_AM_I_REG 0x75
  14. #define PWR_MGMT_1_REG 0x6B
  15. #define SMPLRT_DIV_REG 0x19
  16. #define ACCEL_CONFIG_REG 0x1C
  17. #define ACCEL_XOUT_H_REG 0x3B
  18. #define TEMP_OUT_H_REG 0x41
  19. #define GYRO_CONFIG_REG 0x1B
  20. #define GYRO_XOUT_H_REG 0x43
  21. // Setup MPU6050
  22. #define MPU6050_ADDR 0xD0
  23. const uint16_t i2c_timeout = 100;
  24. const double Accel_Z_corrector = 14418.0;
  25. uint32_t timer;
  26. Kalman_t KalmanX = {
  27. .Q_angle = 0.001f,
  28. .Q_bias = 0.003f,
  29. .R_measure = 0.03f};
  30. Kalman_t KalmanY = {
  31. .Q_angle = 0.001f,
  32. .Q_bias = 0.003f,
  33. .R_measure = 0.03f,
  34. };
  35. uint8_t MPU6050_Init(I2C_HandleTypeDef *I2Cx)
  36. {
  37. uint8_t check;
  38. uint8_t Data;
  39. // check device ID WHO_AM_I
  40. HAL_I2C_Mem_Read(I2Cx, MPU6050_ADDR, WHO_AM_I_REG, 1, &check, 1, i2c_timeout);
  41. if (check == 104) // 0x68 will be returned by the sensor if everything goes well
  42. {
  43. // power management register 0X6B we should write all 0's to wake the sensor up
  44. Data = 0;
  45. HAL_I2C_Mem_Write(I2Cx, MPU6050_ADDR, PWR_MGMT_1_REG, 1, &Data, 1, i2c_timeout);
  46. // Set DATA RATE of 1KHz by writing SMPLRT_DIV register
  47. Data = 0x07;
  48. HAL_I2C_Mem_Write(I2Cx, MPU6050_ADDR, SMPLRT_DIV_REG, 1, &Data, 1, i2c_timeout);
  49. // Set accelerometer configuration in ACCEL_CONFIG Register
  50. // XA_ST=0,YA_ST=0,ZA_ST=0, FS_SEL=0 -> ? 2g
  51. Data = 0x00;
  52. HAL_I2C_Mem_Write(I2Cx, MPU6050_ADDR, ACCEL_CONFIG_REG, 1, &Data, 1, i2c_timeout);
  53. // Set Gyroscopic configuration in GYRO_CONFIG Register
  54. // XG_ST=0,YG_ST=0,ZG_ST=0, FS_SEL=0 -> ? 250 ?/s
  55. Data = 0x00;
  56. HAL_I2C_Mem_Write(I2Cx, MPU6050_ADDR, GYRO_CONFIG_REG, 1, &Data, 1, i2c_timeout);
  57. return 0;
  58. }
  59. return 1;
  60. }
  61. void MPU6050_Read_Accel(I2C_HandleTypeDef *I2Cx, MPU6050_t *DataStruct)
  62. {
  63. uint8_t Rec_Data[6];
  64. // Read 6 BYTES of data starting from ACCEL_XOUT_H register
  65. HAL_I2C_Mem_Read(I2Cx, MPU6050_ADDR, ACCEL_XOUT_H_REG, 1, Rec_Data, 6, i2c_timeout);
  66. DataStruct->Accel_X_RAW = (int16_t)(Rec_Data[0] << 8 | Rec_Data[1]);
  67. DataStruct->Accel_Y_RAW = (int16_t)(Rec_Data[2] << 8 | Rec_Data[3]);
  68. DataStruct->Accel_Z_RAW = (int16_t)(Rec_Data[4] << 8 | Rec_Data[5]);
  69. /*** convert the RAW values into acceleration in 'g'
  70. we have to divide according to the Full scale value set in FS_SEL
  71. I have configured FS_SEL = 0. So I am dividing by 16384.0
  72. for more details check ACCEL_CONFIG Register ****/
  73. DataStruct->Ax = DataStruct->Accel_X_RAW / 16384.0;
  74. DataStruct->Ay = DataStruct->Accel_Y_RAW / 16384.0;
  75. DataStruct->Az = DataStruct->Accel_Z_RAW / Accel_Z_corrector;
  76. }
  77. void MPU6050_Read_Gyro(I2C_HandleTypeDef *I2Cx, MPU6050_t *DataStruct)
  78. {
  79. uint8_t Rec_Data[6];
  80. // Read 6 BYTES of data starting from GYRO_XOUT_H register
  81. HAL_I2C_Mem_Read(I2Cx, MPU6050_ADDR, GYRO_XOUT_H_REG, 1, Rec_Data, 6, i2c_timeout);
  82. DataStruct->Gyro_X_RAW = (int16_t)(Rec_Data[0] << 8 | Rec_Data[1]);
  83. DataStruct->Gyro_Y_RAW = (int16_t)(Rec_Data[2] << 8 | Rec_Data[3]);
  84. DataStruct->Gyro_Z_RAW = (int16_t)(Rec_Data[4] << 8 | Rec_Data[5]);
  85. /*** convert the RAW values into dps (?/s)
  86. we have to divide according to the Full scale value set in FS_SEL
  87. I have configured FS_SEL = 0. So I am dividing by 131.0
  88. for more details check GYRO_CONFIG Register ****/
  89. DataStruct->Gx = DataStruct->Gyro_X_RAW / 131.0;
  90. DataStruct->Gy = DataStruct->Gyro_Y_RAW / 131.0;
  91. DataStruct->Gz = DataStruct->Gyro_Z_RAW / 131.0;
  92. }
  93. void MPU6050_Read_Temp(I2C_HandleTypeDef *I2Cx, MPU6050_t *DataStruct)
  94. {
  95. uint8_t Rec_Data[2];
  96. int16_t temp;
  97. // Read 2 BYTES of data starting from TEMP_OUT_H_REG register
  98. HAL_I2C_Mem_Read(I2Cx, MPU6050_ADDR, TEMP_OUT_H_REG, 1, Rec_Data, 2, i2c_timeout);
  99. temp = (int16_t)(Rec_Data[0] << 8 | Rec_Data[1]);
  100. DataStruct->Temperature = (float)((int16_t)temp / (float)340.0 + (float)36.53);
  101. }
  102. void MPU6050_Read_All(I2C_HandleTypeDef *I2Cx, MPU6050_t *DataStruct)
  103. {
  104. uint8_t Rec_Data[14];
  105. int16_t temp;
  106. // Read 14 BYTES of data starting from ACCEL_XOUT_H register
  107. HAL_I2C_Mem_Read(I2Cx, MPU6050_ADDR, ACCEL_XOUT_H_REG, 1, Rec_Data, 14, i2c_timeout);
  108. DataStruct->Accel_X_RAW = (int16_t)(Rec_Data[0] << 8 | Rec_Data[1]);
  109. DataStruct->Accel_Y_RAW = (int16_t)(Rec_Data[2] << 8 | Rec_Data[3]);
  110. DataStruct->Accel_Z_RAW = (int16_t)(Rec_Data[4] << 8 | Rec_Data[5]);
  111. temp = (int16_t)(Rec_Data[6] << 8 | Rec_Data[7]);
  112. DataStruct->Gyro_X_RAW = (int16_t)(Rec_Data[8] << 8 | Rec_Data[9]);
  113. DataStruct->Gyro_Y_RAW = (int16_t)(Rec_Data[10] << 8 | Rec_Data[11]);
  114. DataStruct->Gyro_Z_RAW = (int16_t)(Rec_Data[12] << 8 | Rec_Data[13]);
  115. DataStruct->Ax = DataStruct->Accel_X_RAW / 16384.0;
  116. DataStruct->Ay = DataStruct->Accel_Y_RAW / 16384.0;
  117. DataStruct->Az = DataStruct->Accel_Z_RAW / Accel_Z_corrector;
  118. DataStruct->Temperature = (float)((int16_t)temp / (float)340.0 + (float)36.53);
  119. DataStruct->Gx = DataStruct->Gyro_X_RAW / 131.0;
  120. DataStruct->Gy = DataStruct->Gyro_Y_RAW / 131.0;
  121. DataStruct->Gz = DataStruct->Gyro_Z_RAW / 131.0;
  122. // Kalman angle solve
  123. double dt = (double)(HAL_GetTick() - timer) / 1000;
  124. timer = HAL_GetTick();
  125. double roll;
  126. double roll_sqrt = sqrt(
  127. DataStruct->Accel_X_RAW * DataStruct->Accel_X_RAW + DataStruct->Accel_Z_RAW * DataStruct->Accel_Z_RAW);
  128. if (roll_sqrt != 0.0)
  129. {
  130. roll = atan(DataStruct->Accel_Y_RAW / roll_sqrt) * RAD_TO_DEG;
  131. }
  132. else
  133. {
  134. roll = 0.0;
  135. }
  136. double pitch = atan2(-DataStruct->Accel_X_RAW, DataStruct->Accel_Z_RAW) * RAD_TO_DEG;
  137. if ((pitch < -90 && DataStruct->KalmanAngleY > 90) || (pitch > 90 && DataStruct->KalmanAngleY < -90))
  138. {
  139. KalmanY.angle = pitch;
  140. DataStruct->KalmanAngleY = pitch;
  141. }
  142. else
  143. {
  144. DataStruct->KalmanAngleY = Kalman_getAngle(&KalmanY, pitch, DataStruct->Gy, dt);
  145. }
  146. if (fabs(DataStruct->KalmanAngleY) > 90)
  147. DataStruct->Gx = -DataStruct->Gx;
  148. DataStruct->KalmanAngleX = Kalman_getAngle(&KalmanX, roll, DataStruct->Gx, dt);
  149. }
  150. double Kalman_getAngle(Kalman_t *Kalman, double newAngle, double newRate, double dt)
  151. {
  152. double rate = newRate - Kalman->bias;
  153. Kalman->angle += dt * rate;
  154. Kalman->P[0][0] += dt * (dt * Kalman->P[1][1] - Kalman->P[0][1] - Kalman->P[1][0] + Kalman->Q_angle);
  155. Kalman->P[0][1] -= dt * Kalman->P[1][1];
  156. Kalman->P[1][0] -= dt * Kalman->P[1][1];
  157. Kalman->P[1][1] += Kalman->Q_bias * dt;
  158. double S = Kalman->P[0][0] + Kalman->R_measure;
  159. double K[2];
  160. K[0] = Kalman->P[0][0] / S;
  161. K[1] = Kalman->P[1][0] / S;
  162. double y = newAngle - Kalman->angle;
  163. Kalman->angle += K[0] * y;
  164. Kalman->bias += K[1] * y;
  165. double P00_temp = Kalman->P[0][0];
  166. double P01_temp = Kalman->P[0][1];
  167. Kalman->P[0][0] -= K[0] * P00_temp;
  168. Kalman->P[0][1] -= K[0] * P01_temp;
  169. Kalman->P[1][0] -= K[1] * P00_temp;
  170. Kalman->P[1][1] -= K[1] * P01_temp;
  171. return Kalman->angle;
  172. };

 5. 移植完毕代码之后

重要的是怎么去使用

(在使用之前请确保 编译时 上述文件是包含在程序中的!!!!)

我们需要创建一个全局变量 用于存放数据

这一步非常重要!!!!!!

请不要忘记创建变量!!!!

请不要忘记创建变量!!!!

请不要忘记创建变量!!!!

请按下面步骤操作

这一步也是至关重要!!!!

请放在进入while(1)死循环之前 

请放在进入while(1)死循环之前 

请放在进入while(1)死循环之前 

这一步是用于确保初始化的正确

这之后就是while(1)死循环里的操作了 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/429162
推荐阅读
相关标签
  

闽ICP备14008679号