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;
}

猜你喜欢

转载自blog.csdn.net/m0_74962389/article/details/140665404