// 这个示例演示如何使用 I2C 总线读取 MPU6050 的原始六轴数据(加速度 + 陀螺仪),
// 并按所设量程把原始计数值(raw counts, LSB)换算成“物理单位”输出。
// 依赖:Wire(I2C库,Arduino自带)+ MPU6050 库(Electronic Cats / Jeff Rowberg 兼容接口)
//
// 连接要点(以常见开发板为例,如 UNO / Mega / ESP32 等):
// - VCC:多数 MPU6050 模块板带稳压与上拉,可接 5V;裸芯片只能 3.3V。
// - GND:公共地
// - SCL/SDA:I2C 时钟/数据线。UNO 为 A5/A4;Mega 为 21(SCL)/20(SDA);ESP32 见芯片引脚映射。
// - AD0:I2C 低位地址脚,接 GND -> 地址 0x68(默认),接 VCC -> 0x69。
// - 注意 I2C 需要上拉电阻(模块板通常已自带)。
//
// 本例设置:
// - 加速度计量程 ±2g(灵敏度 16384 LSB/g)
// - 陀螺仪量程 ±2000 °/s(灵敏度 16.4 LSB/(°/s))
#include <Wire.h> // I2C 通讯库(主/从设备数据线)
#include <MPU6050.h> // MPU6050 设备驱动库(提供初始化、读写寄存器、获取数据等接口)
MPU6050 mpu; // 创建一个 MPU6050 对象实例(使用默认 I2C 地址 0x68)
void setup() {
Serial.begin(115200); // 打开串口,波特率 115200,方便高速打印数据
Wire.begin(); // 启动 I2C 主机功能(加入 I2C 总线)
// Wire.setClock(400000); // (可选)把 I2C 速率调到 400kHz,加快采样/传输
Serial.println("初始化MPU6050..."); // 提示正在初始化
// 初始化 MPU6050:复位必要寄存器、唤醒芯片(默认上电在休眠)、设置 I2C 地址等
mpu.initialize();
// 验证与 MPU6050 的 I2C 连接是否正常
// 底层通常通过读取 WHO_AM_I 寄存器(应返回 0x68)来判断
if (mpu.testConnection()) {
Serial.println("MPU6050 连接成功");
} else {
Serial.println("MPU6050 连接失败,请检查接线或I2C地址!");
while (1); // 卡在此处,不再往下执行,避免继续使用未连接好的设备
}
// 根据库的接口设置传感器量程(影响灵敏度:LSB/物理量)
// 陀螺仪量程设为 ±2000 °/s -> 灵敏度常数 ≈ 16.4 LSB/(°/s)
mpu.setFullScaleGyroRange(MPU6050_GYRO_FS_2000);
// 加速度计量程设为 ±2g -> 灵敏度常数 = 16384 LSB/g
mpu.setFullScaleAccelRange(MPU6050_ACCEL_FS_2);
// (可选)可以进一步设置 DLPF 低通滤波、采样率等:
// mpu.setDLPFMode(MPU6050_DLPF_BW_42); // 例如设置带宽 42Hz,降低高频噪声
// mpu.setRate(4); // 采样分频,详见数据手册/库文档
Serial.println("MPU6050 初始化成功");
}
void loop() {
// 原始传感器数据变量(单位:原始计数,int16_t 对应芯片输出的 16 位有符号数)
int16_t ax, ay, az; // 加速度计原始数据(X/Y/Z 轴)
int16_t gx, gy, gz; // 陀螺仪原始数据(X/Y/Z 轴)
// 一次性读取 6 路数据:ax, ay, az, gx, gy, gz
// 底层从对应的数据寄存器中连续读出,保证同一时刻采样的一致性
mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
// === 原始值 -> 物理单位换算 ===
// 加速度:根据量程 ±2g,对应灵敏度 16384 LSB/g
// 例如:ax=16384 -> 1g;ax=-16384 -> -1g
float accelX = ax / 16384.0f; // 单位:g
float accelY = ay / 16384.0f; // 单位:g
float accelZ = az / 16384.0f; // 单位:g
// 陀螺仪:量程 ±2000 °/s,灵敏度 ≈ 16.4 LSB/(°/s)
// 例如:gx=164 -> 10 °/s;gx=-328 -> -20 °/s
float gyroX = gx / 16.4f; // 单位:度/秒 (°/s)
float gyroY = gy / 16.4f; // 单位:度/秒 (°/s)
float gyroZ = gz / 16.4f; // 单位:度/秒 (°/s)
// === 温度 ===
// 调用库函数获取原始温度(等效于直接读 TEMP_OUT_H/L)
int16_t tempRaw = mpu.getTemperature();
// 按数据手册换算为摄氏度
float temperature = (tempRaw / 340.0) + 36.53;
// === 串口输出 ===
// 注意:Serial.printf 在 ESP32/ESP8266 等平台可直接使用;
// 若在 AVR 平台(UNO/Mega)编译报错,请改用 Serial.print 组合(见下方注释示例)。
Serial.printf("加速度 X:%.2f Y:%.2f Z:%.2f g\n", accelX, accelY, accelZ);
Serial.printf("陀螺仪 X:%.2f Y:%.2f Z:%.2f °/s\n", gyroX, gyroY, gyroZ);
Serial.printf("温度: %.2f ℃\n", temperature);
Serial.println("---");
// (可根据需要调整输出频率;过快会淹没串口)
delay(500); // 500ms 打印一次
}
/*
【在 UNO/Mega 等不支持 Serial.printf 的平台,请用以下写法替换上面的三行打印】:
Serial.print("加速度 X:"); Serial.print(accelX, 2);
Serial.print(" Y:"); Serial.print(accelY, 2);
Serial.print(" Z:"); Serial.print(accelZ, 2);
Serial.println(" g");
Serial.print("陀螺仪 X:"); Serial.print(gyroX, 2);
Serial.print(" Y:"); Serial.print(gyroY, 2);
Serial.print(" Z:"); Serial.print(gyroZ, 2);
Serial.println(" °/s");
Serial.println("---");
*/