Code covered by the BSD License  

Highlights from
Analog Filter Design Toolbox

image thumbnail
from Analog Filter Design Toolbox by James Squire
GUI to design and simulate active (opamp) LP and HP Bessel, Butter, Cheby, and Elliptic filters.

BuildCircuit_UpdateComponents(curStage,nRTol,nCTol,componentName,componentValue)
function curStage = BuildCircuit_UpdateComponents(curStage,nRTol,nCTol,componentName,componentValue)
% BuildCircuit_UpdateComponents is a subfile of the AnalogFilter GUI collection
%
% BuildCircuit_UpdateComponents determines the required R/C values to implement a given 
% zero, first, or second order transfer function, as specified by its zeros, poles, and k.

% James C. Squire, Assistant Professor, Virginia Military Institute
% Matthew R. York, Cadet, Virginia Military Institute
% ver 1.0


schName = curStage.schName;
if nargin==1
    nRTol=0; nCTol=0;
end

if nargin==4 || nargin==5      %given a new component value
    vfCSelect = curStage.vfCSelect;
    vfRSelect = curStage.vfRSelect;
    if isequal(componentName,'Ca')
        vfCSelect(1) = componentValue;
    elseif isequal(componentName,'Cb')
        vfCSelect(2) = componentValue;
    elseif isequal(componentName,'Ra')
        vfRSelect(1) = componentValue;
    elseif isequal(componentName,'Rb')
        vfRSelect(2) = componentValue;
    elseif isequal(componentName,'New Tolerance') % don't change any component yet
    else
        error(['Wrong number of arguments in ' mfilename])
    end
else
    vfCSelect = [];
    vfRSelect = [];
    csCSelectMan = {};
    csRSelectMan = {};
    vnCSelectExp = [];
    vnRSelectExp = [];
    vfCCalc = [];
    vfRCalc = [];
    csCCalc = {};
    csRCalc = {};
end

