1. MPU6050传感器基础入门MPU6050是一款集成了三轴陀螺仪和三轴加速度计的六轴运动处理传感器广泛应用于无人机、平衡车、手机等设备的姿态检测中。我第一次接触这个传感器是在做一个自平衡机器人项目时当时就被它小巧的体积和强大的功能所吸引。传感器的工作原理其实很直观加速度计测量的是物体在三个轴向上的线性加速度而陀螺仪则测量绕三个轴的旋转角速度。举个例子当你把手机从水平状态快速抬起时加速度计能感知到这个向上的运动而陀螺仪则能检测到手机角度的变化。在实际使用中MPU6050有以下几个关键参数需要注意加速度计量程通常选择±8g就足够日常使用陀螺仪量程500°/s是个比较适中的选择滤波器带宽21Hz能有效滤除高频噪声#include Adafruit_MPU6050.h #include Adafruit_Sensor.h #include Wire.h Adafruit_MPU6050 mpu; void setup() { Serial.begin(115200); if (!mpu.begin()) { Serial.println(Failed to find MPU6050 chip); while (1); } mpu.setAccelerometerRange(MPU6050_RANGE_8_G); mpu.setGyroRange(MPU6050_RANGE_500_DEG); mpu.setFilterBandwidth(MPU6050_BAND_21_HZ); }2. Arduino与MPU6050的硬件连接连接MPU6050到Arduino其实非常简单但新手经常会犯一些低级错误。我记得第一次接线时就把SDA和SCL接反了结果调试了半天才发现问题。正确的接线方式如下VCC → 5VGND → GNDSCL → A5 (UNO板)或SCL引脚SDA → A4 (UNO板)或SDA引脚INT → 数字引脚2可选这里有个实用建议使用面包板连接时最好用不同颜色的杜邦线区分电源、地和信号线这样既美观又不容易出错。另外如果发现传感器工作不稳定可以在VCC和GND之间加一个0.1uF的滤波电容。实际项目中我遇到过I2C地址冲突的问题。MPU6050默认地址是0x68但有些模块可以通过AD0引脚改变地址。如果总线上有多个I2C设备记得检查地址是否冲突。3. 传感器数据读取与处理成功连接硬件后下一步就是读取原始数据了。MPU6050输出的原始数据需要经过一些处理才能变成有用的信息。下面这个示例展示了如何读取并显示传感器的原始数据void loop() { sensors_event_t a, g, temp; mpu.getEvent(a, g, temp); Serial.print(Accel X:); Serial.print(a.acceleration.x); Serial.print( Y:); Serial.print(a.acceleration.y); Serial.print( Z:); Serial.print(a.acceleration.z); Serial.println( m/s^2); Serial.print(Gyro X:); Serial.print(g.gyro.x); Serial.print( Y:); Serial.print(g.gyro.y); Serial.print( Z:); Serial.print(g.gyro.z); Serial.println( rad/s); delay(100); }读取数据时需要注意几个常见问题加速度计数据包含重力分量静止时Z轴大约为9.8m/s²陀螺仪数据会有零偏误差需要进行校准温度变化会影响传感器精度我通常会在设备启动时做一个简单的校准将传感器水平静止放置几秒钟记录这段时间的平均值作为初始偏移量。4. 从数据到姿态角度计算原理有了原始数据如何计算设备的俯仰角(pitch)和横滚角(roll)呢这里介绍两种基本方法加速度计法 通过加速度计的三轴数据可以计算出倾斜角度float pitch atan2(a.acceleration.y, a.acceleration.z) * 180/PI; float roll atan2(-a.acceleration.x, sqrt(a.acceleration.y*a.acceleration.y a.acceleration.z*a.acceleration.z)) * 180/PI;陀螺仪积分法 陀螺仪测量的是角速度通过对时间积分可以得到角度变化float pitch 0; float roll 0; void loop() { sensors_event_t a, g, temp; mpu.getEvent(a, g, temp); float dt 0.1; // 采样间隔100ms pitch g.gyro.x * dt * 180/PI; roll g.gyro.y * dt * 180/PI; }单独使用任一种方法都有明显缺陷加速度计在运动时会有误差陀螺仪则会随时间累积误差。这就是为什么需要传感器融合算法。5. 传感器融合与姿态解算在实际项目中我推荐使用互补滤波或卡尔曼滤波来融合加速度计和陀螺仪的数据。这里先介绍一个简单的互补滤波实现float pitch 0, roll 0; float alpha 0.98; // 滤波系数 void loop() { sensors_event_t a, g, temp; mpu.getEvent(a, g, temp); float dt 0.1; // 100ms采样周期 // 加速度计角度 float acc_pitch atan2(a.acceleration.y, a.acceleration.z) * 180/PI; float acc_roll atan2(-a.acceleration.x, sqrt(a.acceleration.y*a.acceleration.y a.acceleration.z*a.acceleration.z)) * 180/PI; // 陀螺仪积分 pitch alpha * (pitch g.gyro.x * dt * 180/PI) (1-alpha) * acc_pitch; roll alpha * (roll g.gyro.y * dt * 180/PI) (1-alpha) * acc_roll; Serial.print(Pitch:); Serial.print(pitch); Serial.print( Roll:); Serial.println(roll); delay(100); }这个简单的算法中alpha值决定了信任陀螺仪数据的程度。经过实测0.98左右的值在大多数情况下都能取得不错的效果。对于更精确的应用可以考虑使用DMP数字运动处理器或Madgwick/Mahony等更先进的滤波算法。6. 实际应用案例平衡小车最后分享一个我在平衡小车项目中的实际应用。小车需要实时监测自身的倾斜角度并通过PID控制电机保持平衡。核心代码如下#include PID_v1.h // PID参数 double Setpoint, Input, Output; PID myPID(Input, Output, Setpoint, 2, 5, 1, DIRECT); void setup() { // 初始化MPU6050 // ... // 初始化PID Setpoint 0; // 目标角度为0度直立 myPID.SetMode(AUTOMATIC); myPID.SetSampleTime(10); // 10ms采样周期 } void loop() { // 获取当前角度使用融合后的数据 Input getFusedAngle(); // 计算PID输出 myPID.Compute(); // 控制电机 controlMotors(Output); delay(10); }在这个项目中最关键的是采样周期和PID参数的调整。经过多次测试我发现10ms的采样周期配合适中的PID参数能够实现稳定的平衡控制。调试过程中使用串口绘图工具实时观察角度变化和PID输出非常有帮助。