Why are my filters designed with fdesign so bad?

2 次查看(过去 30 天)
I am getting very poor bandpass and bandstop IIR filters designed using fdesign.bandpass and fdesign.bandstop, using any of the following design methods:
'butter', 'ellip', 'cheby1', 'cheby2'
However, if I call the simple design functions directly (e.g. buttord, followed by butter) then the results are very good.
Just to be clear, I get good results from both methods if the passband/stopband is relatively wide:
However, for very narrow passbands/stopbands, the fdesign filters are garbage. I don't get any error or warning telling me that anything bad happened:
What are the differences between how the design methods are implemented in these two cases? And when should I choose which?
In general, I find the multiple MATLAB/toolbox implementations of the same filter design methods rather convoluted. I have spent many hours reading through all the different incarnations of the documentation and I'm not really any the wiser. In particular, the system objects, dfilt filter objects and designfilt digital filters all seem very inconvenient to use (and all hide subtle differences).
To reproduce my results above, you can run this script:
close all; clear all; clc;
% Filter parameters
Type = 'bandpass'; % Filter type
Fsamp = 1e6; % Sample rate (Hz)
Fp = [9,11]; % Passband edges (Hz)
Fst = [5,20]; % Stopband edges (Hz)
Ap = 0.1; % Passband ripple (dB)
Ast = 60; % Stopband attenuation (dB)
Method = 'butter'; % Filter design method
% Plot parameters
Fplot = logspace(-2, log10(0.5*Fsamp), 32768);
% Design filters and calculate responses
Hsimp = SimpleResponse(Method, Type, Fp, Fst, Ap, Ast, Fsamp, Fplot);
Htbox = FdesignResponse(Method, Type, Fp, Fst, Ap, Ast, Fsamp, Fplot);
% Plot
semilogx(Fplot, 20*log10(abs(Hsimp)), 'LineWidth', 1.5);
hold on; grid on;
semilogx(Fplot, 20*log10(abs(Htbox)), '--r', 'LineWidth', 1.5);
legend('simple', 'fdesign');
ylim([-200,5]);
xlim([0.1*Fp(1), 10*Fp(2)]);
xlabel('Frequency (Hz)');
ylabel('Magnitude (dB)');
which calls SimpleResponse.m:
function H = SimpleResponse(Method, Type, Fp, Fst, Ap, Ast, Fsamp, Fplot)
switch Method
case 'butter'
[n,Wn] = buttord(Fp/(0.5*Fsamp), Fst/(0.5*Fsamp), Ap, Ast);
[z,p,k] = butter(n, Wn, Type);
case 'ellip'
[n,Wn] = ellipord(Fp/(0.5*Fsamp), Fst/(0.5*Fsamp), Ap, Ast);
[z,p,k] = ellip(n, Ap, Ast, Wn, Type);
case 'cheby1'
[n,Wn] = cheb1ord(Fp/(0.5*Fsamp), Fst/(0.5*Fsamp), Ap, Ast);
[z,p,k] = cheby1(n, Ap, Wn, Type);
case 'cheby2'
[n,Wn] = cheb2ord(Fp/(0.5*Fsamp), Fst/(0.5*Fsamp), Ap, Ast);
[z,p,k] = cheby2(n, Ast, Wn, Type);
otherwise
error(['Unsupported method: ' Method]);
end
% Calculate response
SOS = zp2sos(z,p,k);
H = freqz(SOS, 2*pi*Fplot/Fsamp);
and FdesignResponse.m:
function H = FdesignResponse(Method, Type, Fp, Fst, Ap, Ast, Fsamp, Fplot)
if isequal(Type, 'bandpass')
fd = fdesign.bandpass('Fst1,Fp1,Fp2,Fst2,Ast1,Ap,Ast2', Fst(1), Fp(1), Fp(2), Fst(2), Ast, Ap, Ast, Fsamp);
elseif isequal(Type, 'stop')
fd = fdesign.bandstop('Fp1,Fst1,Fst2,Fp2,Ap1,Ast,Ap2', Fp(1), Fst(1), Fst(2), Fp(2), Ap, Ast, Ap, Fsamp);
else
error(['Unsupported filter type: ' Type]);
end
d = design(fd, Method);
% Compute response
H = freqz(d, 2*pi*Fplot/Fsamp);

回答(0 个)

类别

Help CenterFile Exchange 中查找有关 Filter Design 的更多信息

产品


版本

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by