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 本章知识体系
为了让大家更直观地理解本章内容,我画了一张流程图,展示传感器数据从采集到预处理的全过程:
这张图清晰地展示了数据流向:从原始数据开始,经过读取、零偏校准、标度因数校准,最后通过滤波得到可用数据。每一步都不可或缺。
最后提醒:校准和滤波的参数不是一成不变的。不同传感器、不同飞行环境,参数都需要微调。我建议每次更换硬件或环境后,重新做一遍校准流程。
好了,这一章的内容就到这里。传感器数据预处理是飞控调参的基础,希望大家动手实践,把代码跑起来,看看原始数据和滤波后的数据有什么区别。相信我,当你看到平滑的波形时,那种成就感是无可替代的。
公众号:蓝海资料掘金营,微信deep3321