MPU6050

MPU-60X0 由三个独立的 MEMS 振动陀螺仪组成,这些陀螺仪检测 X、Y 和 Z 轴的旋转。当陀螺仪绕任何感测轴旋转时,科里奥利效应会产生振动,并由电容式传感器进行检测。产生的信号经过放大、解调和滤波处理后,生成与角速率成正比的电压。该电压通过片上独立的 16 位模数转换器(ADC)进行数字化,以便对每个轴进行采样。陀螺仪的满量程范围可以数字编程选择为 ±250、±500、±1000 或 ±2000 度每秒(dps)。ADC 的采样率可编程,从每秒 8000 个采样降低至每秒 3.9 个采样,并且用户可以选择低通滤波器,以实现不同的截止频率。

引脚说明

引脚编号 MPU-6000 MPU-6050 引脚名称 引脚描述
1 Y Y CLKIN 可选的外部参考时钟输入。如果不使用,连接到 GND。
6 Y Y AUX_DA I²C 主串行数据,用于连接外部传感器。
7 Y Y AUX_CL I²C 主串行时钟,用于连接外部传感器。
8 Y Y /CS SPI 片选(0 = SPI 模式)。
8 Y Y VLOGIC 数字 I/O 供电电压。
9 Y Y AD0 / SDO I²C 从设备地址最低有效位 (AD0)
SPI 串行数据输出 (SDO)
9 Y Y AD0 I²C 从设备地址最低有效位 (AD0)。
10 Y Y REGOUT 稳压滤波器电容器连接。
11 Y Y FSYNC 帧同步数字输入。未使用时连接到 GND。
12 Y Y INT 中断数字输出(推挽或开漏)。
13 Y Y VDD 电源供电电压和数字 I/O 供电电压。
18 Y Y GND 电源地。
19, 21 Y Y RESV 保留引脚。不要连接。
20 Y Y CPOUT 电荷泵电容器连接。
22 Y Y RESV 保留引脚。不要连接。
23 Y Y SCL / SCLK I²C 串行时钟(SCL);SPI 串行时钟信号(SCLK)。
23 Y Y SCL I²C 串行时钟(SCL)。
24 Y Y SDA / SDI I²C 串行数据线(SDA);SPI 串行数据输入线(SDI)。
24 Y Y SDA I²C 串行数据线(SDA)。
2, 3, 4, 5, 14, 15, 16, 17 Y Y NC 未内部连接,可用于 PCB 路由。

I2C 时序特性

参数 含义 最小值 典型值 最大值 单位 说明
fSCL SCL 时钟频率 - - 400 kHz I²C Fast-Mode 最大时钟频率。
tHD.STA START 条件保持时间(重复 START 条件) 0.6 - - µs START 条件后 SDA 需要保持的时间。
tLOW SCL 低电平时间 1.3 - - µs 时钟信号 SCL 的低电平周期时间。
tHIGH SCL 高电平时间 0.6 - - µs 时钟信号 SCL 的高电平周期时间。
tSU.STA START 条件建立时间 0.6 - - µs START 条件信号开始前 SDA 建立的时间。
tHD;DAT 数据保持时间 0 - - µs 数据传输后 SDA 保持的时间。
tSU;DAT 数据建立时间 100 - - ns 数据传输前 SDA 建立的最小时间。
tR SCL 和 SDA 的上升时间 - 20+0.1Cb 300 ns 受电容 Cb 影响的上升时间。
tF SCL 和 SDA 的下降时间 - 20+0.1Cb 300 ns 受电容 Cb 影响的下降时间。
tSU;STO STOP 条件建立时间 0.6 - - µs STOP 条件信号开始前的建立时间。
tBUF STOP 和下一次 START 之间的空闲时间 1.3 - - µs STOP 条件与下一次 START 之间的最小间隔。
Cb 每条总线的电容 - - < 400 pF I²C 总线允许的最大电容负载。
tVD;DAT 数据有效时间(SDA 数据有效) - - 0.9 µs 主机或从机输出数据后,接收方必须等待最多 0.9 µs 才能确认数据是有效的。
tVD;ACK ACK/NACK 信号有效时间(SDA 数据确认) - - 0.9 µs 接收端发送 ACK/NACK 信号后,发送方最多需要等待 0.9 µs 才能确认这个应答信号是有效的。