switch upper(schName)
    case 'SK_LP_KLE1'
        % convert from zpk to polynomial form
        a0 = abs(curStage.k);  % implements a non-inverting biquad, even if given inverting
        b0 = abs(curStage.p(1))^2;
        b1 = -2*real(curStage.p(1));
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        C1 = a0*b1^2*Ca/(a0+b0)^2;
        R1 = 1/(sqrt(a0*C1*Ca));
        if b1*R1*Ca-2==0
            R2 = Inf;  % not present
        else
            R2 = R1/(b1*R1*Ca-2);
        end
        if abs(R2)>1e12, R2=Inf; end
        vfCCalc = [C1];
        vfRCalc = [R1 R2];
    case 'SK_LP_KGT1'
        % convert from zpk to polynomial form
        a0 = abs(curStage.k);  % implements a non-inverting biquad, even if given inverting
        b0 = abs(curStage.p(1))^2;
        b1 = -2*real(curStage.p(1));
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            Ra = 10e3;
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [Ra];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        Ra = vfRSelect(1);
        R2 = Ra*(a0-b0)/b0;
        R1 = (sqrt(8*Ra*R2*b0+b1^2*Ra^2)-b1*Ra)/(2*b0*Ca*R2);
        C1 = 1/(b0*Ca*R1^2);
        vfCCalc = [C1];
        vfRCalc = [R1 R2];
    case 'SK_HP_KLE1'
        % convert from zpk to polynomial form
        a2 = abs(curStage.k);  % implements a non-inverting biquad, even if given inverting
        b0 = abs(curStage.p(1))^2;
        b1 = -2*real(curStage.p(1));
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        C1 = Ca*(1-a2)/a2;
        R1 = (a2+1)/(b1*Ca);
        R2 = a2/(b0*R1*Ca^2);
        vfCCalc = [C1];
        vfRCalc = [R1 R2];
    case 'SK_HP_KGT1'
        % convert from zpk to polynomial form
        a2 = abs(curStage.k);  % implements a non-inverting biquad, even if given inverting
        b0 = abs(curStage.p(1))^2;
        b1 = -2*real(curStage.p(1));
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        R1 = 4/(Ca*(b1+sqrt(b1^2+8*b0*(a2-1))));
        R2 = (b1+sqrt(b1^2+8*b0*(a2-1)))/(4*b0*Ca);
        R3 = R1*(a2-1);
        vfCCalc = [];
        vfRCalc = [R1 R2 R3];
    case 'MFB_LP'
        % convert from zpk to polynomial form
        a0 = -abs(curStage.k);  % implements an inverting biquad, even if given NI
        b0 = abs(curStage.p(1))^2;
        b1 = -2*real(curStage.p(1));
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        R1 = b1/(2*b0*Ca-a0*Ca);
        R2 = -R1*b0/a0;
        C1 = 1/(b0*Ca*R1^2);
        vfCCalc = [C1];
        vfRCalc = [R1 R2];
    case 'MFB_Z_LP'
        % convert from zpk to polynomial form
        a0 = abs(curStage.z(1))^2 * abs(curStage.k); % MFB is NI, even if k is neg
        a2 = abs(curStage.k);
        b0 = abs(curStage.p(1))^2;
        b1 = -2*real(curStage.p(1));
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        kf = (a0+a2*b0)/(a2*(a0+a2*(b0+b1^2)));
        C1 = Ca*(1-a2*kf)*(-a0+a2*kf*(a0+a2*b1^2))/(a2^3*b1^2*kf^2);
        R1 = (1-a2*kf)/(a2*b1*C1*kf);
        R2 = R1*(1/(a2*kf)-1);
        R3 = R1/(b1*Ca*R1 - 2);
        vfCCalc = [C1];
        vfRCalc = [R1 R2 R3];
    case 'MFB_Z_HP'
        % convert from zpk to polynomial form
        a0 = abs(curStage.z(1))^2 * abs(curStage.k); % MFB is NI, even if k is neg
        a2 = abs(curStage.k);
        b0 = abs(curStage.p(1))^2;
        b1 = -2*real(curStage.p(1));
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        kf = (b0^2*(a0+a2*b0))/(a0*(a2*b0^2+a0*(b0+b1^2)));
        C1 = Ca*(a2*b0-a0)/a0;
        R1 = (C1+2*Ca)/(b1*Ca^2);
        R2 = R1*(1+C1/Ca-a2*kf)/(a2*kf);
        R3 = 1/(b0*Ca^2*R1);
        vfCCalc = [C1];
        vfRCalc = [R1 R2 R3];
    case 'AM_LP_N'
        % convert from zpk to polynomial form
        a0 = abs(curStage.k);  % implements a non-inverting biquad, even if given inverting
        b0 = abs(curStage.p(1))^2;
        b1 = -2*real(curStage.p(1));
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        R1 = 1/(Ca*sqrt(b0));
        R2 = 1/(b1*Ca);
        R3 = 1/(a0*Ca^2*R1);
        vfCCalc = [];
        vfRCalc = [R1 R2 R3];
    case 'AM_LP_I'
        % convert from zpk to polynomial form
        a0 = -abs(curStage.k);  % implements an inverting biquad, even if given NI
        b0 = abs(curStage.p(1))^2;
        b1 = -2*real(curStage.p(1));
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        R1 = 1/(Ca*sqrt(b0));
        R2 = 1/(b1*Ca);
        R3 = -1/(a0*Ca^2*R1);
        vfCCalc = [];
        vfRCalc = [R1 R2 R3];
    case 'AM_HP'
        % convert from zpk to polynomial form
        a2 = -abs(curStage.k);  % implements an inverting biquad, even if given NI
        b0 = abs(curStage.p(1))^2;
        b1 = -2*real(curStage.p(1));
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        C1 = -a2*Ca;
        R1 = 1/(Ca*sqrt(b0));
        R2 = 1/(b1*Ca);
        vfCCalc = [C1];
        vfRCalc = [R1 R2];
    case 'AM_Z'
        % convert from zpk to polynomial form
        a0 = -abs(curStage.z(1))^2 * abs(curStage.k);  % implements an inverting biquad, even if given NI
        a2 = -abs(curStage.k);       % implements an inverting biquad, even if given NI
        b0 = abs(curStage.p(1))^2;
        b1 = -2*real(curStage.p(1));
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        C1 = -a2*Ca;
        R1 = 1/(Ca*sqrt(b0));
        R2 = 1/(b1*Ca);
        R3 = -1/(a0*R1*Ca^2);
        vfCCalc = [C1];
        vfRCalc = [R1 R2 R3];
    case 'SO_LP_N_KLE1'
        % convert from zpk to polynomial form
        a0 = abs(curStage.k); % implements a non-inverting stage, even if given inverting
        b0 = -curStage.p(1);
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        R1 = 1/(a0*Ca);
        if b0==a0
            R2 = inf;
        else
            R2 = 1/(Ca*(b0-a0));
        end
        vfCCalc = [];
        vfRCalc = [R1 R2];
    case 'SO_LP_N_KGT1'
        % convert from zpk to polynomial form
        a0 = abs(curStage.k); % implements a non-inverting stage, even if given inverting
        b0 = -curStage.p(1);
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            Ra = 10e3;
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [Ra];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        Ra = vfRSelect(1);
        R1 = 1/(b0*Ca);
        R2 = Ra*(a0*R1*Ca-1);
        vfCCalc = [];
        vfRCalc = [R1 R2];
    case 'SO_LP_I'
        % convert from zpk to polynomial form
        a0 = -abs(curStage.k); % implements an inverting stage, even if given NI
        b0 = -curStage.p(1);
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            Ra = 2/(Ca*b0);
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [Ra];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        Ra = vfRSelect(1);
        R1 = a0*Ra^2*Ca/(1-b0*Ca*Ra);
        R2 = -R1/(a0*Ca*Ra);
        vfCCalc = [];
        vfRCalc = [R1 R2];
    case 'SO_HP_N_KLE1'
        % convert from zpk to polynomial form
        a1 = abs(curStage.k); % implements a non-inverting stage, even if given inverting
        b0 = -curStage.p(1);
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        R1 = (1-a1)/(b0*Ca);
        R2 = a1/(b0*Ca);
        vfCCalc = [];
        vfRCalc = [R1 R2];
    case 'SO_HP_N_KGT1'
        % convert from zpk to polynomial form
        a1 = abs(curStage.k); % implements a non-inverting stage, even if given inverting
        b0 = -curStage.p(1);
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            Ra = 10e3;
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [Ra];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        Ra = vfRSelect(1);
        R1 = 1/(b0*Ca);
        R2 = Ra*(a1-1);
        vfCCalc = [];
        vfRCalc = [R1 R2];
    case 'SO_HP_I' 
        % convert from zpk to polynomial form
        a1 = -abs(curStage.k); % implements an inverting stage, even if given NI
        b0 = -curStage.p(1);
        if nargin<4
            % Create default values.
            Ca = 1e-9;
            % load the variables
            vfCSelect = [Ca];
            vfRSelect = [];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ca = vfCSelect(1);
        R1 = 1/(b0*Ca);
        R2 = -a1*R1;
        vfCCalc = [];
        vfRCalc = [R1 R2];
    case 'ZO_N_KLE1'
        % convert from zpk to polynomial form
        a0 = abs(curStage.k1); % implements a non-inverting stage, even if given inverting
        if nargin<4
            % Create default values.
            Ra = 10e3;
            % load the variables
            vfCSelect = [];
            vfRSelect = [Ra];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ra = vfRSelect(1);
        if a0==1
            R1 = inf;
        else
            R1 = Ra*a0/(1-a0);
        end
        vfCCalc = [];
        vfRCalc = [R1];
    case 'ZO_N_KGT1'
        % convert from zpk to polynomial form
        a0 = abs(curStage.k1); % implements a non-inverting stage, even if given inverting
        if nargin<4
            % Create default values.
            Ra = 10e3;
            % load the variables
            vfCSelect = [];
            vfRSelect = [Ra];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ra = vfRSelect(1);
        R1 = Ra*(a0-1);
        vfCCalc = [];
        vfRCalc = [R1];
    case 'ZO_I'
        % convert from zpk to polynomial form
        a0 = -abs(curStage.k); % implements a inverting stage, even if given NI
        if nargin<4
            % Create default values.
            Ra = 10e3;
            % load the variables
            vfCSelect = [];
            vfRSelect = [Ra];
        end
        % Round components to given tolerance
        [vfCSelect, vfRSelect] = RoundComponent(vfCSelect, vfRSelect, nCTol, nRTol);
        % Calculate R,C Calc vectors given R,C Select vectors
        Ra = vfRSelect(1);
        R1 = -a0*Ra;
        vfCCalc = [];
        vfRCalc = [R1];
    otherwise
        error(['unknown circuit title name ' schName ' in' mfilename])
