使用MPU6050传感器获取加速度

1. MPU6050传感器简介

      智能手环需要实时检测人体姿态,如加速度和角速度等。本项目使用MPU6050传感器来检测人体姿态。MPU6050传感器模块是一种六轴传感器模块,采用InvenSense 公司的MPU6050 作为主芯片,能同时检测三轴加速度、三轴陀螺仪(三轴角速度)的运动数据以及温度数据。

      利用MPU6050 芯片内部的DMP 模块(Digital Motion Processor 数字运动处理器),可对传感器数据进行滤波、融合处理,它直接通过I2C 接口向主控器输出姿态解算后的姿态数据,降低主控器的运算量。其姿态解算频率最高可达200Hz,非常适合智能手环的姿态检测。

image.png

 图1  DMP模块 

1.1 引脚功能说明

      DMP模块引出的8 个引脚功能说明,如下表所示;

序号

引脚名称

说明

1

VCC

3.3/5V 电源输入

2

GND

地线

3

SCL

I2C 从时钟信号线SCL (模块上已接上拉电阻)

4

SDA

I2C   从数据信号线SDA (模块上已接上拉电阻)

5

XDA

I2C 主串行数据信号线,用于外接传感器(模块上已接上拉电阻)

6

XCL

I2C   主串行时钟信号线,用于外接传感器(模块上已接上拉电阻)

7

AD0

从机地址设置引脚

 接地或悬空时, 地址为: 0x68

 接VCC 时,地址为:0x69

8

INT

中断输出引脚

      其中的SDA/SCL、XDA/XCL 通讯引脚分别为两组I2C 信号线。当模块与外部主机通讯时,使用SDA/SCL,如与STM32 芯片通讯;而XDA/XCL 则用于MPU6050 芯片与其它I2C传感器通讯时使用,例如使用它与磁场传感器连接,MPU6050 模块可以把从主机SDA/SCL 接收的数据或命令通过XDA/XCL 引脚转发到磁场传感器中。

      但实际上这种功能控制麻烦且效率低,一般会直接把磁场传感器之类的I2C传感器直接与MPU6050 挂载在同一条总线上(即都连接到SDA/SCL),使用主机直接控制。

image.png

图2  主机控制

1.2 MPU6050 模块的特性参数

image.png

图3  MPU6050 模块参数

      从表中还可了解到传感器的加速度及陀螺仪的采样频率分别为1000Hz 及8000Hz,它们是指加速度及角速度数据的采样频率,我们可以使用STM32 控制器把这些数据读取出来然后进行姿态融合解算,以求出传感器当前的姿态(即求出偏航角、横滚角、俯仰角)。而如果使用传感器内部的DMP 单元进行解算,它可以直接对采样得到的加速度及角速度进行姿态解算,解算得到的结果再输出给STM32 控制器,即STM32 无需自己计算,可直接获取偏航角、横滚角及俯仰角,该DMP 每秒可输出200 次姿态数据。

1.3 硬件设计

      用杜邦线把STM32 开发板与该MPU6050 模块连接起来,如下图所示;

image.png

 图4  模块连接 

      详细的管脚连接,如下表所示;

序号

引脚名称

与开发板连接

1

VCC

接3.3V或5V

2

GND

GND

3

SCL

PB6

4

SDA

PB7

5

AD0

悬空或接地

6

INT

悬空

 2. 软件实现

      1)驱动移植。将提供好的硬件驱动程序”mpu6050.c”、”mpu6050.h”、”bsp_i 2c.c”、”bsp_i2c.h”文件移植到工程中。

image.png

图5  mpu6050

      2)硬件初始化。初始化硬件主要包括三部分,LCD初始化、I2C总线初始化和MPU6050传感器初始化。

//LCD 初始化
ILI9341_Init ();        
//I2C初始化
i2c_GPIO_Config();
//MPU6050初始化
MPU6050_Init();

       LCD初始化调用函数ILI9341_Init (),该函数前面已经讲解,这里不在叙述。I2C总线初始化调用函数i2c_GPIO_Config(),该函数位于I2C驱动文件bsp_i2c.c中,需要注意的是使用该函数不要忘记添加头文件,如下所示;

#include "bsp_i2c.h"      i2c_GPIO_Config()函数源码如下,该函数主要功能是配置I2C总线管脚。

void i2c_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_I2C_PORT, ENABLE);    /* 打开GPIO时钟 */

    GPIO_InitStructure.GPIO_Pin = I2C_SCL_PIN | I2C_SDA_PIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;      /* 开漏输出 */
    GPIO_Init(GPIO_PORT_I2C, &GPIO_InitStructure);

    /* 给一个停止信号, 复位I2C总线上的所有设备到待机模式 */
    i2c_Stop();
}

       MPU6050_Init()函数位于MPU6050.c文件中,使用时需要添加头文件“MPU6050.h”,其源码如下所示;

