微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > (五)麒麟座读取MPU6050

(五)麒麟座读取MPU6050

时间:10-02 整理:3721RD 点击:

平衡车的陀螺仪部件,我使用的MPU6050模块。左侧那个洞洞板上,上方红色的是电机驱动。中间蓝色的小模块就是MPU6050。连线如图,可能看不清,下面会详细介绍。


查看麒麟座开发板的原理图可以看到,有一些没有用到的引脚。之所以不占用板子上其他资源的IO口,主要是考虑到,小车跑起来之后 还要用板子上的传感器采集信息。所以只能用剩下的引脚东拼西凑了。


决定用PB3引脚做IIC通讯的SCK时钟线,PB4引脚做SDA数据线。右侧 PA8-PA11为定时器1的4个通道,后面可以用来做PWM输出作为直流电机驱动的输入信号。或者给电机编码器使用。左侧的PC0-PC3被1602占用了。可以说如果不放弃板子原本就带的一些传感器的话,可用的引脚资源非常少 - -


IIC通讯采用软件模拟的方式,下面是IIC底层驱动程序。

  1. <blockquote>/**************************êμ??oˉêy********************************************

复制代码


MPU6050初始化,数据读取。

  1. /**************************êμ??oˉêy********************************************
  2. 将新的ADC数据更新到FIFO数组,做滤波处理
  3. *******************************************************************************/

  4. void  MPU6050_newValues(int16_t ax,int16_t ay,int16_t az,int16_t gx,int16_t gy,int16_t gz)
  5. {
  6. unsigned char i ;
  7. int32_t sum=0;
  8. for(i=1;i<10;i++){        //FIFO 2ù×÷
  9. MPU6050_FIFO[0][i-1]=MPU6050_FIFO[0][i];
  10. MPU6050_FIFO[1][i-1]=MPU6050_FIFO[1][i];
  11. MPU6050_FIFO[2][i-1]=MPU6050_FIFO[2][i];
  12. MPU6050_FIFO[3][i-1]=MPU6050_FIFO[3][i];
  13. MPU6050_FIFO[4][i-1]=MPU6050_FIFO[4][i];
  14. MPU6050_FIFO[5][i-1]=MPU6050_FIFO[5][i];
  15. }
  16. MPU6050_FIFO[0][9]=ax;//??D?μ?êy?Y·???μ? êy?Yμ?×?oó??
  17. MPU6050_FIFO[1][9]=ay;
  18. MPU6050_FIFO[2][9]=az;
  19. MPU6050_FIFO[3][9]=gx;
  20. MPU6050_FIFO[4][9]=gy;
  21. MPU6050_FIFO[5][9]=gz;

  22. sum=0;
  23. for(i=0;i<10;i++){        //?óμ±?°êy×éμ?o?£??ùè????ù?μ
  24.    sum+=MPU6050_FIFO[0][i];
  25. }
  26. MPU6050_FIFO[0][10]=sum/10;

  27. sum=0;
  28. for(i=0;i<10;i++){
  29.    sum+=MPU6050_FIFO[1][i];
  30. }
  31. MPU6050_FIFO[1][10]=sum/10;

  32. sum=0;
  33. for(i=0;i<10;i++){
  34.    sum+=MPU6050_FIFO[2][i];
  35. }
  36. MPU6050_FIFO[2][10]=sum/10;

  37. sum=0;
  38. for(i=0;i<10;i++){
  39.    sum+=MPU6050_FIFO[3][i];
  40. }
  41. MPU6050_FIFO[3][10]=sum/10;

  42. sum=0;
  43. for(i=0;i<10;i++){
  44.    sum+=MPU6050_FIFO[4][i];
  45. }
  46. MPU6050_FIFO[4][10]=sum/10;

  47. sum=0;
  48. for(i=0;i<10;i++){
  49.    sum+=MPU6050_FIFO[5][i];
  50. }
  51. MPU6050_FIFO[5][10]=sum/10;
  52. }

  53. /**************************êμ??oˉêy********************************************
  54. 设置MPU6050的时钟源
  55. * CLK_SEL | Clock Source
  56. * --------+--------------------------------------
  57. * 0       | Internal oscillator
  58. * 1       | PLL with X Gyro reference
  59. * 2       | PLL with Y Gyro reference
  60. * 3       | PLL with Z Gyro reference
  61. * 4       | PLL with external 32.768kHz reference
  62. * 5       | PLL with external 19.2MHz reference
  63. * 6       | Reserved
  64. * 7       | Stops the clock and keeps the timing generator in reset
  65. *******************************************************************************/
  66. void MPU6050_setClockSource(uint8_t source){
  67.     IICwriteBits(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_CLKSEL_BIT, MPU6050_PWR1_CLKSEL_LENGTH, source);

  68. }

  69. /** Set full-scale gyroscope range.
  70. * @param range New full-scale gyroscope range value
  71. * [url=home.php?mod=space&uid=1466806]@SEE[/url] getFullScaleRange()
  72. * @see MPU6050_GYRO_FS_250
  73. * @see MPU6050_RA_GYRO_CONFIG
  74. * @see MPU6050_GCONFIG_FS_SEL_BIT
  75. * @see MPU6050_GCONFIG_FS_SEL_LENGTH
  76. */
  77. void MPU6050_setFullScaleGyroRange(uint8_t range) {
  78.     IICwriteBits(devAddr, MPU6050_RA_GYRO_CONFIG, MPU6050_GCONFIG_FS_SEL_BIT, MPU6050_GCONFIG_FS_SEL_LENGTH, range);
  79. }

  80. /**************************êμ??oˉêy********************************************
  81. 设置加速度计的最大量程
  82. *******************************************************************************/
  83. void MPU6050_setFullScaleAccelRange(uint8_t range) {
  84.     IICwriteBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range);
  85. }

  86. /**************************êμ??oˉêy********************************************
  87. 设置是否进入睡眠模式
  88. *******************************************************************************/
  89. void MPU6050_setSleepEnabled(uint8_t enabled) {
  90.     IICwriteBit(devAddr, MPU6050_RA_PWR_MGMT_1, MPU6050_PWR1_SLEEP_BIT, enabled);
  91. }

  92. /**************************êμ??oˉêy********************************************
  93. 读取芯片ID
  94. *******************************************************************************/
  95. uint8_t MPU6050_getDeviceID(void) {

  96.     IICreadBytes(devAddr, MPU6050_RA_WHO_AM_I, 1, buffer);
  97.     return buffer[0];
  98. }

  99. /**************************êμ??oˉêy********************************************
  100. 检测是否已连接
  101. *******************************************************************************/
  102. uint8_t MPU6050_testConnection(void) {
  103.    if(MPU6050_getDeviceID() == 0x68)  //0b01101000;
  104.    return 1;
  105.            else return 0;
  106. }

  107. /**************************êμ??oˉêy********************************************
  108. 设置MPU6050是否做AUX IIC主机
  109. *******************************************************************************/
  110. void MPU6050_setI2CMasterModeEnabled(uint8_t enabled) {
  111.     IICwriteBit(devAddr, MPU6050_RA_USER_CTRL, MPU6050_USERCTRL_I2C_MST_EN_BIT, enabled);
  112. }

  113. /**************************êμ??oˉêy********************************************

  114. *******************************************************************************/
  115. void MPU6050_setI2CBypassEnabled(uint8_t enabled) {
  116.     IICwriteBit(devAddr, MPU6050_RA_INT_PIN_CFG, MPU6050_INTCFG_I2C_BYPASS_EN_BIT, enabled);
  117. }

  118. /**************************êμ??oˉêy********************************************
  119. 初始化
  120. *******************************************************************************/
  121. void MPU6050_initialize(void) {
  122.     MPU6050_setClockSource(MPU6050_CLOCK_PLL_YGYRO); //éè??ê±?ó
  123.     MPU6050_setFullScaleGyroRange(MPU6050_GYRO_FS_2000);//íó?Yò?×?′óá?3ì +-1000?è????
  124.     MPU6050_setFullScaleAccelRange(MPU6050_ACCEL_FS_2);        //?ó?ù?è?è×?′óá?3ì +-2G
  125.     MPU6050_setSleepEnabled(0); //??è?1¤×÷×′ì?
  126.          MPU6050_setI2CMasterModeEnabled(0);         //2?è?MPU6050 ????AUXI2C
  127.          MPU6050_setI2CBypassEnabled(0);         //?÷?????÷μ?I2Có?        MPU6050μ?AUXI2C        ?±í¨?£?????÷?éò??±?ó·??êHMC5883L
  128. }

