7818|5

606

帖子

20

TA的资源

一粒金砂(高级)

楼主
 

F7 独轮机器人 MPU6050-DMP移植 [复制链接]

本帖最后由 ketose 于 2015-10-26 21:43 编辑

     这篇主要谈独轮机器人的软件部分,独轮机器人要想能够站立不倒,那么必须有个反馈把现在的状态反馈给MCU。这个反馈在该项目中使用的是MPU6050这个模块,所以我们就要把MPU6050的数据读出来。MPU6050是什么东西?MPU-6000(6050)的角速度全格感测范围为±250、±500、±1000与±2000°/sec (dps),可准确追踪快速与慢速动作,并且,用户可程式控制的加速器全格感测范围为±2g、±4g±8g与±16g。产品传输可透过最高至400kHz的IC或最高达20MHz的SPI(MPU-6050没有SPI)。MPU-6000可在不同电压下工作,VDD供电电压介为2.5V±5%、3.0V±5%或3.3V±5%,逻辑接口VVDIO供电为1.8V± 5%(MPU6000仅用VDD)。MPU-6000的包装尺寸4x4x0.9mm(QFN),在业界是革命性的尺寸。其他的特征包含内建的温度感测器、包含在运作环境中仅有±1%变动的振荡器。
    以数字输出6轴或9轴的旋转矩阵、四元数(quaternion)、欧拉角格式(Euler Angle forma)的融合演算数据。 具有131 LSBs/°/sec 敏感度与全格感测范围为±250、±500、±1000与±2000°/sec 的3轴角速度感测器(陀螺仪)。 可程式控制,且程式控制范围为±2g、±4g、±8g和±16g的3轴加速器。 移除加速器与陀螺仪轴间敏感度,降低设定给予的影响与感测器的飘移。 数字运动处理(DMP: Digital Motion Processing)引擎可减少复杂的融合演算数据、感测器同步化、姿势感应等的负荷。 运动处理数据库支持Android、Linux与Windows 内建之运作时间偏差与磁力感测器校正演算技术,免除了客户须另外进行校正的需求。
   读MPU6050的数据有两种方案,一种通过寄存器直接读出原始数据,然后进行数据融合,计算出机器人的倾斜角度和角速度。还有一种是使用MPU6050数字运动处理(DMP: Digital Motion Processing)引擎。我们的项目中使用DMP,官方只给出了DMP在MSP430上的例子,今天就来说说MPU6050的DMP在STM32F7上的移植。
先看下电路图:

从原理上看,使用了PB8,PB9两个引角,所以在配置的时候,我们配置这两个引角

另外我们项目使用到FreeRTOS所以这个也必须选上,还有就是使用串口来给上位机传输调试信息,所以串口也要选上。
时钟配置如下:

FreeRTOS再添加两个任务。堆栈由原来的128改为256.因为MPU6050 DMP库使用的堆栈超过了128.

一切配置完后生成项目。
在生成的项目文件夹里新建Drv文件夹,然后把MPU6050 DMP官方例子里的eMPL文件夹全部复制过来,并添加到项目里。

一切准备工作就绪,下面就来看如何移植到F7里了。其实就一个文件inv_mpu.c把这个文件里所有MPS430的注释到,然后实现I2C的读写函数。
  1. #if defined MOTION_DRIVER_TARGET_STM32F7
  2. <font color="Green">/*#include "msp430.h"
  3. #include "msp430_i2c.h"
  4. #include "msp430_clock.h"
  5. #include "msp430_interrupt.h" */</font>

  6. #define i2c_write   i2cWrite
  7. #define i2c_read    i2cRead
  8. #define delay_ms    delay_ms
  9. #define get_ms      get_ms

  10. <font color="Green">//static int reg_int_cb(struct int_param_s *int_param)
  11. //{
  12. //    /*return msp430_reg_int_cb(int_param->cb, int_param->pin, int_param->lp_exit,
  13. //        int_param->active_low);*/
  14. //                return 0;
  15. //}         
  16. //#define log_i(...)     do {} while (0)
  17. //#define log_e(...)     do {} while (0)</font>
  18. #define log_e    printf
  19. #define log_i    printf
  20. <font color="Green">/* labs is already defined by TI's toolchain. */
  21. /* fabs is for doubles. fabsf is for floats. */</font>
  22. #define fabs        fabsf
  23. #define min(a,b) ((a<b)?a:b)
