Code covered by the BSD License  

Highlights from
Analytic Circuit Solver

image thumbnail

Analytic Circuit Solver

by

 

Reads in text netlist and uses symbolic toolbox to provide transfer function in analytic form.

abcd_calc_symbolic(file1)
function [abcd,Rin] = abcd_calc_symbolic(file1) 

% function [abcd,Rin] = abcd_calc_symbolic(file1) 
% A sample file might be:
% % opamp1 vi e1 vo
% % r1 e1 0
% % r2 e1 vo

% clear ; 
% file1 = 'trans1.txt' ; 
% file1 = 'pi_network_Y.txt' ; 
% file1 = 'series_L.txt' ; 
% file1 = 'input3.txt' ; 
% file1 = 'tee_network_Z.txt' ; 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   Getting Node Equations       %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
syms Rload ; 
[names n1 n2 n3]=textread(file1,'%s%s%s%s','commentstyle','shell') ; 
% Now add Rs and Rload elements
names(end+1,1) = {'Rload'} ; 
n1(end+1,1) = {'vo'} ; 
n2(end+1,1) = {'0'} ; 
n3(end+1,1) = {''} ; 

allnodes = [n1 n2 n3] ; 

% separate opamp components from passives
a = strvcat(names) ; % collect all component names
a = a(:,1:5) ; % consider just the first five letters
[i1 i2 i] = setxor(['opamp';'trans'],a,'rows') ;  % finds all the components that are not opamp or trans

opi = find(strncmp('opamp',names,5)) ; % finds all the components that are opamps
tri = find(strncmp('trans',names,5)) ; % finds all the components that are transformers

% find current through each passive element
nodes = allnodes(i,:) ; 
nodes(:,3) = [] ; 
passives = names(i) ; 
for i = 1:length(passives)
    switch passives{i}(1)
        case {'r','R','z','Z'} 
            cond{i} = sprintf('1/%s',passives{i}) ; 
        case {'g','G','y','Y'} 
            cond{i} = sprintf('%s',passives{i}) ; 
        case {'c','C'}
            cond{i} = sprintf('s*%s',passives{i}) ; 
        case {'l','L'}
            cond{i} = sprintf('1/s/%s',passives{i}) ; 
    end
end

avoid_kcl_nodes = allnodes(opi,3)' ; % don't do KCL at an output node of an oamp.
kcl_nodes = setdiff(unique(nodes),{'' 'vi' '0' avoid_kcl_nodes{:}}) ; 

for kcl_i = 1:length(kcl_nodes)
    passive_Is = find(sum(strcmp(kcl_nodes(kcl_i),nodes),2)) ; 
    % This has index of passive attached to kcl node
    clear term1 ; 
    for pi = 1:length(passive_Is)
        other_node = setdiff(nodes(passive_Is(pi),:),kcl_nodes(kcl_i)) ; 
        other_node(find(strcmp(other_node,''))) = [] ;
        term1{pi} = sprintf('(%s - %s) * ',other_node{:},kcl_nodes{kcl_i}) ; 
        term1{pi} = sprintf('%s%s',term1{pi},cond{passive_Is(pi)}) ;
    end
    txt0 = sprintf('%s + ',term1{:}) ;
    txt0 = txt0(1:end-3) ; 
    eqn(kcl_i,1) = sym(txt0) ; 
end

% for all elements == to opamp
for i = 1:length(opi)
    Avar{i} = sprintf('A%s',setdiff(names{opi(i)},'opamp')) ; 
    txt0 = sprintf('%s - %s*(%s - %s)',...
        allnodes{opi(i),3},Avar{i},allnodes{opi(i),1},allnodes{opi(i),2}) ;
    eqn(kcl_i+i,1) = sym(txt0) ; 
end
eqn(end+1,1) = 'vi' ; 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   Solving Node Equations       %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

x = setdiff(unique(allnodes),{'' '0'}) ;
for i = 1:length(eqn)
    for i2 = 1:length(x)
        z = zeros(1,length(x)) ; 
        z(i2) = 1 ;
        zcell = num2cell(z) ; 
        A(i,i2) = diff(eqn(i),x{i2}) ; 
    end
end
b = zeros(length(x),1) ; b(end) = 1 ; 
xsoln = A^(-1)*b ; 
if exist('Avar')
    for i = 1:length(Avar)
        xsoln = limit(xsoln,sym(Avar{i}),inf) ; 
    end
end
xsoln = simple(xsoln) ;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   Solving Currents Through each Element      %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

for i = 1:length(passives)
    node1 = nodes{i,1} ; 
    if ~strcmp(node1,'0')
        node1 = xsoln(find(strcmp(x,node1))) ;
    end
    
    node2 = nodes{i,2} ; 
    if ~strcmp(node2,'0')
        node2 = xsoln(find(strcmp(x,node2))) ;
    end
    
    curr(i,1) = (node1 - node2)*cond{i} ; 
end
curr = simple(curr) ; 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   Find Input and Output Currents             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


passive_Is = find(sum(strcmp('vi',nodes),2)) ; 
Iin = sum(curr(passive_Is)) ;  
passive_Is = find(strcmp('Rload',passives)) ;
Irload = curr(passive_Is) ; 

abcd(1,1) = xsoln(end-1)/xsoln(end) ; 
abcd(1,2) = xsoln(end-1)/Irload ; 
abcd(2,1) = Iin/xsoln(end) ; 
abcd(2,2) = Iin/Irload ; 

abcd(1,1) = limit(abcd(1,1),Rload,inf) ; 
abcd(1,2) = limit(abcd(1,2),Rload,0) ; 
abcd(2,1) = limit(abcd(2,1),Rload,inf) ; 
abcd(2,2) = limit(abcd(2,2),Rload,0) ; 
abcd = simple(abcd) ; 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   Calculating Rin and Rout                   %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Rin = simple(1/Iin) ; 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   Outputting the results                     %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% fprintf(1,'For input file:\n') ; 
% type(file1)
% fprintf(1,'The ABCD Matrix is:  \n')
% pretty(abcd)
% fprintf(1,'The Input resistance is:  \n')
% pretty(Rin)

Contact us