2015-01-20 164 views
2

我试图用buttord函数(实际上,我正在移植一个程序,其中这个函数从MATLAB调用到Python)来设计模拟Butterworth过滤器。MATLAB和SciPy为'buttord'函数提供了不同的结果

我的参数是:

通带频率(FP)= 10赫兹,使Wp的= 2 * PI * 10赫兹

阻带频率(fs)= 100赫兹,给人Ws的= 2 * PI * 100 Hz

通带和阻带损耗/衰减(Rp,Rs)分别为3和80 dB。

在MATLAB中我使用此代码:

Wp = 2 * pi * 10 
Ws = 2 * pi * 100 
Rp = 3 
Rs = 80 
[N, Wn] = buttord(Wp, Ws, Rp, Rs, 's') 

,让我N = 5Wn = 99.581776302

在SciPy的我试图做同样的:

from numpy import pi 
from scipy import signal 
Wp = 2 * pi * 10 
Ws = 2 * pi * 100 
Rp = 3 
Rs = 80 
(N, Wn) = signal.buttord(Wp, Ws, Rp, Rs, analog=True) 

,我得到N = 5Wn = 62.861698649592753。 Wn与MATLAB给出的值不同,并且与Wp非常接近。这里有什么问题?我发现this pull request这可能会解释一些事情:事实证明,MATLAB和SciPy有不同的设计目标(MATLAB试图针对匹配阻带频率进行优化,SciPy试图针对匹配通带频率进行优化)。

我正在使用MATLAB R2013a,Python 3.4.2和SciPy 0.15.0(如果有的话)。

+0

Matlab的信号处理工具通常需要频率相关参数被表示为相对于该奈奎斯特归一化频率。也就是说,Wp = Fp/Fn和Ws = Fs/Fn,其中Fn是奈奎斯特频率。 – Juderb 2015-01-21 04:58:55

+0

@Juderb我正在使用奈奎斯特频率无关紧要的模拟滤波器。从SciPy的文档中,对于模拟滤波器,wp和ws是角频率(例如rad/s)._ – Renan 2015-01-21 11:18:12

回答

3

(我也贴了SciPy的邮件列表如下。)

当你设计一个巴特沃斯滤波器buttord,没有足够的 自由度,以满足所有的设计约束完全相同。因此 是过渡区域的哪一端碰到约束 以及哪一端是“过度设计”的选择。在scipy 0.14.0中做出的改变将该选择从阻带边缘切换到通带边缘。

一张照片会说清楚。下面的脚本生成以下图。 (我将Rp从3改为1.5,-3 dB与Wn的增益一致,这就是为什么你的Wn与Wp相同。)使用旧约定或新约定生成的滤波器都满足设计约束条件。随着新公约的出现,这种反应恰好与通带末端的约束相抵触。

frequency response

import numpy as np 
from scipy.signal import buttord, butter, freqs 
import matplotlib.pyplot as plt 


# Design results for: 
Wp = 2*np.pi*10 
Ws = 2*np.pi*100 
Rp = 1.5  # instead of 3 
Rs = 80 

n_old = 5 
wn_old = 99.581776302787929 

n_new, wn_new = buttord(Wp, Ws, Rp, Rs, analog=True) 

b_old, a_old = butter(n_old, wn_old, analog=True) 
w_old, h_old = freqs(b_old, a_old) 

b_new, a_new = butter(n_new, wn_new, analog=True) 
w_new, h_new = freqs(b_new, a_new) 


db_old = 20*np.log10(np.abs(h_old)) 
db_new = 20*np.log10(np.abs(h_new)) 

plt.semilogx(w_old, db_old, 'b--', label='old') 
plt.axvline(wn_old, color='b', alpha=0.25) 
plt.semilogx(w_new, db_new, 'g', label='new') 
plt.axvline(wn_new, color='g', alpha=0.25) 

plt.axhline(-3, color='k', ls=':', alpha=0.5, label='-3 dB') 

plt.xlim(40, 1000) 
plt.ylim(-100, 5) 

xbounds = plt.xlim() 
ybounds = plt.ylim() 
rect = plt.Rectangle((Wp, ybounds[0]), Ws - Wp, ybounds[1] - ybounds[0], 
        facecolor="#000000", edgecolor='none', alpha=0.1, hatch='//') 
plt.gca().add_patch(rect) 
rect = plt.Rectangle((xbounds[0], -Rp), Wp - xbounds[0], 2*Rp, 
        facecolor="#FF0000", edgecolor='none', alpha=0.25) 
plt.gca().add_patch(rect) 
rect = plt.Rectangle((Ws, ybounds[0]), xbounds[1] - Ws, -Rs - ybounds[0], 
        facecolor="#FF0000", edgecolor='none', alpha=0.25) 
plt.gca().add_patch(rect) 

plt.annotate("Pass", (0.5*(xbounds[0] + Wp), Rp+0.5), ha='center') 
plt.annotate("Stop", (0.5*(Ws + xbounds[1]), -Rs+0.5), ha='center') 
plt.annotate("Don't Care", (0.1*(8*Wp + 2*Ws), -Rs+10), ha='center') 

plt.legend(loc='best') 
plt.xlabel('Frequency [rad/s]') 
plt.ylabel('Gain [dB]') 
plt.show() 
相关问题