MPU6050三轴传感器性能详解

1.背景:

        MPU6050 是由 InvenSense(现为 TDK 旗下公司)生产的一款集成了三轴加速度计和三轴陀螺仪的微机电系统(MEMS)传感器。它可以测量物体在三个轴上的加速度和旋转角速度,被广泛应用于消费电子、工业控制、无人机、智能设备等领域。

1.2.工作原理

MPU6050 内部集成了:

  1. 三轴加速度计:能够测量X、Y、Z轴的加速度(以g为单位,1g ≈ 9.81 m/s²)。加速度计的工作原理基于微机电系统技术,通过微小的悬臂梁结构感知加速度引起的位移,然后转换为电信号输出。

  2. 三轴陀螺仪:能够测量X、Y、Z轴的角速度(以°/s为单位)。陀螺仪使用科里奥利效应,通过检测旋转时微小质量块的偏移来测量角速度。

        MPU6050 通过 I2C 或 SPI 接口与主机通信,传输传感器数据和配置信息。它还包括一个数字运动处理单元(DMP),可以进行姿态估计和运动检测。内部的数字低通滤波器(DLPF)能够减少噪声影响,提高数据稳定性。

1.3.规格

以下是 MPU6050 的一些关键规格:

  • 加速度计量程:±2g、±4g、±8g、±16g(可配置)
  • 陀螺仪量程:±250°/s、±500°/s、±1000°/s、±2000°/s(可配置)
  • 工作电压:2.375V – 3.46V
  • I2C 地址:0x68 或 0x69(可选)
  • 采样率:最高 1kHz
  • 低功耗特性:具备睡眠模式和低功耗传感器读取功能
  • 尺寸:4x4x0.9mm
  • 功耗:在典型配置下约为 3.9 mA
  • 1.4.应用

    MPU6050 在多种领域中有广泛应用,包括但不限于:

    1. 消费电子:智能手机、平板电脑中的屏幕旋转检测和稳定功能。
    2. 无人机:姿态控制、飞行稳定和导航。
    3. 可穿戴设备:运动追踪器、智能手表的活动监测和姿态检测。
    4. 虚拟现实(VR)和增强现实(AR)设备:用于头部和手部跟踪。
    5. 机器人和自动化控制:用于姿态估计和平衡控制。
    6. 汽车电子:用于车内安全系统、导航和防盗报警系统。

            MPU6050 的高集成度和多功能性使其成为各种应用中的理想选择,尤其是在需要精确运动检测和姿态估计的场景中。

    2.pin to pin(引脚说明):

            这两个电路都是基于STM32F7系列的微控制器,它们通过不同的接口与外部设备相连。

  • 左侧电路:

  • MPU-6000微控制器通过CLKIN引脚接收外部时钟信号,同时通过SDI/SCK引脚发送数据。
  • AUX_DA引脚连接到AUX_CL上,用于提供额外的数据通道。
  • VDD引脚连接到C1和C2电容器上,用于稳定电源电压。
  • GND引脚接地,确保电路的稳定运行。
  • FSYNC引脚连接到INT上,用于同步外部设备的数据流。
  • 右侧电路:

  • MPU-6050微控制器同样通过CLKIN引脚接收外部时钟信号,并通过SDI/SCK引脚发送数据。
  • AUX_DA引脚也连接到AUX_CL上,提供额外的数据通道。
  • VDD引脚同样连接到C1和C2电容器上,确保电源电压稳定。
  • GND引脚接地,保证电路稳定运行。
  • C4电容器和VLOGIC引脚用于滤波和逻辑处理,提高电路的性能和稳定性。
  • FSYNC引脚连接到INT上,实现数据的同步传输。
  •         这两个电路的主要区别在于它们的功能和连接方式略有不同。左侧电路主要用于数据传输和同步控制,而右侧电路则更加注重逻辑处理和滤波功能。尽管如此,它们都采用了相同的STM32F7系列微控制器作为核心处理器,并共享了相似的接口和功能设计。这种设计使得这两个电路可以在不同的应用场景下发挥各自的优势,满足不同的需求。

    3.陀螺仪特性:

    3.1.特性:

  • 数字输出的X、Y和Z轴角速度传感器(陀螺仪),用户可编程的满量程范围为±250、±500、±1000和±2000°/秒
  • 连接到FSYNC引脚的外部同步信号支持图像、视频和GPS同步
  • 集成的16位ADCs能够同时采样陀螺仪
  • 增强的偏差和灵敏度温度稳定性减少了用户校准的需求
  • 改善了低频噪声性能
  • 数字可编程低通滤波器
  • 陀螺仪工作电流:3.6mA
  • 待机电流:5µA
  • 工厂校准的灵敏度比例因子
  • 用户自检
  • 3.2. 加速度计特性

    MPU-60X0中的三轴MEMS加速度计包括以下特性:

  • 数字输出的三轴加速度计,可编程的满量程范围为±2g、±4g、±8g和±16g
  • 集成的16位ADCs能够在不需要外部多路复用器的情况下同时采样加速度计
  • 加速度计正常工作电流:500µA
  • 低功耗加速度计模式电流:1.25Hz时10µA,5Hz时20µA,20Hz时60µA,40Hz时110µA
  • 方向检测和信号传递
  • 敲击检测
  • 用户可编程中断
  • 高G中断
  • 用户自检
  •  3.3.自检代码示例:

    (注意这里的你的i2c地址需要根据自己的设计修改)

    #include <Wire.h>
    
    #define MPU6050_ADDR 0x68 // I2C地址
    
    int16_t ax, ay, az; // 加速度计数据
    int16_t gx, gy, gz; // 陀螺仪数据
    
    void setup() {
      Serial.begin(9600);
      Wire.begin();
      Wire.setClock(400000); // 设置I2C时钟频率为400kHz
    
      // 初始化MPU6050
      Wire.beginTransmission(MPU6050_ADDR);
      Wire.write(0x6B); // PWR_MGMT_1寄存器地址
      Wire.write(0);    // 复位所有传感器
      Wire.endTransmission(true);
      delay(200);
    
      Wire.beginTransmission(MPU6050_ADDR);
      Wire.write(0x6B); // PWR_MGMT_1寄存器地址
      Wire.write(0x00); // 唤醒所有传感器
      Wire.endTransmission(true);
      delay(200);
    
      Wire.beginTransmission(MPU6050_ADDR);
      Wire.write(0x1B); // GYRO_CONFIG寄存器地址
      Wire.write(0x18); // 设置陀螺仪量程为±2000°/sec
      Wire.endTransmission(true);
      delay(200);
    
      Wire.beginTransmission(MPU6050_ADDR);
      Wire.write(0x1C); // ACCEL_CONFIG寄存器地址
      Wire.write(0x10); // 设置加速度计量程为±2g
      Wire.endTransmission(true);
      delay(200);
    }
    
    void loop() {
      // 读取加速度计数据
      Wire.beginTransmission(MPU6050_ADDR);
      Wire.write(0x3B); // ACCEL_XOUT_H寄存器地址
      Wire.endTransmission(false);
      Wire.requestFrom(MPU6050_ADDR, 14, true);
      ax = Wire.read() << 8 | Wire.read();
      ay = Wire.read() << 8 | Wire.read();
      az = Wire.read() << 8 | Wire.read();
      gx = Wire.read() << 8 | Wire.read();
      gy = Wire.read() << 8 | Wire.read();
      gz = Wire.read() << 8 | Wire.read();
    
      // 输出加速度计和陀螺仪数据
      Serial.print("Accelerometer: X=");
      Serial.print(ax);
      Serial.print(" Y=");
      Serial.print(ay);
      Serial.print(" Z=");
      Serial.println(az);
    
      Serial.print("Gyroscope: X=");
      Serial.print(gx);
      Serial.print(" Y=");
      Serial.print(gy);
      Serial.print(" Z=");
      Serial.println(gz);
    
      delay(1000); // 每秒更新一次数据
    }
    

    4.初始化运行示例:

    #include "main.h"
    #include "i2c.h"
    
    #define MPU6050_ADDR 0x68 << 1      // I2C address of MPU6050 (shifted for HAL)
    #define MPU6050_WHO_AM_I 0x75       // WHO_AM_I register address
    #define MPU6050_PWR_MGMT_1 0x6B     // Power management register
    #define MPU6050_ACCEL_XOUT_H 0x3B   // Acceleration data register
    #define MPU6050_GYRO_XOUT_H 0x43    // Gyroscope data register
    #define MPU6050_ACCEL_CONFIG 0x1C   // Accelerometer configuration register
    #define MPU6050_GYRO_CONFIG 0x1B    // Gyroscope configuration register
    #define MPU6050_CONFIG 0x1A         // Configuration register (DLPF)
    
    // Accelerometer sensitivity scale factors
    #define AFS_2G 16384.0
    #define AFS_4G 8192.0
    #define AFS_8G 4096.0
    #define AFS_16G 2048.0
    
    // Gyroscope sensitivity scale factors
    #define GFS_250DPS 131.0
    #define GFS_500DPS 65.5
    #define GFS_1000DPS 32.8
    #define GFS_2000DPS 16.4
    
    void MPU6050_Init(uint8_t accelRange, uint8_t gyroRange, uint8_t dlpf);
    void MPU6050_ReadAccel(int16_t* pData);
    void MPU6050_ReadGyro(int16_t* pData);
    float MPU6050_ConvertAccel(int16_t rawValue, uint8_t accelRange);
    float MPU6050_ConvertGyro(int16_t rawValue, uint8_t gyroRange);
    
    I2C_HandleTypeDef hi2c1; // Assume hi2c1 is initialized elsewhere
    
    int main(void) {
        // System initialization code
        HAL_Init();
        // Initialize the I2C peripheral
        MX_I2C1_Init();
        // Initialize the MPU6050
        MPU6050_Init(0x00, 0x00, 0x03); // 2G accel range, 250dps gyro range, DLPF 42Hz
    
        int16_t accelData[3];
        int16_t gyroData[3];
    
        while (1) {
            // Read accelerometer and gyroscope data
            MPU6050_ReadAccel(accelData);
            MPU6050_ReadGyro(gyroData);
    
            // Convert raw data to meaningful values
            float accelX = MPU6050_ConvertAccel(accelData[0], 0x00);
            float accelY = MPU6050_ConvertAccel(accelData[1], 0x00);
            float accelZ = MPU6050_ConvertAccel(accelData[2], 0x00);
    
            float gyroX = MPU6050_ConvertGyro(gyroData[0], 0x00);
            float gyroY = MPU6050_ConvertGyro(gyroData[1], 0x00);
            float gyroZ = MPU6050_ConvertGyro(gyroData[2], 0x00);
    
            // Use the converted data
        }
    }
    
    void MPU6050_Init(uint8_t accelRange, uint8_t gyroRange, uint8_t dlpf) {
        uint8_t check, data;
    
        // Check MPU6050 WHO_AM_I register
        HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, MPU6050_WHO_AM_I, 1, &check, 1, HAL_MAX_DELAY);
        if (check == 0x68) {
            // Wake up the MPU6050 by writing to PWR_MGMT_1 register
            data = 0x00;
            HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR, MPU6050_PWR_MGMT_1, 1, &data, 1, HAL_MAX_DELAY);
    
            // Set accelerometer range
            HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, MPU6050_ACCEL_CONFIG, 1, &data, 1, HAL_MAX_DELAY);
            data = (data & 0xE7) | (accelRange << 3);
            HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR, MPU6050_ACCEL_CONFIG, 1, &data, 1, HAL_MAX_DELAY);
    
            // Set gyroscope range
            HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, MPU6050_GYRO_CONFIG, 1, &data, 1, HAL_MAX_DELAY);
            data = (data & 0xE7) | (gyroRange << 3);
            HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR, MPU6050_GYRO_CONFIG, 1, &data, 1, HAL_MAX_DELAY);
    
            // Set DLPF (Digital Low Pass Filter)
            HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, MPU6050_CONFIG, 1, &data, 1, HAL_MAX_DELAY);
            data = (data & 0xF8) | dlpf;
            HAL_I2C_Mem_Write(&hi2c1, MPU6050_ADDR, MPU6050_CONFIG, 1, &data, 1, HAL_MAX_DELAY);
        }
    }
    
    void MPU6050_ReadAccel(int16_t* pData) {
        uint8_t data[6];
        HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, MPU6050_ACCEL_XOUT_H, 1, data, 6, HAL_MAX_DELAY);
        pData[0] = (int16_t)(data[0] << 8 | data[1]);
        pData[1] = (int16_t)(data[2] << 8 | data[3]);
        pData[2] = (int16_t)(data[4] << 8 | data[5]);
    }
    
    void MPU6050_ReadGyro(int16_t* pData) {
        uint8_t data[6];
        HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, MPU6050_GYRO_XOUT_H, 1, data, 6, HAL_MAX_DELAY);
        pData[0] = (int16_t)(data[0] << 8 | data[1]);
        pData[1] = (int16_t)(data[2] << 8 | data[3]);
        pData[2] = (int16_t)(data[4] << 8 | data[5]);
    }
    
    float MPU6050_ConvertAccel(int16_t rawValue, uint8_t accelRange) {
        float scaleFactor;
    
        switch (accelRange) {
            case 0x00: scaleFactor = AFS_2G; break;
            case 0x01: scaleFactor = AFS_4G; break;
            case 0x02: scaleFactor = AFS_8G; break;
            case 0x03: scaleFactor = AFS_16G; break;
            default: scaleFactor = AFS_2G; break;
        }
    
        return rawValue / scaleFactor;
    }
    
    float MPU6050_ConvertGyro(int16_t rawValue, uint8_t gyroRange) {
        float scaleFactor;
    
        switch (gyroRange) {
            case 0x00: scaleFactor = GFS_250DPS; break;
            case 0x01: scaleFactor = GFS_500DPS; break;
            case 0x02: scaleFactor = GFS_1000DPS; break;
            case 0x03: scaleFactor = GFS_2000DPS; break;
            default: scaleFactor = GFS_250DPS; break;
        }
    
        return rawValue / scaleFactor;
    }

    作者:小但同学

    物联沃分享整理
    物联沃-IOTWORD物联网 » MPU6050三轴传感器性能详解

    发表回复