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 Comments

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.

Sign in to comment.

 Accepted Answer

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 Comments

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

Sign in to comment.

More Answers (0)

Products

Release

R2016b

Community Treasure Hunt

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

Start Hunting!