MPU6050 加速度 + 陀螺仪传感器完整教程:从接线到姿态解算
一、前言
MPU6050 是一款集成三轴加速度计、三轴陀螺仪的 6 轴运动传感器,凭借低成本、小体积、高集成度,成为物联网、机器人、穿戴设备开发的首选。它支持 I2C 通信,可输出高精度运动数据,不仅能检测加速度、角速度,还能通过姿态解算得到设备的俯仰角、滚转角,适用于体感控制、姿态监测、计步器等场景。
本文基于 Arduino 平台,从硬件基础、接线方法、库函数使用、原生寄存器驱动到姿态解算,全方位讲解 MPU6050 的使用,兼顾新手入门和进阶需求。
二、MPU6050 核心参数与硬件解析
1. 关键参数
| 特性 | 规格参数 |
|---|---|
| 加速度计范围 | ±2G/±4G/±8G/±16G(可配置) |
| 陀螺仪范围 | ±250°/s/±500°/s/±1000°/s/±2000°/s(可配置) |
| 输出数据率 | 4Hz~1kHz |
| 供电电压 | 3.3V(绝对最大值 3.9V) |
| 通信协议 | I2C(默认地址 0x68/0x69) |
| 工作温度 | -40℃~85℃ |
| 内置传感器 | 加速度计(16 位 ADC)、陀螺仪(16 位 ADC)、温度传感器 |
2. 引脚定义(传感器模块)
| 引脚标识 | 功能说明 | 注意事项 |
|---|---|---|
| VCC | 电源输入 | 仅支持 3.3V,接 5V 直接烧毁 |
| GND | 接地 | 必须与主控板共地,否则信号干扰 |
| SDA | I2C 数据引脚 | 接主控板 SDA 引脚(Arduino A4) |
| SCL | I2C 时钟引脚 | 接主控板 SCL 引脚(Arduino A5) |
| AD0 | 地址选择引脚 | 接地 = 0x68(默认),接 VCC=0x69 |
| INT | 中断输出引脚(可选) | 数据就绪时输出高电平,可用于中断触发 |
三、硬件准备与接线方法
1. 必备组件
-
主控板:Arduino UNO/Nano(或 ESP32、STM32)
-
MPU6050 模块(带电压转换的模块更稳定)
-
杜邦线(公对母):4-6 根
-
面包板(可选):方便接线测试
-
5V 电源(可选):若需独立供电,需确保 3.3V 输出稳定
2. 接线表(Arduino UNO 为例)
| MPU6050 引脚 | Arduino 引脚 | 接线说明 |
|---|---|---|
| VCC | 3.3V | 严禁接 5V!模块无 LDO 时必烧 |
| GND | GND | 共地连接,减少数据噪声 |
| SDA | A4 | I2C 数据线,Arduino 默认引脚 |
| SCL | A5 | I2C 时钟线,Arduino 默认引脚 |
| AD0 | GND | 选择默认地址 0x68,多传感器时接 VCC |
| INT | 不接 / 任意数字引脚 | 不用中断功能可悬空 |
接线技巧:若使用 ESP32,SDA=GPIO21,SCL=GPIO22;STM32 需根据型号确认 I2C 引脚(如 STM32F103c8t6:SDA=PB7,SCL=PB6)。
四、驱动代码实现(3 种方案,从易到难)
方案 1:Adafruit 库快速实现(新手首选)
步骤 1:安装依赖库
打开 Arduino IDE → 项目 → 加载库 → 管理库:
-
搜索「Adafruit MPU6050」安装(核心库)
-
搜索「Adafruit Unified Sensor」安装(依赖库)
步骤 2:完整代码(读取加速度、陀螺仪、温度)
\#include ruit\_MPU6050.h>
\#include \<Adafruit\_Sensor.h>
\#include >
Adafruit\_MPU6050 mpu; // 实例化传感器对象
void setup() {
  Serial.begin(115200); // 串口波特率115200(比9600更流畅)
  while (!Serial) delay(10); // 等待串口连接(USB模式)
  // 初始化MPU6050
  if (!mpu.begin()) {
  Serial.println("找不到MPU6050传感器!检查:");
  Serial.println("1. 接线是否正确(VCC必须3.3V)");
  Serial.println("2. 地址是否为0x68(AD0接地)");
  while (1) {
  delay(500);
  digitalWrite(LED\_BUILTIN, !digitalRead(LED\_BUILTIN)); // 指示灯闪烁报警
  }
  }
  Serial.println("MPU6050初始化成功!");
  // 配置传感器参数(按需调整)
  mpu.setAccelerometerRange(MPU6050\_RANGE\_8\_G); // 加速度范围±8G(灵敏度更高)
  mpu.setGyroRange(MPU6050\_RANGE\_500\_DEG); // 陀螺仪范围±500°/s
  mpu.setFilterBandwidth(MPU6050\_BAND\_44\_HZ); // 滤波带宽44Hz(减少数据噪声)
  delay(100); // 传感器稳定时间
}
void loop() {
  sensors\_event\_t a, g, temp; // 存储加速度、陀螺仪、温度数据
  mpu.getEvent(\&a, \&g, \&temp); // 读取所有传感器数据
  // 打印加速度数据(单位:m/s²)
  Serial.print("加速度 \[m/s²]:");
  Serial.print("X: "); Serial.print(a.acceleration.x, 2); // 保留2位小数
  Serial.print(", Y: "); Serial.print(a.acceleration.y, 2);
  Serial.print(", Z: "); Serial.print(a.acceleration.z, 2);
  // 打印陀螺仪数据(单位:rad/s,转角度需×(180/PI))
  Serial.print(" | 陀螺仪 \[rad/s]:");
  Serial.print("X: "); Serial.print(g.gyro.x, 2);
  Serial.print(", Y: "); Serial.print(g.gyro.y, 2);
  Serial.print(", Z: "); Serial.print(g.gyro.z, 2);
  // 打印内置温度(单位:℃)
  Serial.print(" | 温度:"); Serial.print(temp.temperature, 1); Serial.println("℃");
  delay(200); // 控制数据输出频率(5Hz)
}
步骤 3:测试与验证
-
上传代码后打开串口监视器(波特率 115200);
-
晃动传感器,观察加速度 / 陀螺仪数值变化;
-
静止时 Z 轴加速度约 9.81m/s²(重力加速度),陀螺仪数值接近 0。
方案 2:原生寄存器驱动(理解底层原理)
无需第三方库,直接操作 MPU6050 寄存器,适合深入学习 I2C 通信和传感器底层逻辑。
核心代码(读取原始数据)
\#include >
\#define MPU6050\_ADDR 0x68 // 传感器地址
\#define PWR\_MGMT\_1 0x6B // 电源管理寄存器
\#define ACCEL\_XOUT\_H 0x3B // 加速度X轴高位寄存器
\#define GYRO\_XOUT\_H 0x43 // 陀螺仪X轴高位寄存器
// 存储传感器数据
int16\_t ax, ay, az; // 加速度原始值
int16\_t gx, gy, gz; // 陀螺仪原始值
float temp; // 温度
// 初始化MPU6050
void mpu6050\_init() {
  Wire.begin();
  Wire.beginTransmission(MPU6050\_ADDR);
  Wire.write(PWR\_MGMT\_1);
  Wire.write(0x00); // 唤醒传感器(默认睡眠模式)
  Wire.endTransmission();
  // 配置加速度范围±8G(0x10对应±8G)
  Wire.beginTransmission(MPU6050\_ADDR);
  Wire.write(0x1C); // 加速度配置寄存器
  Wire.write(0x10);
  Wire.endTransmission();
  // 配置陀螺仪范围±500°/s(0x08对应±500°/s)
  Wire.beginTransmission(MPU6050\_ADDR);
  Wire.write(0x1B); // 陀螺仪配置寄存器
  Wire.write(0x08);
  Wire.endTransmission();
}
// 读取传感器数据
void mpu6050\_read() {
  Wire.beginTransmission(MPU6050\_ADDR);
  Wire.write(ACCEL\_XOUT\_H); // 从加速度X轴高位寄存器开始读取
  Wire.endTransmission(false);
  Wire.requestFrom(MPU6050\_ADDR, 14); // 连续读取14字节数据
  // 解析加速度数据(16位,高字节在前)
  ax = Wire.read() << 8 | Wire.read();
  ay = Wire.read() <.read();
  az = Wire.read() < | Wire.read();
  // 解析温度数据
  temp = (Wire.read() <.read()) / 340.0 + 36.53;
  // 解析陀螺仪数据
  gx = Wire.read() < Wire.read();
  gy = Wire.read() <8 | Wire.read();
  gz = Wire.read() <.read();
  // 转换为实际物理量
  float ax\_real = ax / 4096.0; // ±8G时,灵敏度4096 LSB/g
  float ay\_real = ay / 4096.0;
  float az\_real = az / 4096.0;
  float gx\_real = gx / 65.5; // ±500°/s时,灵敏度65.5 LSB/(°/s)
  float gy\_real = gy / 65.5;
  float gz\_real = gz / 65.5;
  // 打印数据
  Serial.print("加速度 \[g]:X: "); Serial.print(ax\_real, 2);
  Serial.print(", Y: "); Serial.print(ay\_real, 2);
  Serial.print(", Z: "); Serial.print(az\_real, 2);
  Serial.print(" | 陀螺仪 \[°/s]:X: "); Serial.print(gx\_real, 2);
  Serial.print(", Y: "); Serial.print(gy\_real, 2);
  Serial.print(", Z: "); Serial.print(gz\_real, 2);
  Serial.print(" | 温度:"); Serial.print(temp, 1); Serial.println("℃");
}
void setup() {
  Serial.begin(115200);
  mpu6050\_init();
  Serial.println("MPU6050原生寄存器驱动初始化成功!");
}
void loop() {
  mpu6050\_read();
  delay(200);
}
方案 3:姿态解算(卡尔曼滤波求俯仰角 / 滚转角)
MPU6050 的原始数据含噪声,通过卡尔曼滤波融合加速度和陀螺仪数据,可得到稳定的姿态角(俯仰角 Pitch、滚转角 Roll)。
核心代码(添加卡尔曼滤波)
\#include 6050.h>
\#include \_Sensor.h>
\#include afruit\_MPU6050 mpu;
sensors\_event\_t a, g, temp;
// 卡尔曼滤波参数
float Q\_angle = 0.001; // 角度噪声方差
float Q\_gyro = 0.003; // 角速度噪声方差
float R\_angle = 0.5; // 测量噪声方差
float angle = 0.0; // 滤波后的角度
float bias = 0.0; // 陀螺仪零偏
float P\[2]\[2] = {{1, 0}, {0, 1}}; // 协方差矩阵
// 卡尔曼滤波更新函数
float kalman\_filter(float angle\_measured, float gyro\_measured, float dt) {
  // 预测阶段
  float angle\_pred = angle - bias \* dt;
  float P\_pred\[2]\[2] = {
  {P\[0]\[0] + Q\_angle - P\[0]\[1] \* P\[1]\[0] / (P\[1]\[1] + Q\_gyro), -P\[0]\[1] / (P\[1]\[1] + Q\_gyro)},
  {-P\[1]\[0] / (P\[1]\[1] + Q\_gyro), P\[1]\[1] + Q\_gyro}
  };
  // 更新阶段
  float K\[2] = {
  P\_pred\[0]\[0] / (P\_pred\[0]\[0] + R\_angle),
  P\_pred\[1]\[0] / (P\_pred\[0]\[0] + R\_angle)
  };
  angle = angle\_pred + K\[0] \* (angle\_measured - angle\_pred);
  bias = bias + K\[1] \* (angle\_measured - angle\_pred);
  float P\_update\[2]\[2] = {
  {(1 - K\[0]) \* P\_pred\[0]\[0], (1 - K\[0]) \* P\_pred\[0]\[1]},
  {(1 - K\[1]) \* P\_pred\[1]\[0], P\_pred\[1]\[1] + K\[1] \* P\_pred\[0]\[0]}
  };
  P\[0]\[0] = P\_update\[0]\[0];
  P\[0]\[1] = P\_update\[0]\[1];
  P\[1]\[0] = P\_update\[1]\[0];
  P\[1]\[1] = P\_update\[1]\[1];
  return angle;
}
void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10);
  if (!mpu.begin()) {
  Serial.println("找不到MPU6050!");
  while (1) delay(500);
  }
  mpu.setAccelerometerRange(MPU6050\_RANGE\_8\_G);
  mpu.setGyroRange(MPU6050\_RANGE\_500\_DEG);
  mpu.setFilterBandwidth(MPU6050\_BAND\_44\_HZ);
  delay(100);
}
void loop() {
  static unsigned long last\_time = millis();
  unsigned long current\_time = millis();
  float dt = (current\_time - last\_time) / 1000.0; // 时间间隔(秒)
  last\_time = current\_time;
  mpu.getEvent(\&a, \&g, \&temp);
  // 从加速度计算俯仰角(Pitch):arctan2(ax, az)
  float pitch\_measured = atan2(a.acceleration.x, a.acceleration.z) \* 180 / PI;
  // 陀螺仪角速度转换为角度增量(°)
  float gyro\_pitch = g.gyro.y \* dt; // Y轴陀螺仪对应俯仰角变化
  // 卡尔曼滤波得到稳定的俯仰角
  float pitch\_filtered = kalman\_filter(pitch\_measured, gyro\_pitch, dt);
  // 打印结果
  Serial.print("原始俯仰角:"); Serial.print(pitch\_measured, 1);
  Serial.print("° | 滤波后俯仰角:"); Serial.print(pitch\_filtered, 1);
  Serial.println("°");
  delay(50);
}
五、常见问题与调试技巧
1. 传感器找不到(串口打印 “找不到 MPU6050”)
-
排查 VCC 电压:必须接 3.3V,用万用表测量模块供电是否稳定;
-
检查 I2C 引脚:Arduino UNO 是 A4(SDA)、A5(SCL),ESP32 是 21/22,STM32 需确认 I2C 总线是否使能;
-
地址冲突:若多个 I2C 设备,将 MPU6050 的 AD0 接 VCC,代码中改为
mpu.begin(0x69); -
模块损坏:若接错 5V,传感器可能已烧毁,更换模块测试。
2. 数据跳变严重(数值波动大)
-
启用滤波:通过
setFilterBandwidth设置更低的带宽(如 21Hz),或在代码中添加滑动平均滤波; -
固定传感器:将模块粘贴在硬纸板上,避免晃动导致的噪声;
-
减少干扰:远离电机、蓝牙模块等强电磁干扰源,供电线尽量短;
-
校准陀螺仪:静止时读取陀螺仪原始值,计算零偏并在代码中补偿。
3. 加速度 Z 轴数值异常(静止时≠9.81m/s²)
-
传感器校准:将模块水平放置,读取 ax、ay、az 的静止值,在代码中减去偏移量;
-
范围配置错误:若配置为 ±2G,灵敏度是 16384 LSB/g,转换时需用 ax/16384.0,而非 4096.0。
4. 中断功能无法使用
-
确认 INT 引脚接线:接 Arduino 数字引脚(如 D2);
-
配置中断寄存器:通过寄存器 0x38 设置中断触发方式(如数据就绪触发);
-
启用中断响应:在代码中编写中断服务函数,处理传感器数据。
六、进阶应用场景与扩展
1. 典型应用
-
姿态监测:无人机、机器人的姿态控制(需融合磁力计的 9 轴数据);
-
体感控制:通过俯仰角、滚转角遥控小车、LED 灯亮度;
-
计步器:通过加速度变化检测步数(阈值法或峰值检测);
-
振动检测:监测设备运行状态,振动超标时触发报警。
2. 平台移植
-
ESP32 适配:接线 SDA=21、SCL=22,代码无需修改(Wire 库兼容),可结合 WiFi 上传数据到云平台;
-
STM32 适配:使用 HAL 库的 I2C 函数,替换 Wire 库,寄存器操作逻辑一致;
-
Raspberry Pi 适配:使用 smbus2 库操作 I2C,代码结构与 Arduino 类似。
3. 功能扩展
-
9 轴融合:搭配 HMC5883L 磁力计,实现航向角(Yaw)测量;
-
数据存储:将传感器数据存储到 SD 卡,或通过蓝牙、LoRa 传输;
-
低功耗优化:配置 MPU6050 的睡眠模式,定时唤醒采集数据,延长电池寿命。
浙公网安备 33010602011771号