Normalize graph chebyshev filter
显示 更早的评论
Hello, I have this code that corresponds to an analog chebyshev low pass filter, which must have a cutoff frequency of 250 Hz at 0.7, when graphing with freqs I get a signal that does not cut at 0.7. ¿How do I normalize the filter to match the point (250,0.7)?
n = 3; Rp = 0.5;
Wn = [250 2000];
[b a]=cheby1(n,Rp,Wn,'s')
[h,w]=freqs(b,a)
plot(w,abs(h))

2 个评论
try this code but it doesn't work either
Fs = 4400;
Fn = Fs/2;
n = 3; Rp = 0.5;
Wn = [250 2000]/Fn;
[b a]=cheby1(n,Rp,Wn,'s')
[h,w]=freqs(b,a)
plot(w,abs(h))

Chebyshev filter passbands and stopbands are defined differently than for other filters. The stopband is the frequency at which the filter characteristic equals the passband ripple amplitude, not the -6 dB point as with other filter types.
采纳的回答
hello
I tried an iterative correction method . I plot the frf of the filter in dB and 0.7 then correspond to the - 3 dB cutoff amplitude.
Got a good result within 8 iterations :

Code :
n = 3; Rp = 0.5;
Wn = [250 2000];
[b a]=cheby1(n,Rp,Wn,'s') ;
w = logspace(2,4,300); % Frequency vector
[h,ww]=freqs(b,a,w) ;
FRF_dB = 20*log10(abs(h));
FRF_dB2 = FRF_dB;
semilogx(w,FRF_dB);
for ci = 1:8 % loops
% find the - 3dB crossing points
[f1,s0_pos,f2,s0_neg] = crossing_V7(FRF_dB2,w,-3);
cor_coeff1 = Wn(1)/f1;
cor_coeff2 = Wn(2)/f2;
% 2nd iteration
W = [W(1)*cor_coeff1 W(2)*cor_coeff2];
[b a]=cheby1(n,Rp,W,'s') ;
[h,ww]=freqs(b,a,w) ;
FRF_dB2 = 20*log10(abs(h));
end
% check again the - 3dB crossing points
[f11,s0_pos,f22,s0_neg] = crossing_V7(FRF_dB2,w,-3);
semilogx(w,FRF_dB,'b',w,FRF_dB2,'r',f11,s0_pos,'dr',f22,s0_neg,'dr');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [t0_pos,s0_pos,t0_neg,s0_neg] = crossing_V7(S,t,level,imeth)
% [ind,t0,s0,t0close,s0close] = crossing_V6(S,t,level,imeth,slope_sign) % older format
% CROSSING find the crossings of a given level of a signal
% ind = CROSSING(S) returns an index vector ind, the signal
% S crosses zero at ind or at between ind and ind+1
% [ind,t0] = CROSSING(S,t) additionally returns a time
% vector t0 of the zero crossings of the signal S. The crossing
% times are linearly interpolated between the given times t
% [ind,t0] = CROSSING(S,t,level) returns the crossings of the
% given level instead of the zero crossings
% ind = CROSSING(S,[],level) as above but without time interpolation
% [ind,t0] = CROSSING(S,t,level,par) allows additional parameters
% par = {'none'|'linear'}.
% With interpolation turned off (par = 'none') this function always
% returns the value left of the zero (the data point thats nearest
% to the zero AND smaller than the zero crossing).
%
% [ind,t0,s0] = ... also returns the data vector corresponding to
% the t0 values.
%
% check the number of input arguments
error(nargchk(1,4,nargin));
% check the time vector input for consistency
if nargin < 2 | isempty(t)
% if no time vector is given, use the index vector as time
t = 1:length(S);
elseif length(t) ~= length(S)
% if S and t are not of the same length, throw an error
error('t and S must be of identical length!');
end
% check the level input
if nargin < 3
% set standard value 0, if level is not given
level = 0;
end
% check interpolation method input
if nargin < 4
imeth = 'linear';
end
% make row vectors
t = t(:)';
S = S(:)';
% always search for zeros. So if we want the crossing of
% any other threshold value "level", we subtract it from
% the values and search for zeros.
S = S - level;
% first look for exact zeros
ind0 = find( S == 0 );
% then look for zero crossings between data points
S1 = S(1:end-1) .* S(2:end);
ind1 = find( S1 < 0 );
% bring exact zeros and "in-between" zeros together
ind = sort([ind0 ind1]);
% and pick the associated time values
t0 = t(ind);
s0 = S(ind);
if ~isempty(ind)
if strcmp(imeth,'linear')
% linear interpolation of crossing
for ii=1:length(t0)
%if abs(S(ind(ii))) > eps(S(ind(ii))) % MATLAB V7 et +
if abs(S(ind(ii))) > eps*abs(S(ind(ii))) % MATLAB V6 et - EPS * ABS(X)
% interpolate only when data point is not already zero
NUM = (t(ind(ii)+1) - t(ind(ii)));
DEN = (S(ind(ii)+1) - S(ind(ii)));
slope = NUM / DEN;
slope_sign(ii) = sign(slope);
t0(ii) = t0(ii) - S(ind(ii)) * slope;
s0(ii) = level;
end
end
end
% extract the positive slope crossing points
ind_pos = find(sign(slope_sign)>0);
t0_pos = t0(ind_pos);
s0_pos = s0(ind_pos);
% extract the negative slope crossing points
ind_neg = find(sign(slope_sign)<0);
t0_neg = t0(ind_neg);
s0_neg = s0(ind_neg);
else
% empty output
ind_pos = [];
t0_pos = [];
s0_pos = [];
% extract the negative slope crossing points
ind_neg = [];
t0_neg = [];
s0_neg = [];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% % Addition:
% % Some people like to get the data points closest to the zero crossing,
% % so we return these as well
% [CC,II] = min(abs([S(ind-1) ; S(ind) ; S(ind+1)]),[],1);
% ind2 = ind + (II-2); %update indices
%
% t0close = t(ind2);
% s0close = S(ind2);
end
7 个评论
hello Juan
so did you check my submission ?
all the best
Hello Mathieu, if I was checking your answer and thank you for the same, the question is that it was not what I was looking for. What I need is to put together a chebyshev low pass filter with cutoff frequency at 250Hz, which drops to 0.707 at that point.
hello Juan
well , I was maybe fooled by the fact that the code and figure in your initial post deals with a passband filter (and not a lowpass filter)
I can correct that if the real question is for only lowpass filter
so this is the lowpass version
I also came back to a vertical linear scale - not dB - as it seems this was also a bit confusing.
plot :