基本条件

  • VDD:工作电压范围在 2.375V - 3.46V
  • VLOGIC:对于 MPU-6050,这个逻辑电压为 1.8V±5% 或等于 VDD。
  • TA = 25°C:所有数据的测量温度为 25°C

I2C 地址

I2C 接口的从设备地址的最低有效位(LSB)由引脚 9(AD0)的电平决定,

  • 如果 AD0 = 0(接地,逻辑低),LSB 为 0,从设备地址为 0x68(1101000)。

  • 如果 AD0 = 1(接高电平,逻辑高),LSB 为 1,从设备地址为 0x69(1101001)。

通过配置 AD0 引脚,用户可以改变 MPU-60X0 的地址,从而允许两个 MPU-60X0 设备共存于同一条 I2C 总线上,而不会发生地址冲突。

角速度与加速度

角速度

角速度描述的是一个物体绕某个轴旋转的快慢,即物体在单位时间内旋转的角度。

它是旋转运动中的一个重要物理量。

加速度

加速度是描述物体速度变化快慢的物理量

它表示单位时间内速度的变化量,可以描述直线运动中的加速、减速,或者方向变化引起的加速(如圆周运动)。

示例电路

sldl

pwqj

示例代码

业务逻辑

屏幕翻转

翻转屏幕主要基于 加速度计的重力方向。当设备正常摆放时,重力加速度主要作用在 Z 轴方向;当设备翻转(如倒置或侧翻)时,重力方向会改变。

实现原理:

  • 重力加速度分布:
    • Z 轴朝上时:加速度计输出约 +1g。
    • Z 轴朝下时:加速度计输出约 -1g。
    • X 和 Y 轴也会随着设备翻转发生变化。
  • 通过计算加速度计三轴(X、Y、Z)的方向与幅值,判断设备当前的朝向。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void Check_Screen_Orientation(void) {
short accelData[3]; // 存储加速度数据 ax, ay, az
MPU6050ReadAcc(accelData); // 读取加速度计数据

short ax = accelData[0];
short ay = accelData[1];
short az = accelData[2];

if (az > 8000)
printf("屏幕正向朝上\n");
else if (az < -8000)
printf("屏幕已翻转\n");
else if (ax > 8000)
printf("屏幕左侧朝上\n");
else if (ax < -8000)
printf("屏幕右侧朝上\n");
else if (ay > 8000)
printf("屏幕顶部朝上\n");
else if (ay < -8000)
printf("屏幕底部朝上\n");
}

说明

  • ax, ay, az 是加速度计的三轴数据。
  • 值为 8000 表示加速度接近 1g(取决于量程配置,例如 ±8g 时 1g≈8192)。

睡眠

睡眠状态的判断通常基于 加速度计的变化程度。当设备长时间处于静止状态(加速度变化非常小),可以认为设备处于睡眠状态。

实现原理:

  • 计算加速度计三轴数据的 均方根变化幅度
  • 如果变化小于某个阈值,并持续一段时间,则进入睡眠状态。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#define THRESHOLD_SLEEP 500  // 静止状态加速度变化阈值
#define SLEEP_TIME 5000 // 静止持续时间 (毫秒)

void Check_Sleep_State(void) {
static u32 sleep_timer = 0;
short accelData[3];
MPU6050ReadAcc(accelData);

short ax = accelData[0];
short ay = accelData[1];
short az = accelData[2];

int accel_magnitude = sqrt(ax * ax + ay * ay + az * az);

if (abs(accel_magnitude - 8192) < THRESHOLD_SLEEP) { // 判断是否接近静止
sleep_timer += 10; // 每10ms调用一次
if (sleep_timer >= SLEEP_TIME) {
printf("设备进入睡眠状态\n");
sleep_timer = SLEEP_TIME;
}
}
else {
sleep_timer = 0; // 重置计时器
}
}