end

% Round calculated components to given tolerance for new z1,p1,k1 calculations
for i=1:length(vfCCalc)
    vfCCalc(i) = Utility_Round2Tolerance(vfCCalc(i),nCTol);
end
for i=1:length(vfRCalc)
    vfRCalc(i) = Utility_Round2Tolerance(vfRCalc(i),nRTol);
end

% create strings representing the numbers
csCSelectMan = {};  % start by defining variables so later assignment operators always work
vnCSelectExp = [];
csRSelectMan = {};
vnRSelectExp = [];
csCCalc = [];
csRCalc = [];
for i=1:length(vfCSelect)
    [csCSelectMan{i}, vnCSelectExp(i)] = Utility_EngOutput(vfCSelect(i),4,'',-12,-3);
end
for i=1:length(vfRSelect)
    [csRSelectMan{i}, vnRSelectExp(i)] = Utility_EngOutput(vfRSelect(i),4,'',0,6);
end
for i=1:length(vfCCalc)
    csCCalc{i} = Utility_EngOutput(vfCCalc(i),4,'F');
    if abs(vfCCalc(i)) < 1e-14
        vfCCalc(i) = 0;
        csCCalc{i} = 'Not present';
    end
end
for i=1:length(vfRCalc)
    csRCalc{i} = Utility_EngOutput(vfRCalc(i),4,'ohm');  
    if vfRCalc(i) > 1e14 | vfRCalc(i) < -1e14
        vfRCalc(i) = inf;
        csRCalc{i} = 'Not present';
    end
end

% fill up curStage with calculated values
curStage.vfCSelect = vfCSelect;
curStage.vfRSelect = vfRSelect;
curStage.csCSelectMan = csCSelectMan;
curStage.csRSelectMan = csRSelectMan;
curStage.vnCSelectExp = vnCSelectExp;
curStage.vnRSelectExp = vnRSelectExp;
curStage.vfCCalc = vfCCalc;
curStage.vfRCalc = vfRCalc;
curStage.csCCalc = csCCalc;
curStage.csRCalc = csRCalc;

% Determine z1,p1,k1,Q1,wp1,wz1 values using rounded components
curStage = BuildCircuit_FindZ1P1K1(curStage);


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                            Round Component Value                          %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [vfCCalc, vfRCalc] = RoundComponent(vfCCalc, vfRCalc, nCTol, nRTol)
% Round calculated components to given tolerance for new z1,p1,k1 calculations
for i=1:length(vfCCalc)
    vfCCalc(i) = Utility_Round2Tolerance(vfCCalc(i),nCTol);
end
for i=1:length(vfRCalc)
    vfRCalc(i) = Utility_Round2Tolerance(vfRCalc(i),nRTol);
end

Contact us at files@mathworks.com