复制代码

获取姿态信息

  1. /**************************************************************************
  2. <span style="background-color: rgb(255, 255, 255);">获取姿态信息</span>
  3. **************************************************************************/
  4. void Get_Angle(u8 way)
  5. {
  6.             float Accel_Y,Accel_X,Accel_Z,Gyro_Y,Gyro_Z;
  7.                    Temperature=Read_Temperature();      //===?áè?MPU6050?ú?????è′??D?÷êy?Y£??ü??±íê??÷°????è?£
  8.             if(way==1)                           //===DMPμ??áè??úêy?Y2é?ˉ?D??ìáD?μ?ê±oò£?????×??-ê±Dòòa?ó
  9.                         {        
  10.                                         Read_DMP();                      //===?áè??ó?ù?è?¢???ù?è?¢????
  11.                                         Angle_Balance=Pitch;             //===?üD???oa????
  12.                                         Gyro_Balance=gyro[1];            //===?üD???oa???ù?è
  13.                                         Gyro_Turn=gyro[2];               //===?üD?×a?ò???ù?è
  14.                                   Acceleration_Z=accel[2];         //===?üD?Z?á?ó?ù?è??
  15.                         }                        
  16.       else
  17.       {
  18.                         Gyro_Y=(I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_YOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_YOUT_L);    //?áè?Y?áíó?Yò?
  19.                         Gyro_Z=(I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_ZOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_GYRO_ZOUT_L);    //?áè?Z?áíó?Yò?
  20.                   Accel_X=(I2C_ReadOneByte(devAddr,MPU6050_RA_ACCEL_XOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_ACCEL_XOUT_L); //?áè?X?á?ó?ù?è??
  21.                   Accel_Z=(I2C_ReadOneByte(devAddr,MPU6050_RA_ACCEL_ZOUT_H)<<8)+I2C_ReadOneByte(devAddr,MPU6050_RA_ACCEL_ZOUT_L); //?áè?Z?á?ó?ù?è??
  22.                   if(Gyro_Y>32768)  Gyro_Y-=65536;                       //êy?YààDí×a??  ò2?éí¨1yshort????ààDí×a??
  23.                         if(Gyro_Z>32768)  Gyro_Z-=65536;                       //êy?YààDí×a??
  24.                   if(Accel_X>32768) Accel_X-=65536;                      //êy?YààDí×a??
  25.                   if(Accel_Z>32768) Accel_Z-=65536;                      //êy?YààDí×a??
  26.                         Gyro_Balance=-Gyro_Y;                                  //?üD???oa???ù?è
  27.                    Accel_Y=atan2(Accel_X,Accel_Z)*180/PI;                 //????????        
  28.                   Gyro_Y=Gyro_Y/16.4;                                    //íó?Yò?á?3ì×a??        
  29.       if(Way_Angle==2)                          Kalman_Filter(Accel_Y,-Gyro_Y);//?¨???ü??2¨        
  30.                         else if(Way_Angle==3)   Yijielvbo(Accel_Y,-Gyro_Y);    //?¥21??2¨
  31.             Angle_Balance=angle;                                   //?üD???oa????
  32.                         Gyro_Turn=Gyro_Z;                                      //?üD?×a?ò???ù?è
  33.                         Acceleration_Z=Accel_Z;                                //===?üD?Z?á?ó?ù?è??        
  34.                 }
  35. }

复制代码


通过IO引脚模拟I2C程序,读取MPU6050的ADC转换结果。进行姿态解算。麒麟座的PA9 PA10两个IO引脚虽然作为USRAT1串口,可以打印姿态到电脑上,但是由于资源有限,这两个引脚打算作为PWM输出信号给直流电机驱动板。暂时把姿态信息显示在1602液晶屏上看看效果。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top