说明

  • 静止时加速度幅值接近 1g,即 8192(取决于加速度量程)。
  • 如果加速度变化幅度小于阈值 THRESHOLD_SLEEP 且持续时间大于 SLEEP_TIME,认为设备进入静止。

运动状态

运动状态的检测主要通过 加速度计或陀螺仪数据的变化。当设备处于运动中时,加速度或角速度的变化较大。

实现原理:

  • 加速度突变:通过检测加速度值的变化,判断设备是否处于运动中。
  • 陀螺仪角速度变化:检测旋转运动,增加判断的准确性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#define THRESHOLD_MOTION_ACCEL 2000 // 运动检测加速度变化阈值
#define THRESHOLD_MOTION_GYRO 3000 // 运动检测角速度变化阈值

void Check_Motion_State(void) {
short accelData[3], gyroData[3];
MPU6050ReadAcc(accelData); // 获取加速度数据
MPU6050ReadGyro(gyroData); // 获取陀螺仪数据

short ax = accelData[0];
short ay = accelData[1];
short az = accelData[2];

short gx = gyroData[0];
short gy = gyroData[1];
short gz = gyroData[2];

if ((abs(ax) > THRESHOLD_MOTION_ACCEL) || (abs(ay) > THRESHOLD_MOTION_ACCEL) || (abs(az) > THRESHOLD_MOTION_ACCEL) ||
(abs(gx) > THRESHOLD_MOTION_GYRO) || (abs(gy) > THRESHOLD_MOTION_GYRO) || (abs(gz) > THRESHOLD_MOTION_GYRO)) {
printf("设备正在运动中\n");
}
else {
printf("设备处于静止状态\n");
}
}

说明

  • 加速度和角速度 的变化幅度都可用于判断运动状态。
  • 如果任意轴的加速度或角速度超过设定阈值,则判定为运动。

摔倒检测

摔倒检测是一个较复杂的场景,通常结合 加速度的剧烈变化角速度的瞬时变化

实现原理:

  1. 自由落体检测:加速度突然接近 0g,表示设备正在快速下坠。
  2. 冲击检测:落地时加速度会瞬间增加,超过一定阈值。
  3. 结合角速度变化:摔倒时通常伴随较大的旋转运动。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#define FREE_FALL_THRESHOLD 3000 // 自由落体阈值 (加速度接近0)
#define IMPACT_THRESHOLD 16000 // 冲击检测阈值
#define GYRO_THRESHOLD 3000 // 角速度变化阈值

void Check_Fall_State(void) {
short accelData[3], gyroData[3];
MPU6050ReadAcc(accelData); // 获取加速度数据
MPU6050ReadGyro(gyroData); // 获取陀螺仪数据

short ax = accelData[0];
short ay = accelData[1];
short az = accelData[2];

short gx = gyroData[0];
short gy = gyroData[1];
short gz = gyroData[2];

int accel_magnitude = sqrt(ax * ax + ay * ay + az * az);

if (accel_magnitude < FREE_FALL_THRESHOLD) {
printf("检测到自由落体,可能正在下坠!\n");
}else if (accel_magnitude > IMPACT_THRESHOLD) {
printf("检测到强烈冲击,可能发生摔倒!\n");
}else if ((abs(gx) > GYRO_THRESHOLD) || (abs(gy) > GYRO_THRESHOLD) || (abs(gz) > GYRO_THRESHOLD)) {
printf("检测到大幅度旋转,可能正在摔倒!\n");
}
}

说明

  • 自由落体:加速度接近 0。
  • 冲击:落地时加速度远大于 1g。
  • 摔倒往往伴随大幅度旋转,因此检测陀螺仪变化。

驱动库

https://github.com/TooUpper/SensorDrive