复制代码
实现硬件相关的几个函数:
  1. void get_ms(unsigned long *time)
  2. {

  3. }
  4. <font color="Green">/**
  5. ****************************************************************************************
  6. * @brief  delay function
  7. * @description
  8. *  This function is to use timer7 to delay for mpu6050 sensor.
  9. *****************************************************************************************
  10. */</font>
  11. __weak void mdelay(uint32_t ms)
  12. {
  13.         extern int delayCount;
  14.         
  15.         delayCount = ms;
  16.         HAL_TIM_Base_Start_IT(&htim7);
  17.         while(delayCount != 0);
  18.         HAL_TIM_Base_Stop_IT(&htim7);
  19. }
  20. <font color="Green">/**
  21. ****************************************************************************************
  22. * @brief  I2C function for write mpu data
  23. * @description
  24. *  This function is implemented using the i2c bus protocol write data to the mpu6050 sensor.
  25. *****************************************************************************************
  26. */</font>
  27. __weak int i2cwrite(uint8_t addr, uint8_t reg, uint8_t len, uint8_t * data)
  28. {
  29.         if(HAL_I2C_Mem_Write(&hi2c1,addr<<1,reg,1,data,len,5000) == HAL_OK)
  30.                 return 0;
  31.         else
  32.                 return 1;
  33. }
  34. <font color="Green">/**
  35. ****************************************************************************************
  36. * @brief  I2C function for read mpu data
  37. * @description
  38. *  This function is to impletmented using i2c bus protocol read data from mpu6050 sensor.
  39. *****************************************************************************************
  40. */</font>
  41. __weak int i2cread(uint8_t addr, uint8_t reg, uint8_t len, uint8_t *data)
  42. {
  43.         if(HAL_I2C_Mem_Read(&hi2c1,addr<<1,reg,1,data,len,5000) == HAL_OK)
  44.                 return 0;
  45.         else
  46.                 return 1;
  47. }
复制代码
OK了,移植完成了,很简单,再增加两个辅助函数,一个是MPU6050 DMP的初始化,一个就是读MPU6050的数据。
  1. <font color="Green">/**
  2. ****************************************************************************************
  3. * @brief  start mpu6050 dmp
  4. * @description
  5. *  This function is used to initialize mpu6050 dmp.
  6. *****************************************************************************************
  7. */</font>
  8. void mpu_start()
  9. {
  10.     int result = mpu_init(NULL);
  11.         while(result != MPU_OK)
  12.         {
  13.                 result = mpu_init(NULL);
  14.         }
  15.     if(result == MPU_OK)
  16.     {
  17.         printf("mpu initialization complete......\n ");                   //mpu_set_sensor
  18.         if(mpu_set_sensors(INV_XYZ_GYRO | INV_XYZ_ACCEL) == MPU_OK)
  19.             printf("mpu_set_sensor complete ......\n");
  20.         else
  21.             printf("mpu_set_sensor come across error ......\n");
  22.         if(mpu_configure_fifo(INV_XYZ_GYRO | INV_XYZ_ACCEL) == MPU_OK)                     //mpu_configure_fifo
  23.             printf("mpu_configure_fifo complete ......\n");
  24.         else
  25.             printf("mpu_configure_fifo come across error ......\n");
  26.         if(mpu_set_sample_rate(DEFAULT_MPU_HZ) == MPU_OK)                     //mpu_set_sample_rate
  27.             printf("mpu_set_sample_rate complete ......\n");
  28.         else
  29.             printf("mpu_set_sample_rate error ......\n");
  30.         if(dmp_load_motion_driver_firmware() == MPU_OK)             //dmp_load_motion_driver_firmvare
  31.             printf("dmp_load_motion_driver_firmware complete ......\n");
  32.         else
  33.             printf("dmp_load_motion_driver_firmware come across error ......\n");
  34.         if(dmp_set_orientation(inv_orientation_matrix_to_scalar(gyro_orientation)) == MPU_OK)           //dmp_set_orientation
  35.             printf("dmp_set_orientation complete ......\n");
  36.         else
  37.             printf("dmp_set_orientation come across error ......\n");
  38.         if(dmp_enable_feature(DMP_FEATURE_6X_LP_QUAT | DMP_FEATURE_TAP |
  39.                               DMP_FEATURE_ANDROID_ORIENT | DMP_FEATURE_SEND_RAW_ACCEL | DMP_FEATURE_SEND_CAL_GYRO |
  40.                               DMP_FEATURE_GYRO_CAL) == MPU_OK)                             //dmp_enable_feature
  41.             printf("dmp_enable_feature complete ......\n");
  42.         else
  43.             printf("dmp_enable_feature come across error ......\n");
  44.         if(dmp_set_fifo_rate(DEFAULT_MPU_HZ) == MPU_OK)             //dmp_set_fifo_rate
  45.             printf("dmp_set_fifo_rate complete ......\n");
  46.         else
  47.             printf("dmp_set_fifo_rate come across error ......\n");
  48.         run_self_test();
  49.         if(mpu_set_dmp_state(1) == MPU_OK)
  50.             printf("mpu_set_dmp_state complete ......\n");
  51.         else
  52.             printf("mpu_set_dmp_state come across error ......\n");
  53.     }
  54. }
