看了很多介绍设计FIR滤波器的,但鲜有告诉你如何应用的。本文以工程师的角度,从介绍、特点、设计使用三个方面出发,并结合代码介绍如何设计并应用FIR滤波器。同时本文也是个人的学习笔记,学习链接也放在了下面,如果不足,请多指导。
- 介绍:What is FIR filter?
- 特点:Why is FIR filter?
- 如何设计并使用:How to apply a designed FIR filter?
一,介绍:What is FIR filter?
线性时不变系统(LTI)冲激响应按照其是有限长还是无限长可分为FIR(Finite Impulse Response)有限长冲激响应系统以及无限长冲激响应IIR(Infinite Impulse Response)系统。
关于有限长和无现长的理解,如下图的,该图的冲激响应有无限多个,所以就是无限长冲击响应系统;如果冲激响应是有限个,就是有限长冲击响应系统。
二,特点:Why is FIR filter?
1,传递函数:
2,差分方程
其中N代表滤波器阶数,N越大,该滤波器的幅频响应就会越理想,过渡带就会越陡峭,但缺点是带来了更多的计算量。需要综合考量选择。
FIR是全零点系统,也即在Z复平面上Z传递函数的极点全在Z=0处。
FIR滤波器具有多种实现形式,比如直接型、二阶级联型、Lattice结构,都只是上述基本传递函数的不同数学表达形式,没有本质区别,只是在具体算法实现上各具特点。这里将二阶级联形式描述如下。
二阶级联的意思是将上述传递函数分解为二阶多项式块连乘的形式,其数学表达如下:
三,如何设计并使用:How to apply a designed FIR filter?
设计方法
FIR滤波器主要设计方法有窗函数法、“最优法”(切比雪夫逼近法、最小均方差)等。其中窗函数法使用最为广泛。“最优法”也比较常用。
最优法”主要思路就是找到一组脉冲响应,让它的频域响应与期望的滤波器的频域响应尽可能的一致,主要通过两种方法来实现,一个是最小二乘法,另一个是切比雪夫法。
关于最小二乘法(最小均方差法)和切比雪夫逼近法,以及窗函数方法设计原理和流程,已有大牛介绍的比较好,详见
J Pan:如何快速设计一个FIR滤波器(二)zhuanlan.zhihu.com从工程师的角度看这篇文章,虽理论性特别强(有关于连续信号的介绍,个人建议不要太深究。),但是缺乏更贴切的实践和使用介绍。我当时读了几遍之后对实际应用还是有一些疑问。接下来我举个例子,重点从仿真和实际使用来介绍一下。所以这里就不得不提到matlab了。
如何利用MATLAB设计FIR滤波器
如何快速设计一个FIR滤波器(一) 也介绍到,可以通过一种简单设计FIR的方法——零极点法 设计FIR滤波器。
这个方法非常简单,稍加培训,用笔和纸就能完成;当然缺点也很显而易见:零极点设计出的滤波器,只能给出大概的频率响应,对于一些要求较高的系统,显得无能为力。今天我们介绍一种更加严谨的方法。
matlab可以很方便的设计各种滤波器。具体就是命令行输入‘filterDesigner’弹出设计框。如下图,图上方的几个小方框对应着幅频响应、相频响应等。左下方可选择滤波器类型和具体参数等。
举个例子,实现采样频率2kHz,带宽为100Hz~300KHz带通滤波器。
设计一个128阶的FIR带通滤波器,Fstop1为100Hz, Fpass1为110Hz,Fpass2为290Hz, Fstop2为300Hz,Wstop1 为30dB, Wstop2 为30dB。
分析:从下图可以看出,FIR滤波器的相位是线性的。
然后可以拷贝其系数,根据差分方程,进行滤波。
matlab code:
Fs = 2000; % Sampling frequency
T = 1/Fs; % Sample time
L = Fs*1; % Length of signal
t = (0:L-1)*T; % Time vector
% Sum of a 50 Hz , 5.8 , 500 , 120 Hz sinusoid
y = 1*sin(2*pi*50*t) + sin(2*pi*120*t) + sin(2*pi*5.8*t) + sin(2*pi*500*t);
y_target = sin(2*pi*120*t)
N = 128; % Order
Fc1 = 100; % First Cutoff Frequency
Fc2 = 300; % Second Cutoff Frequency
flag = 'scale'; % Sampling Flag
SidelobeAtten = 100; % Window Parameter
% Create the window vector for the design algorithm.
win = chebwin(N+1, SidelobeAtten);
% Calculate the coefficients using the FIR1 function.
b = fir1(N, [Fc1 Fc2]/(Fs/2), 'bandpass', win, flag);
Hd = dfilt.dffir(b);
figure
freqz(b)
filteredSignal = filter(Hd.Numerator,1,y);
% filteredSignal = filter(b,1,y);
figure
subplot(3,1,1)
plot(t,y)
title('Original Signal')
ys = ylim;
subplot(3,1,2)
plot(t,filteredSignal)
title('Target Bandpass Signal')
xlabel('Time (s)'); ylim(ys)
subplot(3,1,3)
plot(t,y_target)
title('Filtered BandPass Signal')
xlabel('Time (s)'); ylim(ys)
C code: 手把手教系列之FIR滤波器设计
其实这部分,对工程师来说很关键啊。
References:
手把手教系列之FIR滤波器设计
如何快速设计一个FIR滤波器(一)
如何快速设计一个FIR滤波器(二)