void MPU6050_Init(void)
{
  int i=0,j=0;
  //在初始化之前要延时一段时间,若没有延时,则断电后再上电数据可能会出错
  for(i=0;i<1000;i++)
  {
    for(j=0;j<1000;j++)
    {
      ;
    }
  }
    MPU6050_WriteReg(MPU6050_RA_PWR_MGMT_10x00);        
    MPU6050_WriteReg(MPU6050_RA_SMPLRT_DIV , 0x07);        
    MPU6050_WriteReg(MPU6050_RA_CONFIG , 0x06);           
    MPU6050_WriteReg(MPU6050_RA_ACCEL_CONFIG , 0x00);      
    MPU6050_WriteReg(MPU6050_RA_GYRO_CONFIG0x18);     
}

      用于初始化MPU6050,如设置陀螺仪采样率、设置低通滤波器、配置加速度传感器、设置陀螺仪自检及测量范围等。

      3)硬件初始化完成以后,读取MPU6050的ID。使用函数MPU6050ReadID(),函数源码如下所示;

uint8_t MPU6050ReadID(void)
{
    unsigned char Re = 0;
    MPU6050_ReadData(MPU6050_RA_WHO_AM_I,&Re,1);    //读器件地址
    if(Re != 0x68)
    {
//        printf("MPU6050 dectected error!\r\n检测不到MPU6050模块。");
        return 0;
    }
    else
    {
//        printf("MPU6050 ID = %d\r\n",Re);
        return 1;
    }
        
}

      若返回1,则表示读取成功。读取成功以后即可进行下一步操作-读取加速度、角速度及温度的原始值。

      4)获取加速度、角速度和温度的原始值

      ① 获取加速度值调用MPU6050ReadAcc()函数,函数原型如下所示;

void MPU6050ReadAcc(short *accData)
{
    u8 buf[6];
    MPU6050_ReadData(MPU6050_ACC_OUT, buf, 6);
    accData[0] = (buf[0] << 8) | buf[1];
    accData[1] = (buf[2] << 8) | buf[3];
    accData[2] = (buf[4] << 8) | buf[5];
}

      此处,需要定义一个short类型的数组变量,用来接收加速度值。 

      ② 获取角速度值调用MPU6050ReadGyro()函数,函数原型如下所示;

void MPU6050ReadGyro(short *gyroData)
{
    u8 buf[6];
    MPU6050_ReadData(MPU6050_GYRO_OUT,buf,6);
    gyroData[0] = (buf[0] << 8) | buf[1];
    gyroData[1] = (buf[2] << 8) | buf[3];
    gyroData[2] = (buf[4] << 8) | buf[5];
}

      此处,同样需要定义一个short类型的数组变量,用来接收角速度值。 

      ③ 温度获取使用MPU6050_ReturnTemp()函数,函数原型如下所示;

void MPU6050_ReturnTemp(short*Temperature)
{
    short temp3;
    u8 buf[2];
    
    MPU6050_ReadData(MPU6050_RA_TEMP_OUT_H,buf,2);     //读取温度值
     temp3= (buf[0] << 8) | buf[1];
    *Temperature=(((double) (temp3 + 13200)) / 280)-13;
}

      4)主函数代码,如下所示;

int main(void)
{
short Accel[3];
short Gyro[3];
short Temp;
char temp_num[4];

//LCD 初始化
ILI9341_Init ();        
//I2C初始化
i2c_GPIO_Config();
//MPU6050初始化
MPU6050_Init();
//检测MPU6050
if (MPU6050ReadID() == 1)
{    
    while(1)
    {
        MPU6050ReadAcc(Accel);    
        int2str(Accel[0],temp_num);
        ILI9341_DispString_EN ( 2020"Accel->x=", macBLUE2, macRED );
          ILI9341_DispString_EN ( 9020, temp_num, macBLUE2, macRED );
            
        int2str(Accel[1],temp_num);
        ILI9341_DispString_EN ( 2040"Accel->y=", macBLUE2, macRED );
        ILI9341_DispString_EN ( 9040, temp_num, macBLUE2, macRED );
        int2str(Accel[2],temp_num);
         ILI9341_DispString_EN ( 2060"Accel->z=", macBLUE2, macRED );
         ILI9341_DispString_EN ( 9060, temp_num, macBLUE2, macRED );
            
        MPU6050ReadGyro(Gyro);
        int2str(Gyro[0],temp_num);
        ILI9341_DispString_EN ( 20100"Gyro->x=", macBLUE2, macRED );
        ILI9341_DispString_EN ( 80100, temp_num, macBLUE2, macRED );
            
        int2str(Gyro[1],temp_num);
         ILI9341_DispString_EN ( 20120"Gyro->y=", macBLUE2, macRED );
        ILI9341_DispString_EN ( 80120, temp_num, macBLUE2, macRED );
                
        int2str(Gyro[2],temp_num);
        ILI9341_DispString_EN ( 20140"Gyro->z=", macBLUE2, macRED );
        ILI9341_DispString_EN ( 80140, temp_num, macBLUE2, macRED );
            
        MPU6050_ReturnTemp(&Temp);
        int2str(Temp,temp_num);
        ILI9341_DispString_EN ( 20180"Temp=", macBLUE2, macRED );
        ILI9341_DispString_EN ( 60180, temp_num, macBLUE2, macRED );
              
        Delay(0x15FFFF);
    }   
}
else
    while(1);    
}

      主函数是对获取到数据进行在加工,将数值转换成字符,并打印输出到LCD中。LCD显示屏显示的数据是寄存器的原始数据。这些原始数据需要进一步进行换算才能得到我们角速度和加速度,关于换算方法,会在后面进行讲解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序老猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值