一阶低通滤波(LPF):原理推导、截止频率计算、C语言实现与参数整定

各位同学,大家好。今天我们聊一聊运动控制里最基础、也最常用的一个滤波算法——一阶低通滤波器。

说实话,很多刚入行的工程师觉得这东西太简单了,不就是个加权平均嘛。但我在项目里见过太多因为参数没调好,导致系统震荡甚至飞车的案例。所以今天咱们把它彻底讲透。

1. 从物理直觉到数学推导

先问大家一个问题:为什么需要低通滤波?

你想想看,电机编码器反馈回来的速度信号,是不是经常毛刺很多?尤其是低速的时候,量化误差带来的抖动特别明显。这时候我们就需要把高频的噪声滤掉,保留低频的真实信号。

一阶低通滤波的数学本质,说白了就是一个惯性环节。它的传递函数长这样:

Y(s) / X(s) = 1 / (τs + 1)

其中τ是时间常数。这个公式怎么来的?我简单推导一下。

在时域里,一阶低通滤波的微分方程是:

τ * dy/dt + y = x

做拉普拉斯变换,就得到了上面的传递函数。嗯,这里不展开讲太多数学,大家记住核心结论就行:这个滤波器本质上是一个RC低通电路的数学抽象

核心公式:

离散化后的差分方程:

y[n] = α * x[n] + (1 - α) * y[n-1]

其中α = T / (T + τ),T是采样周期,τ是时间常数。

这个公式看着简单,但里面门道不少。α的取值范围是0到1之间。α越大,滤波效果越弱,响应越快;α越小,滤波效果越强,但响应也越慢。

2. 截止频率的计算

做工程的人,最关心的就是:我到底该设多大的α?

这就涉及到截止频率的概念了。截止频率fc定义为幅值衰减到-3dB(也就是0.707倍)时的频率。

对于一阶低通滤波器,截止频率和时间常数的关系是:

fc = 1 / (2π * τ)

结合α的表达式,我们可以得到:

α = 2π * T * fc / (1 + 2π * T * fc)

反过来,如果已知α,也可以算出截止频率:

fc = α / (2π * T * (1 - α))

我在实际项目中,一般会先根据信号的噪声频率范围,确定一个目标截止频率,然后反算出α。举个例子:

采样周期 T 目标截止频率 fc 计算出的 α
1 ms 10 Hz 0.059
1 ms 50 Hz 0.239
1 ms 100 Hz 0.386

个人经验:我建议大家在调试时,先从一个较小的α开始(比如0.05),然后逐步增大,观察系统的响应。千万不要一上来就设个0.5,那样滤波效果太弱,等于没滤。

3. C语言实现

理论讲完了,咱们直接上代码。这是我个人习惯的写法,结构清晰,适合嵌入式环境:

typedef struct {
    float alpha;      // 滤波系数
    float y_prev;     // 上一次输出值
    uint8_t first;    // 首次运行标志
} LPF_Handle;

void LPF_Init(LPF_Handle *lpf, float alpha) {
    lpf->alpha = alpha;
    lpf->y_prev = 0.0f;
    lpf->first = 1;
}

float LPF_Process(LPF_Handle *lpf, float x) {
    float y;
    
    if (lpf->first) {
        // 首次运行时,直接用输入值初始化
        y = x;
        lpf->first = 0;
    } else {
        // 标准一阶低通滤波
        y = lpf->alpha * x + (1.0f - lpf->alpha) * lpf->y_prev;
    }
    
    lpf->y_prev = y;
    return y;
}

这段代码有几个细节需要注意:

  • 首次初始化:我用了first标志位,第一次滤波时直接输出输入值。如果不这样做,初始的0值会导致输出有一个明显的跳变。
  • 数据类型:全部用float,精度够用。如果MCU不支持浮点,可以用Q格式定点数,但那是另一个话题了。
  • 结构体封装:把状态变量打包,方便多个通道同时使用。

4. 参数整定的实战经验

参数整定,说白了就是找那个「既不慢也不抖」的平衡点。我给大家分享几个我踩过的坑。

我曾经犯过的错:有一次做伺服驱动器的速度环,我把截止频率设得太低(2Hz),结果电机启动时响应慢得像蜗牛,客户直接投诉。后来把截止频率提到20Hz,配合前馈补偿,效果就好了很多。

参数整定的步骤,我建议这样来:

  1. 先确定采样周期T:这个由你的控制周期决定,一般是固定的。
  2. 估算噪声频率:用示波器或者上位机抓一下原始信号,看看毛刺的主要频率成分。
  3. 设定截止频率fc:一般取噪声频率的1/5到1/10。比如噪声是100Hz,fc就设在10-20Hz。
  4. 计算α并测试:用公式算出α,跑一下看看效果。
  5. 微调:如果响应太慢,增大α;如果噪声没滤干净,减小α。

这里有个经验值供参考:对于电机速度环,采样周期1ms时,α通常在0.01到0.1之间。位置环因为信号更平滑,α可以大一些,0.1到0.3都行。

5. 知识体系总览

为了让大家更直观地理解一阶低通滤波在整个运动控制滤波中的位置,我画了一张图:

一阶低通滤波知识体系 一阶低通滤波 原理推导 截止频率计算 C语言实现 参数整定实战 微分方程 → 传递函数 离散化 → 差分方程 fc = 1/(2πτ) α与fc的换算 结构体封装 首次初始化处理 确定采样周期 估算噪声频率 设定fc → 计算α → 微调 核心:在响应速度与滤波效果之间找到平衡

6. 避坑指南

最后,我总结几个常见的坑,大家遇到类似问题可以少走弯路:

  • 采样周期变化:如果控制周期不固定,α需要动态调整。我遇到过有人把α写死,结果换了MCU后滤波效果完全变了。
  • 浮点运算精度:在低端MCU上,float运算可能比较慢。如果α非常小(比如0.001),1-α接近1,浮点精度损失会导致滤波失效。
  • 相位滞后:一阶低通滤波会带来相位滞后,这在闭环控制中可能引起稳定性问题。如果发现系统震荡,先检查是不是滤波滞后太大了。
  • 不要过度滤波:我见过有人把α设到0.001,结果信号平滑得像直线,但系统的动态响应也完全没了。记住,滤波的本质是权衡。

好了,关于一阶低通滤波,今天就聊到这里。这个滤波器虽然简单,但用好了能解决很多实际问题。大家在项目中遇到什么滤波相关的坑,欢迎交流讨论。


专注资料整理