
1. 先搞清楚低通滤波和互补滤波到底解决什么问题如果你在搞嵌入式、机器人、无人机或者任何需要处理传感器数据的项目这两个词你肯定绕不开。很多人一上来就抄代码、调参数结果数据要么延迟大要么噪声多要么角度飘得厉害。其实低通滤波和互补滤波的核心就是解决“如何从带噪声的原始数据里又快又稳地提取出我们真正关心的信号”这个根本问题。低通滤波顾名思义就是让低频信号通过滤掉高频噪声。比如你的加速度计读数电机振动、手部抖动都会产生高频毛刺低通滤波就是用来平滑这些毛刺的。而互补滤波则更像一个“裁判”它知道两个“选手”的优缺点加速度计在静态或慢速时很准但动态响应慢、有延迟陀螺仪动态响应快但会随着时间积分产生漂移。互补滤波的工作就是把这两者的长处结合起来短处互相弥补最终输出一个既响应快又长期稳定的角度或姿态估计。所以这篇文章不是给你列公式的而是帮你建立一套从理解、选型到调参的实战思路。我会直接告诉你什么情况下该用一阶低通什么时候得上二阶互补滤波里那个关键的“比例系数”到底怎么调调的时候看什么指标。目标是让你看完就能在自己的板子上跑起来并且知道数据不对劲的时候该先检查哪里。2. 从一阶到二阶低通滤波的实战选择与参数调校低通滤波不是玄学它的效果直接由两个因素决定滤波器的阶数和截止频率。阶数决定了滤波器的“陡峭”程度截止频率决定了哪些频率的信号算“高频”要被干掉。2.1 一阶低通滤波够用就好理解时间常数绝大多数情况下尤其是单片机资源紧张时一阶低通滤波是你的首选。它计算量小概念简单。它的核心公式是Y(n) α * X(n) (1-α) * Y(n-1)其中X(n)是本次采样值带噪声Y(n)是本次滤波输出值Y(n-1)是上次滤波输出值α是一个介于0到1之间的系数。这里最关键的是理解α和“时间常数”的关系。α越大表示本次采样值的权重越大滤波器响应越快但滤除高频噪声的能力越弱更“跟随”原始信号。α越小表示历史数据的权重越大滤波效果越平滑但带来的延迟也越大。在实际编程中我们更常用“截止频率fc”或“时间常数τ”来思考。它们的关系是α ΔT / (τ ΔT) 2π * fc * ΔT / (2π * fc * ΔT 1)近似 其中ΔT是你的采样周期例如0.01秒代表100Hz采样率。实战建议先确定你需要滤除的噪声频率。用手晃动传感器看看波形噪声频率大概是多少Hz假设是10Hz以上的抖动是你不需要的。设定一个目标截止频率fc。比如设为5Hz意味着高于5Hz的信号会被显著衰减。根据采样周期ΔT计算α。如果采样率100HzΔT0.01sfc5Hz那么 α ≈ 2 * π * 5 * 0.01 ≈ 0.314。你可以从0.3左右开始试。在代码里实现float alpha 0.3; // 滤波系数 float filtered_value 0; // 滤波后的值需持久化 void loop() { float raw_data read_sensor(); // 读取原始数据 filtered_value alpha * raw_data (1 - alpha) * filtered_value; // 一阶低通滤波 // 使用 filtered_value delay(10); // 假设采样周期10ms }调参看什么输出一个平滑的波形图。如果曲线还有明显的高频毛刺说明α太大或fc太高需要减小α。如果感觉信号“变肉”了响应迟钝比如快速转动传感器时滤波后的值跟不上说明α太小或fc太低延迟太大需要增大α。2.2 二阶低通滤波当一阶不够“干净”时当你发现一阶滤波后数据还是不够平滑或者对特定频率的噪声抑制有更高要求时就需要考虑二阶低通滤波。它的传递函数更复杂幅频特性曲线更陡峭能更好地滤除截止频率附近的信号。对于嵌入式应用通常直接使用“二阶巴特沃斯低通滤波器”的离散化形式双线性变换。网上有很多在线计算器或现成的代码片段你需要提供采样频率Fs、截止频率Fc。实战步骤确定参数Fs100Hz, Fc5Hz。生成系数使用工具计算得到差分方程系数a0, a1, a2, b1, b2。实现代码// 假设计算得到的系数 float a0 0.2066, a1 0.4132, a2 0.2066, b1 -0.3695, b2 0.1958; float x[3] {0}; // 当前、前一次、前两次的输入 float y[3] {0}; // 当前、前一次、前两次的输出 float second_order_lpf(float new_sample) { // 更新输入历史 x[2] x[1]; x[1] x[0]; x[0] new_sample; // 更新输出历史 y[2] y[1]; y[1] y[0]; // 计算当前输出: y[n] a0*x[n] a1*x[n-1] a2*x[n-2] - b1*y[n-1] - b2*y[n-2] y[0] a0*x[0] a1*x[1] a2*x[2] - b1*y[1] - b2*y[2]; return y[0]; }与一阶的对比效果二阶滤波在截止频率附近衰减得更快通带内也可能更平坦。代价计算量增加需要存储和计算更多历史状态相位延迟通常也比一阶大。选择对于大多数传感器去抖如按键、加速度计基本平滑一阶完全足够且响应更快。只有当噪声频率和你关心的信号频率靠得很近需要更锐利的滤波时才上二阶。我建议始终先用一阶调试。3. 互补滤波融合加速度计与陀螺仪的经典策略互补滤波是姿态解算的入门核心它巧妙避开了复杂的卡尔曼滤波用很小的计算量实现了不错的效果。它的核心思想就一句话用高通滤波器滤陀螺仪的漂移低频误差用低通滤波器滤加速度计的噪声高频误差再把两者加起来。3.1 算法原理与代码实现最常用的是一阶互补滤波公式如下角度 (0.98) * (上一时刻角度 陀螺仪角速度 * ΔT) (0.02) * 加速度计计算的角度这里的0.98和0.02就是互补系数两者之和为1。0.98对应陀螺仪权重0.02对应加速度计权重。拆解来看陀螺仪路径上一时刻角度 陀螺仪角速度 * ΔT。这是积分能快速跟踪角度变化但误差零偏会随时间积分不断累积导致“漂移”。这属于低频误差。加速度计路径通过测量重力加速度在三个轴上的分量用atan2等函数可以计算出当前姿态角。这个方法在静态或慢速时非常准没有累积误差。但动态时除了重力物体本身的加速度也会被测量进去导致计算的角度剧烈跳动。这属于高频误差。融合对陀螺仪积分结果进行高通滤波通过乘以一个接近1的系数如0.98间接实现让它保留快速变化的部分信号削弱长期漂移的部分低频误差。对加速度计角度进行低通滤波通过乘以一个很小的系数如0.02让它保留长期稳定的部分信号滤除高频跳动的部分高频噪声。最后两者相加得到最终角度。代码示例float angle 0; // 估计角度 float dt 0.01; // 采样周期10ms float alpha 0.98; // 互补滤波系数即陀螺仪权重 void loop() { // 1. 读取数据 float gyro_z read_gyro_z(); // 陀螺仪Z轴角速度度/秒 float accel_y read_accel_y(); // 加速度计Y轴分量 float accel_x read_accel_x(); // 加速度计X轴分量 // 2. 从加速度计计算角度以X-Y平面为例计算滚转角 // 注意这里使用了atan2并转换为角度。实际中需要根据安装方式确定公式。 float accel_angle atan2(accel_y, accel_x) * 180.0 / PI; // 3. 互补滤波核心公式 angle alpha * (angle gyro_z * dt) (1 - alpha) * accel_angle; // 4. 使用融合后的 angle // ... delay(10); // 控制采样周期 }3.2 关键系数 Alpha 的调试心法系数alpha陀螺仪权重是互补滤波的“灵魂”。它不是一个固定值而是需要你根据传感器特性和应用场景来调整的。调试流程初始值通常从 0.95 到 0.98 开始尝试。这个值意味着 95%-98% 的信息来自陀螺仪积分。静态测试看长期稳定性将设备静止放置1-2分钟。观察angle输出。如果角度缓慢漂移说明陀螺仪零偏漂移没有被加速度计有效纠正。需要减小alpha比如从0.98降到0.96增加加速度计的权重让加速度计更用力地把角度“拉”回真实值。如果角度基本稳定说明融合效果良好进入下一步。动态测试看快速响应用手快速、大幅度地转动设备。如果角度响应迟钝感觉“跟不上”说明加速度计权重太大其高频噪声在快速变化时干扰了输出。需要增大alpha比如从0.96升到0.97更信任响应快的陀螺仪。如果角度跟踪迅速但停止后有小幅振荡或回弹可能是alpha略大或者加速度计噪声在变化瞬间被引入。可以微调alpha或考虑对加速度计角度先做一个轻微的一阶低通滤波注意这会增加延迟。权衡alpha越大响应越快但长期静态漂移越明显alpha越小静态越稳但动态响应越慢受加速度干扰越明显。你需要找到一个平衡点。注意这里的dt采样周期必须尽可能准确如果dt不稳定或不准陀螺仪积分误差会急剧放大。最好使用定时器中断来固定采样间隔。4. 进阶从单轴到姿态角以及常见坑点排查前面以单轴角度为例实际中我们需要的是三维姿态滚转 Roll、俯仰 Pitch、偏航 Yaw。同时一些细节问题会直接影响滤波效果。4.1 扩展到三维姿态Roll, Pitch, Yaw对于飞行器、机器人通常需要 Roll 和 Pitch。加速度计可以很好地计算这两个角因为重力方向是固定的参考。但偏航角Yaw无法从加速度计获得因为重力在水平面没有分量。因此常见的做法是Roll 和 Pitch使用互补滤波融合加速度计和陀螺仪。Yaw只能依赖陀螺仪积分这会随时间漂移。为了校正 Yaw需要引入磁力计电子罗盘或视觉/GPS等外部参考形成另一个互补滤波或者使用更复杂的算法如AHRS、卡尔曼滤波。三维互补滤波代码结构示意float roll 0, pitch 0, yaw 0; float dt 0.01; float alpha_rp 0.98; // 滚转/俯仰的系数 void loop() { // 读取陀螺仪三轴角速度 (gyro_x, gyro_y, gyro_z) // 读取加速度计三轴数据 (acc_x, acc_y, acc_z) // 读取磁力计三轴数据 (mag_x, mag_y, mag_z) - 用于Yaw // 1. 从加速度计计算 Roll 和 Pitch float accel_roll atan2(acc_y, acc_z) * 180/PI; float accel_pitch atan2(-acc_x, sqrt(acc_y*acc_y acc_z*acc_z)) * 180/PI; // 2. 互补滤波更新 Roll 和 Pitch roll alpha_rp * (roll gyro_x * dt) (1 - alpha_rp) * accel_roll; pitch alpha_rp * (pitch gyro_y * dt) (1 - alpha_rp) * accel_pitch; // 3. 对于Yaw通常需要磁力计校正这里简化表示 // 先积分陀螺仪Z轴 yaw yaw gyro_z * dt; // ... (此处应有磁力计数据处理和融合可能是一个更复杂的互补或卡尔曼滤波) delay(10); }4.2 必须避开的坑与排查清单当你发现滤波效果不理想时不要急着调参数按这个顺序排查传感器数据本身是否可靠加速度计静止测试设备水平静止读取的加速度计X、Y、Z轴输出是否接近 (0, 0, 1g) 或 (0, 0, -1g)如果不是需要校准加速度计零偏和标度因数。陀螺仪静止测试设备静止陀螺仪各轴输出是否在零附近小幅波动零偏记录这个零偏值在积分前先减去它gyro_corrected gyro_raw - gyro_bias。这是减少漂移最关键的一步单位确认陀螺仪读数是度/秒还是弧度/秒公式中的dt单位是秒吗确保单位统一。采样周期dt是否稳定且准确不要在loop里用delay(10)就认为dt0.01。loop中其他代码也会耗时。使用micros()或定时器中断来精确计算两次采样的时间差作为dt。不稳定的dt会导致积分误差起伏滤波效果极差。坐标系对齐了吗确保陀螺仪角速度的物理轴X, Y, Z和加速度计的物理轴与你在代码里计算 Roll/Pitch 时假设的机体坐标系是一致的。传感器安装方向不同公式也要调整。互补滤波系数是否在合理范围alpha一般就在 0.9 到 0.999 之间。如果调到 0.5那基本就是在用加速度计的角度噪声会很大如果调到 0.999陀螺仪漂移会很快显现。动态性能要求高如竞速无人机alpha可接近 0.99静态稳定性要求高如平衡车alpha可接近 0.95。是否忽略了滤波器的初始状态系统上电时angle变量初始为0但实际物体可能不是水平。一个简单的处理是在开始的1-2秒内只用加速度计的角度来初始化angle然后再开启互补滤波。5. 低通与互补滤波的组合应用与性能边界在实际系统中低通滤波和互补滤波往往是组合使用的它们扮演不同的角色。5.1 典型的信号处理链条一个稳健的姿态估计流程可能是这样的原始加速度计数据 → (低通滤波) → 计算角度 → ↗ ↓ (互补滤波) → 最终姿态角 原始陀螺仪数据 → (减去零偏) → 积分 → ↗对原始加速度计数据进行低通滤波在进入互补滤波之前先对accel_x, accel_y, accel_z进行一阶低通滤波滤除高频振动噪声。这能使得计算出的accel_angle更平滑减少对互补滤波输出的高频干扰。注意这个低通滤波的截止频率可以设得比互补滤波中隐含的低通部分更高一些主要为了去毛刺不要引入太大延迟。对原始陀螺仪数据进行零偏校正这是必须的。进行互补滤波融合。(可选) 对互补滤波输出再进行轻微低通滤波如果融合后的角度仍有你不希望的高频微小波动可以再加一个非常轻微的一阶低通α很大如0.99让曲线更光滑用于显示或低带宽控制。注意这一定会增加额外延迟用于控制回路时要非常小心。5.2 理解算法的性能边界互补滤波是一个简单高效的算法但它有明确的局限性动态加速度干扰这是互补滤波的“天敌”。当物体本身存在较大的线加速度如机器人突然启动、刹车时加速度计测量值不再只反映重力还会包含运动加速度。此时计算出的accel_angle是完全错误的。虽然互补滤波中加速度计权重小但剧烈干扰仍会导致姿态估计出现尖峰误差。应对策略检测运动加速度大小例如加速度计矢量和与重力加速度1g的差值。当检测到较大动态加速度时可以临时增大alpha甚至完全信任陀螺仪alpha1忽略加速度计数据待运动平稳后再恢复。这需要额外的逻辑判断。非水平安装如果传感器不是水平安装那么加速度计计算角度的公式需要根据安装矩阵进行旋转。陀螺仪数据也需要进行相应的坐标变换保证两者在同一个坐标系下融合。要求更高的场景对于高速、高机动性、或者需要同时估计位置和姿态的系统如无人机互补滤波的精度和鲁棒性可能不够。这时就需要升级到扩展卡尔曼滤波EKF或非线性互补滤波如Mahony滤波器、Madgwick滤波器。这些算法能更好地处理动态加速度并提供更优的估计。最后给一个直接的行动建议在你的下一个项目中先别想复杂的。用一阶低通滤波处理加速度计原始数据用互补滤波系数从0.97开始调融合加速度计角度和零偏校正后的陀螺仪积分。把静态漂移和动态响应这两个指标调到一个你能接受的平衡点。把这个基础打牢了你再去研究更高级的滤波器就会明白它们到底在解决什么更具体的问题。滤波器的世界从理解“为什么要融合”和“系数怎么调”开始就成功了一大半。