复制代码
读数据:
  1. <font color="Green">/**
  2. ****************************************************************************************
  3. * @brief  read data from mpu6050
  4. * @description
  5. *  This function is to use DMP to read data from mpu6050 sensor.
  6. *****************************************************************************************
  7. */</font>
  8. int mpu_read(MPU_Data* data)
  9. {

  10. #define q30          1073741824.0f
  11. #define u8                uint8_t

  12.     float q0=1.0f,q1=0.0f,q2=0.0f,q3=0.0f;

  13.     unsigned long sensor_timestamp;
  14.     short sensors;
  15.     unsigned char more;
  16.     long quat[4];

  17.     dmp_read_fifo(data->gyro, data->accel, quat, &sensor_timestamp, &sensors,&more);
  18.     /* Gyro and accel data are written to the FIFO by the DMP in chip
  19.     * frame and hardware units. This behavior is convenient because it
  20.     * keeps the gyro and accel outputs of dmp_read_fifo and
  21.     * mpu_read_fifo consistent.
  22.     */

  23.     /* Unlike gyro and accel, quaternions are written to the FIFO in
  24.     * the body frame, q30. The orientation is set by the scalar passed
  25.     * to dmp_set_orientation during initialization.
  26.     */
  27.     if (sensors & INV_WXYZ_QUAT )
  28.     {
  29.         q0=quat[0] / q30;
  30.         q1=quat[1] / q30;
  31.         q2=quat[2] / q30;
  32.         q3=quat[3] / q30;
  33.         data->Pitch  = asin(2 * q1 * q3 - 2 * q0* q2)* 57.3; // pitch
  34.         data->Roll = atan2(2 * q2 * q3 + 2 * q0 * q1, -2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll
  35.         data->Yaw = atan2(2*(q1*q2 + q0*q3),q0*q0+q1*q1-q2*q2-q3*q3) * 57.3;
  36.                 return MPU_OK;
  37.     }

  38.     return MPU_ERR;
  39. }
复制代码
在freertos.c文件里添加任务代码:
  1. <font color="Green">/* StartDefaultTask function */</font>
  2. void StartDefaultTask(void const * argument)
  3. {
  4.     <font color="Green">/* USER CODE BEGIN StartDefaultTask */</font>
  5.     <font color="Green">/* Infinite loop */</font>
  6.     for(;;)
  7.     {
  8.         if(mpu_read(&Data) == MPU_OK)
  9.         {
  10.             <font color="Green">//printf("Pitch:%f\tRoll:%f\tYaw:%f\n",Data.Pitch,Data.Roll,Data.Yaw);</font>
  11.             report_to_pc(Data.accel[0],
  12.                          Data.accel[1],
  13.                          Data.accel[2],
  14.                          Data.gyro[0],
  15.                          Data.gyro[1],
  16.                          Data.gyro[2],
  17.                          (short)(Data.Roll*100),
  18.                          (short)(Data.Pitch*100),
  19.                          (short)(Data.Yaw*100));
  20.         }
  21.         osDelay(10);
  22.     }
  23.     <font color="Green">/* USER CODE END StartDefaultTask */</font>
  24. }
复制代码
我这里是反数据上传到匿名四轴的上位机观看状态数据。效果视频




此帖出自stm32/stm8论坛

最新回复

楼主  我那个添加的时候好像无法使用模拟I2C 请问 是怎么回事????寄存器没有设置的问题???????  详情 回复 发表于 2015-11-5 08:39
点赞 关注(1)
 

回复
举报

51

帖子

0

TA的资源

一粒金砂(中级)

沙发
 
这个四轴的软件挺高大上,能否共享学习下,呵呵
此帖出自stm32/stm8论坛
 
 

回复

14

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
学习一下
此帖出自stm32/stm8论坛
 
 

回复

5220

帖子

236

TA的资源

管理员

4
 
哈哈,过来看热闹

视频要是有配音就好了
此帖出自stm32/stm8论坛
加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(中级)

5
 
楼主  我那个添加的时候好像无法使用模拟I2C 请问 是怎么回事????寄存器没有设置的问题???????
此帖出自stm32/stm8论坛

点评

这个例子是硬件I2C,没有模拟I2C。模拟I2C应该是自己用IO口来处理,基本上和这个没有多大关系了。 现在STM32的硬件I2C挺好用的,所以能使用硬件就使用硬件。  详情 回复 发表于 2015-11-5 10:45
 
 
 

回复

606

帖子

20

TA的资源

一粒金砂(高级)

6
 
天天好心情亲 发表于 2015-11-5 08:39
楼主  我那个添加的时候好像无法使用模拟I2C 请问 是怎么回事????寄存器没有设置的问题???????

这个例子是硬件I2C,没有模拟I2C。模拟I2C应该是自己用IO口来处理,基本上和这个没有多大关系了。
现在STM32的硬件I2C挺好用的,所以能使用硬件就使用硬件。
此帖出自stm32/stm8论坛
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表