当前位置:   article > 正文

MPU6050篇——姿态解算,卡尔曼滤波_mpu6050姿态解算代码

mpu6050姿态解算代码

一、DMP文件的修改:

        首先我们打开inv_mpu.c文件夹,如下图所示便是第一个要修改的地方:

我们将其修改为:define定义可以改为自己使用的型号的单片机。

修改后在上面定义这个宏,并加上一个MPU6050的宏,用于源文件区别芯片:

然后我们打开inv_mpu_dmp_motion_driver.c,找到如下地方,和上面一样:   

修改为:(记得在上面加入#define  STM32F10x_MPU6050)

此时还有一些地方需要完善,但大致已经改完了,修缮一下:编译,报3处错,如下:

 这里报错:(inv_mpu.h文件中)

修改为:

 在inv_mpu_dmp_motion_driver.c中:

此时编译还有一个错误:

可以发现是inv_mpu中的问题,我们找到这给注释掉

此时再编译,无错误,一个警告,如下图:

我们点击过去给函数注释掉:(注意一定要注释全,是一整个函数,比较长)

 此时再编译:无错误。

 二、官方源码的移植

 此时,我们的DMP代码已经改完了,下面还要移植官方例子的初始化等代码:下面来转植代码,打开官方库如下文件:

下拉,在main函数复制下面方框的结构体及初始化函数,并自己创建一个函数封装起来并判断返回值:这些函数正确执行就会返回0,否则返回非0数。 

到这步你的代码应该是这样:

这几个函数是设置传感器、设置fifo、设置采样率的,复制到自己的代码:

其中DEFAULT_MPU_HZ为官方定义的,ctrl+f搜索一下复制到自己函数上面,然后在相应函数判断返回值,此时代码应该如下:

下面复制DMP初始化步骤代码并粘贴到自己的函数中并判断其返回值:

删掉两行关于注册函数的(未使用到)

再删掉结构体,不使用结构体赋值,如下效果:

这里有个函数报错,去官方库把这个函数复制过来:

即将这两个函数都复制过去并粘贴到MPU6050_DMP_Init上面:

在官方文件找到自检函数复制过来,同样判断返回值:

再将此函数从官方库找出来粘贴到我们初始化函数上方,删掉下图所示内容:

添加返回值,错误返回1,否则为0

自此,其移植已经完成了,下面经行获取姿态数据 

三、使用MPU6050获取姿态数据

 先写下获取数据的函数,由于DMP会将处理好的数据放入fifo,所以我们只需要读取fifo就可以取出其数据了。至于怎么使用这个函数可以转向定义看看:

定义好相关参数并传到读fifo函数中,再判断其返回值,此时代码应该为:

接下来就开始解析四元数了,将四元数转化为欧拉角:

fifo函数的标志位为sensors,当某个数据存在,读函数会把sensors参数某个位置置一。

我们要获取四元数,判断其标志位,如果有四元数便经行下一步解析。将读出四元数转换成浮点数,直接除2的30次方便将Q30格式换为浮点数了。在上方定义四个浮点型变量用来存储转换后的数据:2^30 = 1073741824,我们宏定义于函数上方,在转换为浮点数,第二张图:

最后将四元数转换为欧拉角,网上百度一下公式,如下:

我们根据其公式编写代码:(乘57.3目的时弧度转换成角度) 至于返回值是好查看错误时是哪步的问题。

此时编译无错误警告,移植完成

需要添加的代码我放下面:

  1. #define DEFAULT_MPU_HZ (100)
  2. //q30格式,long转float时的除数.
  3. #define q30 1073741824.0f
  4. void mget_ms(unsigned long *time)
  5. {
  6. //空函数,未使用
  7. }
  8. static unsigned short inv_row_2_scale(const signed char *row)
  9. {
  10. unsigned short b;
  11. if (row[0] > 0)
  12. b = 0;
  13. else if (row[0] < 0)
  14. b = 4;
  15. else if (row[1] > 0)
  16. b = 1;
  17. else if (row[1] < 0)
  18. b = 5;
  19. else if (row[2] > 0)
  20. b = 2;
  21. else if (row[2] < 0)
  22. b = 6;
  23. else
  24. b = 7; // error
  25. return b;
  26. }
  27. static unsigned short inv_orientation_matrix_to_scalar(
  28. const signed char *mtx)
  29. {
  30. unsigned short scalar;
  31. /*
  32. XYZ 010_001_000 Identity Matrix
  33. XZY 001_010_000
  34. YXZ 010_000_001
  35. YZX 000_010_001
  36. ZXY 001_000_010
  37. ZYX 000_001_010
  38. */
  39. scalar = inv_row_2_scale(mtx);
  40. scalar |= inv_row_2_scale(mtx + 3) << 3;
  41. scalar |= inv_row_2_scale(mtx + 6) << 6;
  42. return scalar;
  43. }
  44. static signed char gyro_orientation[9] = {-1, 0, 0,
  45. 0,-1, 0,
  46. 0, 0, 1};
  47. static int run_self_test(void)
  48. {
  49. int result;
  50. long gyro[3], accel[3];
  51. result = mpu_run_self_test(gyro, accel);
  52. if (result == 0x3) {
  53. /* Test passed. We can trust the gyro data here, so let's push it down
  54. * to the DMP.
  55. */
  56. float sens;
  57. unsigned short accel_sens;
  58. mpu_get_gyro_sens(&sens);
  59. gyro[0] = (long)(gyro[0] * sens);
  60. gyro[1] = (long)(gyro[1] * sens);
  61. gyro[2] = (long)(gyro[2] * sens);
  62. dmp_set_gyro_bias(gyro);
  63. mpu_get_accel_sens(&accel_sens);
  64. accel[0] *= accel_sens;
  65. accel[1] *= accel_sens;
  66. accel[2] *= accel_sens;
  67. dmp_set_accel_bias(accel);
  68. }else return 1;
  69. return 0;
  70. }
  71. int MPU6050_DMP_Init(void)
  72. {
  73. int result;
  74. struct int_param_s int_param;
  75. result = mpu_init(&int_param);//mpu初始化
  76. if(result != 0) return -1;
  77. result = mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL);//设置传感器
  78. if(result != 0) return -2;
  79. result = mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL);//设置fifo
  80. if(result != 0) return -3;
  81. result = mpu_set_sample_rate(DEFAULT_MPU_HZ);//设置采样率
  82. if(result != 0) return -4;
  83. result = dmp_load_motion_driver_firmware();//加载DMP固件
  84. if(result != 0) return -5;
  85. result = dmp_set_orientation(
  86. inv_orientation_matrix_to_scalar(gyro_orientation));//设置陀螺仪方向
  87. if(result != 0) return -6;
  88. result = dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT | DMP_FEATURE_TAP |
  89. DMP_FEATURE_ANDROID_ORIENT | DMP_FEATURE_SEND_RAW_ACCEL | DMP_FEATURE_SEND_CAL_GYRO |
  90. DMP_FEATURE_GYRO_CAL);//设置dmp功能
  91. if(result != 0) return -7;
  92. result = dmp_set_fifo_rate(DEFAULT_MPU_HZ);//设置输出速率
  93. if(result != 0) return -8;
  94. result = run_self_test();//自检
  95. if(result != 0) return -9;
  96. result = mpu_set_dmp_state(1);//使能DMP
  97. if(result != 0) return -10;
  98. return result;
  99. }
  100. int mpu_dmp_get_data(float *pitch,float *roll,float *yaw)
  101. {
  102. float q0=1.0f,q1=0.0f,q2=0.0f,q3=0.0f;
  103. unsigned long sensor_timestamp;
  104. short gyro[3], accel[3], sensors;
  105. unsigned char more;
  106. long quat[4];
  107. if(dmp_read_fifo(gyro, accel, quat, &sensor_timestamp, &sensors,&more))return 1;
  108. if(sensors&INV_WXYZ_QUAT)
  109. {
  110. q0 = quat[0] / q30; //q30格式转换为浮点数
  111. q1 = quat[1] / q30;
  112. q2 = quat[2] / q30;
  113. q3 = quat[3] / q30;
  114. //计算得到俯仰角/横滚角/航向角
  115. *pitch = asin(-2 * q1 * q3 + 2 * q0* q2)* 57.3; // pitch
  116. *roll = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll
  117. *yaw = atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3) * 57.3; //yaw
  118. }else return 2;
  119. return 0;
  120. }

