3、传感器数据采集与预处理:IMU数据读取(加速度计、陀螺仪)、数据滤波(低通滤波、互补滤波)、传感器校准(零偏、标度因数)

各位同学,欢迎来到飞控调参实战的第三讲。今天咱们聊聊飞控的“眼睛”和“耳朵”——IMU传感器。

说实话,我见过太多新手一上来就急着调PID,结果飞机在天上乱晃,查了半天发现是传感器数据本身就有问题。你想想看,地基都没打牢,房子能稳吗?所以这一章,咱们把传感器这块彻底吃透。

核心观点:飞控的稳定性,90%取决于传感器数据的质量。数据采集与预处理,是调参前的必修课。

3.1 IMU数据读取:加速度计与陀螺仪

IMU(惯性测量单元)通常包含两个核心器件:加速度计和陀螺仪。加速度计测量的是比力(包含重力),陀螺仪测量的是角速度。我习惯把它们比作“感觉加速度的耳朵”和“感觉旋转的眼睛”。

在实际项目中,我遇到过不少同学直接拿原始数据就用,结果发现加速度计噪声大得离谱。为什么会这样?因为传感器内部有机械振动和电子噪声,必须经过预处理才能用。

读取IMU数据,通常通过I2C或SPI总线。以MPU6050为例,代码大致是这样的:

// 伪代码示例:读取MPU6050加速度计和陀螺仪数据
void read_mpu6050() {
    // 读取加速度计原始值
    accel_x = read_register(ACCEL_XOUT_H);
    accel_y = read_register(ACCEL_XOUT_L);
    // 读取陀螺仪原始值
    gyro_x = read_register(GYRO_XOUT_H);
    gyro_y = read_register(GYRO_XOUT_L);
    // 转换为物理单位(g 和 °/s)
    accel_g = accel_raw / ACCEL_SENSITIVITY;
    gyro_dps = gyro_raw / GYRO_SENSITIVITY;
}

这里有个坑:不同量程下,灵敏度系数不一样。比如±2g和±16g,换算系数差8倍。我曾经因为忘记切换系数,导致飞机起飞就翻,教训深刻。

我的小技巧:读取数据后,先打印出来看看。静止时加速度计Z轴应该接近1g,X/Y轴接近0g。如果偏差太大,说明传感器或电路有问题。

3.2 数据滤波:低通滤波与互补滤波

原始数据拿到手,接下来就是滤波。说白了,就是把有用的信号留下,把没用的噪声滤掉。

3.2.1 低通滤波

低通滤波是最常用的手段。它让低频信号通过,衰减高频噪声。我一般用一阶RC低通滤波,简单高效:

// 一阶低通滤波
float low_pass_filter(float input, float prev_output, float alpha) {
    // alpha = T / (T + RC),T为采样周期
    return alpha * input + (1 - alpha) * prev_output;
}

alpha值怎么选?我个人的经验是:对于加速度计,alpha取0.1~0.3;对于陀螺仪,alpha取0.3~0.5。为什么?加速度计噪声大,需要更平滑;陀螺仪响应快,可以保留更多动态信息。

嗯,这里要注意:alpha太小,数据太“肉”,反应迟钝;alpha太大,噪声滤不干净。需要根据实际飞行效果微调。

3.2.2 互补滤波

互补滤波是飞控里的经典算法。它把加速度计和陀螺仪的数据融合起来,取长补短。

加速度计低频准、高频噪;陀螺仪高频准、低频漂。互补滤波就是让加速度计主导低频,陀螺仪主导高频。公式很简单:

// 互补滤波:融合角度
float complementary_filter(float accel_angle, float gyro_rate, float dt) {
    float tau = 0.5;  // 时间常数,通常0.1~1.0
    float alpha = tau / (tau + dt);
    angle = alpha * (angle + gyro_rate * dt) + (1 - alpha) * accel_angle;
    return angle;
}

我在项目中遇到过一个问题:飞机悬停时角度漂移。后来发现是互补滤波的tau值设得太小,陀螺仪积分漂移没被抑制住。调大tau值后,问题解决了。

避坑指南:我曾经因为采样时间dt计算错误,导致互补滤波失效。dt必须精确,最好用定时器或高精度时钟测量,不要用软件延时估算。

3.3 传感器校准:零偏与标度因数

校准是传感器预处理的重头戏。再好的传感器,出厂也有误差。零偏和标度因数是最常见的两种误差。

3.3.1 零偏校准

零偏,就是传感器在静止状态下输出的非零值。比如陀螺仪静止时应该输出0°/s,但实际可能输出0.5°/s。这个偏差必须去掉。

校准方法很简单:让传感器静止,采集N组数据,取平均值作为零偏值。我一般采集1000组数据,这样统计误差小。

// 零偏校准
void calibrate_gyro_bias() {
    float sum = 0;
    for (int i = 0; i < 1000; i++) {
        sum += read_gyro();
        delay(1);
    }
    gyro_bias = sum / 1000.0;
}

校准后,每次读取数据都要减去这个零偏值。嗯,这里有个细节:温度变化会导致零偏漂移。我建议每次上电后重新校准,或者加入温度补偿。

3.3.2 标度因数校准

标度因数,就是传感器的灵敏度误差。比如理论上1g对应16384 LSB,但实际可能是16200 LSB。这个误差会导致测量值偏大或偏小。

标度因数校准需要已知参考值。比如加速度计,可以用重力加速度作为参考。把传感器分别朝上、朝下放置,测量值应该分别是+1g和-1g。实际测量值与理论值的比值,就是标度因数。

方向 理论值(g) 实测值(LSB) 标度因数
Z轴朝上 +1.0 16200 16200 / 16384 = 0.9888
Z轴朝下 -1.0 -16550 16550 / 16384 = 1.0101

我一般取两个方向的平均值作为最终标度因数。这样能抵消部分非线性误差。

我的经验:标度因数校准最好在恒温环境下进行。温度变化会影响灵敏度,导致校准结果不准。另外,校准后记得验证一下:把传感器旋转90度,看看输出是否合理。

3.4 本章知识体系

为了让大家更直观地理解本章内容,我画了一张流程图,展示传感器数据从采集到预处理的全过程:

传感器数据采集与预处理流程 IMU原始数据 I2C/SPI数据读取 零偏校准 标度因数校准 低通/互补滤波 加速度计 陀螺仪 原始值→物理值 减去静态偏差 修正灵敏度 融合/平滑 → 可用数据

这张图清晰地展示了数据流向:从原始数据开始,经过读取、零偏校准、标度因数校准,最后通过滤波得到可用数据。每一步都不可或缺。

最后提醒:校准和滤波的参数不是一成不变的。不同传感器、不同飞行环境,参数都需要微调。我建议每次更换硬件或环境后,重新做一遍校准流程。

好了,这一章的内容就到这里。传感器数据预处理是飞控调参的基础,希望大家动手实践,把代码跑起来,看看原始数据和滤波后的数据有什么区别。相信我,当你看到平滑的波形时,那种成就感是无可替代的。


公众号:蓝海资料掘金营,微信deep3321