code :
clc
clearvars
n = 3; Rp = 0.5;
Wn = [250];
threshold = 0.707;
W = Wn;
[b a]=cheby1(n,Rp,Wn,'s') ;
w = linspace(0,400,100); % Frequency vector
[h,ww]=freqs(b,a,w) ;
FRF = abs(h);
FRF2 = FRF;
semilogx(w,FRF);
for ci = 1:8 % loops
% find the "threshold" crossing point~
[f1,s0_pos,f2,s0_neg] = crossing_V7(FRF2,w,threshold);
cor_coeff1 = Wn(1)/f2;
% 2nd iteration
W = W(1)*cor_coeff1;
[b a]=cheby1(n,Rp,W,'s') ;
[h,ww]=freqs(b,a,w) ;
FRF2 = abs(h);
end
% check again the "threshold" crossing point
[f11,s0_pos,f22,s0_neg] = crossing_V7(FRF2,w,threshold);
plot(w,FRF,'b',w,FRF2,'r',f11,s0_pos,'dr',f22,s0_neg,'dr');
legend('initial design','final design');
xlabel('Frequency (Hz)');
ylabel('Modulus');
title('Filter FRF ');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [t0_pos,s0_pos,t0_neg,s0_neg] = crossing_V7(S,t,level,imeth)
% [ind,t0,s0,t0close,s0close] = crossing_V6(S,t,level,imeth,slope_sign) % older format
% CROSSING find the crossings of a given level of a signal
% ind = CROSSING(S) returns an index vector ind, the signal
% S crosses zero at ind or at between ind and ind+1
% [ind,t0] = CROSSING(S,t) additionally returns a time
% vector t0 of the zero crossings of the signal S. The crossing
% times are linearly interpolated between the given times t
% [ind,t0] = CROSSING(S,t,level) returns the crossings of the
% given level instead of the zero crossings
% ind = CROSSING(S,[],level) as above but without time interpolation
% [ind,t0] = CROSSING(S,t,level,par) allows additional parameters
% par = {'none'|'linear'}.
% With interpolation turned off (par = 'none') this function always
% returns the value left of the zero (the data point thats nearest
% to the zero AND smaller than the zero crossing).
%
% [ind,t0,s0] = ... also returns the data vector corresponding to
% the t0 values.
%
% check the number of input arguments
error(nargchk(1,4,nargin));
% check the time vector input for consistency
if nargin < 2 | isempty(t)
% if no time vector is given, use the index vector as time
t = 1:length(S);
elseif length(t) ~= length(S)
% if S and t are not of the same length, throw an error
error('t and S must be of identical length!');
end
% check the level input
if nargin < 3
% set standard value 0, if level is not given
level = 0;
end
% check interpolation method input
if nargin < 4
imeth = 'linear';
end
% make row vectors
t = t(:)';
S = S(:)';
% always search for zeros. So if we want the crossing of
% any other threshold value "level", we subtract it from
% the values and search for zeros.
S = S - level;
% first look for exact zeros
ind0 = find( S == 0 );
% then look for zero crossings between data points
S1 = S(1:end-1) .* S(2:end);
ind1 = find( S1 < 0 );
% bring exact zeros and "in-between" zeros together
ind = sort([ind0 ind1]);
% and pick the associated time values
t0 = t(ind);
s0 = S(ind);
if ~isempty(ind)
if strcmp(imeth,'linear')
% linear interpolation of crossing
for ii=1:length(t0)
%if abs(S(ind(ii))) > eps(S(ind(ii))) % MATLAB V7 et +
if abs(S(ind(ii))) > eps*abs(S(ind(ii))) % MATLAB V6 et - EPS * ABS(X)
% interpolate only when data point is not already zero
NUM = (t(ind(ii)+1) - t(ind(ii)));
DEN = (S(ind(ii)+1) - S(ind(ii)));
slope = NUM / DEN;
slope_sign(ii) = sign(slope);
t0(ii) = t0(ii) - S(ind(ii)) * slope;
s0(ii) = level;
end
end
end
% extract the positive slope crossing points
ind_pos = find(sign(slope_sign)>0);
t0_pos = t0(ind_pos);
s0_pos = s0(ind_pos);
% extract the negative slope crossing points
ind_neg = find(sign(slope_sign)<0);
t0_neg = t0(ind_neg);
s0_neg = s0(ind_neg);
else
% empty output
ind_pos = [];
t0_pos = [];
s0_pos = [];
% extract the negative slope crossing points
ind_neg = [];
t0_neg = [];
s0_neg = [];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% % Addition:
% % Some people like to get the data points closest to the zero crossing,
% % so we return these as well
% [CC,II] = min(abs([S(ind-1) ; S(ind) ; S(ind+1)]),[],1);
% ind2 = ind + (II-2); %update indices
%
% t0close = t(ind2);
% s0close = S(ind2);
end
hello Juan
if my answer has fullfilled your expectations, do you mind accepting it ?
thanks
ready, I accepted it
thanks !!
更多回答(0 个)
类别
在 帮助中心 和 File Exchange 中查找有关 Signal Operations 的更多信息
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!选择网站
选择网站以获取翻译的可用内容,以及查看当地活动和优惠。根据您的位置,我们建议您选择:。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 MathWorks 国家/地区网站并未针对您所在位置的访问进行优化。
美洲
- América Latina (Español)
- Canada (English)
- United States (English)
欧洲
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