我们在主函数就可以读取数据了:

main.c

  1. #include "stm32f10x.h" // Device header
  2. #include "Delay.h"
  3. #include "oled.h"
  4. #include "stdio.h"
  5. #include "mpu6050.h"
  6. #include "inv_mpu.h"
  7. int main(void)
  8. {
  9. u8 string[10] = {0};
  10. float pitch,roll,yaw;
  11. MPU_Init();
  12. MPU6050_DMP_Init();
  13. while (1)
  14. {
  15. mpu_dmp_get_data(&pitch,&roll,&yaw);
  16. sprintf((char *)string,"Pitch:%.2f",1.32);//0300
  17. OLED_ShowString(16,10,string,16,1);
  18. sprintf((char *)string,"Roll :%.2f",roll);//0300
  19. OLED_ShowString(16,26,string,16,1);
  20. sprintf((char *)string,"Yaw :%.2f",yaw);//0300
  21. OLED_ShowString(16,46,string,16,1);
  22. OLED_DrawLine(5,5,125,5,1);
  23. OLED_DrawLine(5,5,5,62,1);
  24. OLED_DrawLine(5,62,125,62,1);
  25. OLED_DrawLine(125,5,125,62,1);
  26. OLED_Refresh();
  27. OLED_Refresh();
  28. if(pitch>70)pitch=70;
  29. if(pitch<-70)pitch=-70;
  30. if(roll>70)pitch=70;
  31. if(roll<-70)pitch=-70;
  32. OLED_Refresh();
  33. }
  34. }

上面MPU6050_DMP_Init应该 int型,并返回负数,否则结果不对!

效果:没拍好,但是代码可用

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

闽ICP备14008679号