数字滤波器和模拟滤波器(一)

模拟滤波器和数字滤波器(一)

下面介绍模拟滤波器和数字滤波器的频率响应的异同,以及如何使用python地scipy.signal来绘制其频谱响应和冲激阶跃响应。在第二期将谈到如何设计模拟滤波器和数字滤波器。

在正文之间,应该介绍连续时间傅立叶变换(CTFT)和离散时间傅立叶变换(DTFT)。

  1. CTFT 连续时间信号的傅立叶变换

时域连续,且具有非周期性的函数,可以进行傅里叶变换,求出连续的非周期的频谱。

\\\Large \\begin{aligned}X(\\omega) \&= \\int_{-\\infty}\^\\infty x(t)e\^{-j \\omega t}dt \\\\ x(t) \&= \\frac{1}{2\\pi}\\int_{-\\infty}\^\\infty X(\\omega)e\^{j \\omega t}d\\omega \\end{aligned} \\

  1. DTFT 离散时间信号的傅立叶变换

时域离散,且具有非周期性的函数,可以求出连续的周期的频谱 。周期为\(2\pi\)​

\\\Large \\begin{aligned}X(\\omega) \&= \\sum_{-\\infty}\^\\infty x\[ne^{-j \omega n} \\ xn &= \frac{1}{2\pi}\int_{-\pi}^\pi X(\omega)e^{j \omega n}d\omega \end{aligned} \]

最大的区别是,连续时间信号的频谱从0到无穷大,离散时间信号的频谱从0到\(2\pi\)

下面将介绍python当中的模拟和数字滤波器。

1、模拟滤波器

比如一个二阶系统,其传递函数为:

\H(s) = \\frac{udnf\^2}{s\^2+2\*udnf\*dr\*s+udnf\^2} = \\frac{0s\^2+0s+1}{s\^2+1s+1} \\

该传递函数的时域微分形式为:

\\\frac{d\^2y(t) }{dt\^2} + 2\\zeta w_n \\frac{dy(t)}{dt} + w_n\^2y(t) = w_n\^2x(t) \\

python 复制代码
import numpy as np
from scipy.signal import freqs_zpk,freqs,tf2zpk
import matplotlib.pyplot as plt
dr = 1/2          # damping ratio
udnf = 1          # undamped natural frequency
b = [0,0,udnf**2]
a = [1,2*udnf*dr,udnf**2]
z,p,k = tf2zpk(b,a)
w, h = freqs_zpk(z, p, k, worN=np.logspace(-3, 5, 1000))

fig = plt.figure(figsize=(14,7))
ax1 = fig.add_subplot(1, 1, 1)
ax1.set_title('Analog filter frequency response')
ax1.semilogx(w, 20 * np.log10(abs(h)), 'b')
ax1.set_ylabel('Amplitude [dB]', color='b')
ax1.set_xlabel('Frequency [Hz]')
ax1.grid(True)

ax2 = ax1.twinx()
angles = np.unwrap(np.angle(h,deg=True),period=360)
ax2.semilogx(w, angles, 'g')
ax2.set_ylabel('Angle [degree]', color='g')

plt.axis('tight')
plt.show()
python 复制代码
from scipy.signal import impulse,step
print(z,p,k)
t, y = impulse((z,p,k))
t1, y1 = step((z,p,k))
plt.plot(t,y)
plt.plot(t1,y1)
plt.legend(["impulse response","step response"])
plt.show()

上面用到scipy.signal三个函数:

  1. freqs_zpk:基于零极点的模拟频率响应。

    1. worN:频率轴范围。
    2. np.logspace:生成对数序列
  2. freqs:基于有理传递函数的模拟频率响应。在本例中没有用到。尤其注意b、a对应传递函数是正幂。

    复制代码
            b[0]*(jw)**M + b[1]*(jw)**(M-1) + ... + b[M]
    H(w) = ----------------------------------------------
            a[0]*(jw)**N + a[1]*(jw)**(N-1) + ... + a[N]
  3. tf2zpk:传递函数转零极点表示。

2、数字滤波器

比如一个二阶系统:

