1.背景:
MPU6050 是由 InvenSense(现为 TDK 旗下公司)生产的一款集成了三轴加速度计和三轴陀螺仪的微机电系统(MEMS)传感器。它可以测量物体在三个轴上的加速度和旋转角速度,被广泛应用于消费电子、工业控制、无人机、智能设备等领域。
1.2.工作原理
MPU6050 内部集成了:
-
三轴加速度计:能够测量X、Y、Z轴的加速度(以g为单位,1g ≈ 9.81 m/s²)。加速度计的工作原理基于微机电系统技术,通过微小的悬臂梁结构感知加速度引起的位移,然后转换为电信号输出。
-
三轴陀螺仪:能够测量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 在多种领域中有广泛应用,包括但不限于:
- 消费电子:智能手机、平板电脑中的屏幕旋转检测和稳定功能。
- 无人机:姿态控制、飞行稳定和导航。
- 可穿戴设备:运动追踪器、智能手表的活动监测和姿态检测。
- 虚拟现实(VR)和增强现实(AR)设备:用于头部和手部跟踪。
- 机器人和自动化控制:用于姿态估计和平衡控制。
- 汽车电子:用于车内安全系统、导航和防盗报警系统。
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;
}