\H(z) = \\frac{1}{1-(2r\\cos(\\theta)z\^{-1}+r\^2z\^{-2}} = \\frac{z\^2}{z\^2-(2r\\cos(\\theta)z+r\^2} \\

其单位脉冲响应为:

\h\[n = r^n\frac{\sin(n+1)\theta}{\sin\theta}un \]

差分方程表示为:

\y\[n-2r\cos(\theta)yn-1+r^2yn-2 = xn \]

python 复制代码
import numpy as np
from scipy.signal import freqz_zpk,freqz,tf2zpk
import matplotlib.pyplot as plt

fs = 2*np.pi

r = 3/4            
theta = 45/180*np.pi          
b = [1,0,0]
a = [1,-2*r*np.cos(theta),r**2]
z,p,k = tf2zpk(b,a)
w, h = freqz_zpk(z, p, k, worN=np.linspace(-2.5*np.pi,2.5*np.pi,1000),fs=fs)

fig = plt.figure(figsize=(14,7))
ax1 = fig.add_subplot(1, 1, 1)
ax1.set_title('Digital filter frequency response')
ax1.plot(w, 20 * np.log10(abs(h)), 'b')
ax1.set_ylabel('Amplitude [dB]', color='b')
ax1.set_xlabel('w(radians)')
ax1.set_xticks([-3*np.pi,-2*np.pi,-1*np.pi,0,1*np.pi,2*np.pi,3*np.pi],
               [r"$-3\pi$",r"$-2\pi$",r"$-\pi$","0",r"$\pi$",r"$2\pi$",r"$3\pi$"])
ax1.grid(True)

ax2 = ax1.twinx()
angles = np.unwrap(np.angle(h,deg=True),period=360)
ax2.plot(w, angles, 'g')
ax2.set_ylabel('Angle [degree]', color='g')

plt.axis('tight')
plt.show()

该仿真波形和奥本海姆的教材上面的波形一致。

python 复制代码
print(z,p,k)
from scipy.signal import dimpulse, dstep
dt = 0.1
t, y = dimpulse((z,p,k,dt), n=50)
t1, y1 = dstep((z,p,k,dt), n=50)
plt.stem(t,np.squeeze(y),'r')
plt.plot(t1,np.squeeze(y1),'bo-')
plt.legend(["impulse response","step response"])
plt.show()

需要注意:

  1. freqs_zpk:没有采样率这个概念,worN的单位就是Hz

  2. freqz_zpk:有采样率这个概念,fs的默认值为\(2\pi\)​,此时横坐标的单位为弧度。

  3. freqz:使用传递函数绘制频谱响应。在scipy.signal的定义里面,此函数为负幂。

    复制代码
                jw                 -jw              -jwM
       jw    B(e  )    b[0] + b[1]e    + ... + b[M]e
    H(e  ) = ------ = -----------------------------------
                jw                 -jw              -jwN
             A(e  )    a[0] + a[1]e    + ... + a[N]e
  4. 弧度和频率换算举例:设置\(worN=-2\\pi,2\\pi\),如果fs使用默认值\(2\pi Hz\),那么实际横坐标的范围为\(-2\\pi,2\\pi\),即两个周期;如果fs使用\(\pi Hz\),那么实际的横坐标范围为\(-4\\pi,4\\pi\)。其中\(\pi\)弧度对应\(fs/2\) Hz.

相关推荐
aichitang202416 小时前
应用数学与音频信号处理
音视频·信号处理
沫璃染墨1 天前
《从零入门Linux系统篇(五十七):线程篇·十——生产者消费者模型进阶:从环形缓冲区到POSIX信号量》
linux·运维·服务器·开发语言·c++·系统架构·信号处理
沫璃染墨3 天前
《Qt从零入门系列(十二):Qt文件操作详解——从QFile读写到QFileInfo与记事本实战》
开发语言·网络·c++·qt·交互·信号处理·文件
databook4 天前
使用 SciPy 库进行时间序列分析
python·数据分析·scipy
国科安芯5 天前
星载通信载荷信号处理中抗辐射微控制器的选型与适应性分析
人工智能·嵌入式硬件·mcu·信号处理·risc-v·抗辐射·空间信息
这张生成的图像能检测吗5 天前
(综述)边缘计算 × IoT:从机器信号处理到低时延故障诊断
边缘计算·信号处理·故障诊断
weixin_419658315 天前
CAPL的数据类型(一)
车载系统·自动驾驶·汽车·信号处理
学习FPGA的电气小兴兴8 天前
基于FPGA的CORDIC旋转模式实现sin和cos运算_采用EGo1板卡上板验证【FPGA数字信号处理第5讲】
fpga开发·信号处理·数字信号处理·verilog·cordic·ego1·fpga设计入门与提高
jzshmyt18 天前
我用 Python 从零“生成“了一个宇宙,然后让它观察自己(v14)
人工智能·pytorch·python·numpy·matplotlib·空间计算·scipy
流浪00121 天前
Linux系统篇34——信号(六):信号处理期间又来了怎么办?——sigaction、sa_mask、可重入函数与 volatile
linux·运维·面试·操作系统·信号处理·信号