From @VM.CC.PURDUE.EDU:ARD@SIVA.BRISTOL.AC.UK Tue Apr 16 13:15:44 1991 Received: from bank.ecn.purdue.edu by en.ecn.purdue.edu (5.65/1.30jrs) id AA09839; Tue, 16 Apr 91 13:15:44 -0500 Received: from vm.cc.purdue.edu by bank.ecn.purdue.edu (5.65/1.30jrs) id AA01236; Tue, 16 Apr 91 13:15:41 -0500 Message-Id: <9104161815.AA01236@bank.ecn.purdue.edu> Received: from PURCCVM.BITNET by VM.CC.PURDUE.EDU (IBM VM SMTP V2R1) with BSMTP id 5236; Tue, 16 Apr 91 13:15:29 EST Received: from UKACRL.BITNET by PURCCVM.BITNET (Mailer R2.07) with BSMTP id 0562; Tue, 16 Apr 91 13:15:14 EST Received: from RL.IB by UKACRL.BITNET (Mailer R2.07) with BSMTP id 7767; Tue, 16 Apr 91 19:14:46 BST Received: from RL.IB by UK.AC.RL.IB (Mailer R2.07) with BSMTP id 6882; Tue, 16 Apr 91 19:14:45 BST Via: UK.AC.BRIS.SIVA; 16 APR 91 19:14:17 BST Date: Tue, 16 Apr 91 19:13 BST From: "PDP11 Hacker ....." To: WSCOTT@ECN.PURDUE.EDU Subject: Hp48 program Status: OR This program for the HP48 calculates the voltages at the nodes of a general linear circuit by solving the equation : Y.V = I where Y is the (Complex) admittance matrix (I'll define this later), V is a vector of the (unknown) voltages at the nodes, and I is the vector of current sources (known). The program will calculate the voltages at a given frequency or will plot the Amplitude or phase as a function of frequency. Theory ------ Iij *-->-----Zij-----* i j Now, Iij = (Vi-Vj)*Yij (where Yij=1/Zij is the complex admittance) and also Sum(j, Iij) = Sum(current sources connected to node i) by Kirchoff 1 Therefore, we can write the circuit in matrix form as follows: for each admittance Yij, add it to the complex matrix Y[] like this : add Yij to the positions Y[i,i] and Y[j,j] and subtract it from the positions Y[i,j] and [j,i]. Repeat this for all the components in the circuit. Now create a column vector of current sources, with a source I from node i to node j being represented by adding I to the element j and subtracting it from the element i of the vector. Then we can solve the equation for the V vector as given above. There is however a problem! The system is _always_ singular, which corresponds to the physical statement that only potential _differences_ are measured. However, if we assign node 0 as ground, and only put nodes 1 and higher in the matrix, then the system has a solution (in general), so we can procede. This theory can be found (and much more clearly explained!!) in most books on AC circuit Theory. This program converts the inputed components into 3 matrices MatR,MatL,MatC which represent the Resistive, Inductive and Capacitive components of Y[]. The routine F\->V calculates Y[] for the given frequency (Y=MatR + 2*pi*i*MatC + 1/(2*pi*i)*MatL) and then solves the equation Using the program ----------------- Download the source (given at the end of this article) to your HP48 and select its directory. Then select the CST custom menu. An example circuit (the LRC series resonant circuit) is loaded with the program. To see it, Do NOT CLEAR, then COMPILE, select output node 3, 1000 10000 FRNG, and press amplitude. Then Wait! Firstly clear the circuit by pressing CLEAR (2nd Key on the 2nd page of CST) Then enter your circuit (See below for details) Then compile your circuit by pressing COMPILE (3rd key on 2nd page of CST) If you want to see the voltages on the nodes of your circuit at a given frequency, put the frequency on Top of stack, and press F\->V (4th key on 2nd page of CST). A vector is returned to the stack giving the voltages of all the nodes in your circuit. To plot out either the amplitude or phase response, you must first select the node that you wish to plot. To do this, press the 5th key on the 2nd page of CST (labeled with an output icon), and it will prompt you for the node to use. If you would rather select the node from top of stack, then Left shift the output key. Then select the frequency range using the FRNG key (2nd key on 3rd page of CST) which is simply the XRNG function and press either Amplitude (6th key on the 2nd page) or Phase (1st key on 3rd page) and wait for the graph. Entering your circuit --------------------- This program handles 7 types of circuit element which are selected by the first 7 keys on the CST menu. If you would rather take the values from the stack, use the same keys left shifted. In either case, the nodes are prompted for by the program. For each key I'll give the values it expects to get from the stack if left shifted, or prompts for if simply pressed (note: you may use unit objects for the values, provided they are correct!) Resistors - R (Ohms) Capacitors - C (Farads) Inductors - L (Henries) Current source - I(amps) Voltage source - V(volts), r(Ohms - internal resistance must not be 0) IcIs (Current Controlled Current Source - e.g. Bipolar Transistor), Beta and input resistance. The nodes are : Input to------+ +--------- Output To ! ! / O \ O / ! ! ! In from ------+ +----------Output from VcIs (Voltage controlled Current Source - e.g. FET), gm (Siemens) Nodes are as for IcIs Printing out your circuit ------------------------- To print out the components in your circuit press the 3rd key in the 3rd page of CST (labeled with a printer Icon). The stack will be left full of strings representing the elements of your circuit for those users without a printer. Subroutine \->ENG ----------------- This routine may be useful in other programs, so I'll document it here: Input stack 2 : Real number e.g 2: 10000 1 : "Unit as string: 1: "m" Output 1: "string of number 1: "'10_km'" and unit in engineering notation" Note: If there is sufficient interest, I'll document the internal data structures, and also what all the subroutines do ! ******************************************************************************* * This Program may be freely copied, distributed via mail-servers or any * * Network provided my name remains attached to it. It may also be * * modified provided a note is made of the modifications * * * * * * Written by A.R.Duell (ARD @ UK.AC.BRIS.SIVA Janet) * * (ARD@SIVA.BRIS.AC.UK Bitnet) * ******************************************************************************* Subroutines and Variables ------------------------- Print Print out circuit on printer PHASE Display Phase Graph Amplitude Display Amplitude Graph PEQ Phase Equation (used by PHASE) FEQ Amplitude Equation F\->O Takes REAL frequency on top of stack and returns COMPLEX voltage of output node F\->V Takes REAL frequency on top of stack and returns COMPLEX vector of node voltages pOUT Routine to select output node by prompting user sOUT Routine to select output node from Top of Stack cIcIs ! cVcIs ! cVs ! cIs ! Routines to compile components into the addmittance cC ! matrices. Each takes a list in Top of Stack to cL ! specify values and nodes cR ! pR ! pC ! pL ! pIs ! Routines to Get component values into the Variable pVs ! Circuit. Prompt user for all input pIcIs ! (CST menu keys) pVcIs ! sVcIs ! sIcIs ! sVs ! sIs ! Routines to get component values into the Varaible sL ! Circuit. Take value(s) from Top of Stack, Prompt for sC ! Nodes (Left Shifted CST menu keys) sR ! oIcIs ! oVcIs ! oVs ! oIs ! Routines to convert compoent specification list to a oL ! string. Used by Print oC ! oR ! Nodes4 ! Internal routines for Print Nodes2 ! F Frequency EQ Equation PPAR Plot Parameters out Output node (The one that will be plotted) CST Custom Menu COMPILE Convert Circuit to the admittance matrices Term4 Handle 4 terminal components Term2 Handle 2 terminal components PUTV Put 2nd on stack into I vector at position given by TOS PUTM Put 3rd on stack into matrix given by 4th on stack at position given by 1st (column) and 2nd (row) of stack I Current Source Vector MatL Inductive admittance MatC Capacitive Admittance MatR Resistive admittance Cre Create Matrices MAXnodes Returns highest node used in circuit CLC Clears the circuit iVcIs ! Internal routines to enter current sources iIcIs ! Take all parameters off stack \->ENG Real in 2nd on stack, Unit (as String) in TOS, gives a 'Engineering Unit' as a string on TOS. e.g 1E-7 "F" \->ENG gives "'100_nF'" \->SI Removes units if pressent, and converts to SI if possible Nodes Prompts user for node numbers iVs ! iIs ! Internal routines for component entry iL ! (see iVcIs) iC ! Append Append component to circuit iR Internal routine for resistor entry Passive Internal routine for passive component entry Circuit circuit stored as list of lists. ------------------>8-------------------->8-------------->8------------------ %%HP: T(3)A(R)F(.); DIR Print \<< 1 Circuit SIZE FOR j Circuit j GET DUP 1 GET "o" SWAP + OBJ\-> PR1 NEXT \>> PHASE \<< PICT PURGE 'PEQ' STEQ 'F' INDEP AUTO DRAW GRAPH \>> Amplitude \<< PICT PURGE 'FEQ' STEQ 'F' INDEP AUTO DRAW GRAPH \>> PEQ \<< F F\->O ARG \>> FEQ \<< F F\->O ABS \>> F\->O \<< F\->V out GET \>> F\->V \<< 2 * \pi * i * \->NUM DUP MatC * SWAP INV MatL * + MatR + I SWAP / \>> pOUT \<< "Output Node" "" INPUT OBJ\-> sOUT \>> sOUT \<< 'out' STO \>> cIcIs \<< DUP 2 GET OBJ\-> DROP SWAP OVER / 3 PICK 3 GET OBJ\-> DROP 'MatR' 6 ROLLD Term4 INV SWAP 3 GET OBJ\-> 3 DROPN 'MatR' 4 ROLLD Term2 \>> cVcIs \<< DUP 2 GET OBJ\-> DROP SWAP 3 GET OBJ\-> DROP 'MatR' 6 ROLLD Term4 \>> cVs \<< DUP 2 GET OBJ\-> DROP SWAP OVER / 1 \->LIST 3 PICK 3 GET "" 3 ROLLD 3 \->LIST cIs 1 \->LIST 2 SWAP PUT cR \>> cIs \<< DUP 2 GET OBJ\-> DROP SWAP 3 GET OBJ\-> DROP 3 PICK SWAP PUTV SWAP NEG SWAP PUTV \>> cC \<< DUP 2 GET OBJ\-> DROP SWAP 3 GET OBJ\-> DROP 'MatC' 4 ROLLD Term2 \>> cL \<< DUP 2 GET OBJ\-> DROP INV SWAP 3 GET OBJ\-> DROP 'MatL' 4 ROLLD Term2 \>> cR \<< DUP 2 GET OBJ\-> DROP INV SWAP 3 GET OBJ\-> DROP 'MatR' 4 ROLLD Term2 \>> pR \<< "Resistance" "" INPUT OBJ\-> sR \>> pC \<< "Capacitance" "" INPUT OBJ\-> sC \>> pL \<< "Inductance" "" INPUT OBJ\-> sL \>> pIs \<< "Current" "" INPUT OBJ\-> sIs \>> pVs \<< "Voltage" "" INPUT OBJ\-> "Internal R" "" INPUT OBJ\-> sVs \>> pIcIs \<< "\Gb" "" INPUT OBJ\-> "Input Resistance" "" INPUT OBJ\-> sIcIs \>> pVcIs \<< "gm" "" INPUT OBJ\-> sVcIs \>> sVcIs \<< \->SI "VcIs Control" Nodes "VcIs Output" Nodes iVcIs \>> sIcIs \<< \->SI "IcIs Control" Nodes "IcIs Output" Nodes iIcIs \>> sVs \<< SWAP \->SI SWAP \->SI OVER "V" \->ENG \->STR "Source" + Nodes iVs \>> sIs \<< \->SI DUP "A" \->ENG \->STR "Source" + Nodes iIs \>> sL \<< \->SI DUP "H" \->ENG \->STR "Inductor" + Nodes iL \>> sC \<< \->SI DUP "F" \->ENG \->STR "Capacitor" + Nodes iC \>> sR \<< \->SI DUP "\GW" \->ENG \->STR "Resistor" + Nodes iR \>> oIcIs \<< DUP 2 GET OBJ\-> DROP "\GW" \->ENG " Ri= " SWAP + SWAP "\Gb= " SWAP + SWAP + "IcIs " SWAP + Nodes4 \>> oVcIs \<< DUP 2 GET OBJ\-> DROP "S" \->ENG " gm= " SWAP + "VcIs " SWAP + Nodes4 \>> oVs \<< DUP 2 GET OBJ\-> DROP SWAP "V" \->ENG "," + SWAP "\GW" \->ENG + " Source " + Nodes2 \>> oIs \<< DUP 2 GET OBJ\-> DROP "A" \->ENG " Source " + Nodes2 \>> oL \<< DUP 2 GET OBJ\-> DROP "H" \->ENG " Inductor " + Nodes2 \>> oC \<< DUP 2 GET OBJ\-> DROP "F" \->ENG " Capacitor " + Nodes2 \>> oR \<< DUP 2 GET OBJ\-> DROP "\GW" \->ENG " Resistor " + Nodes2 \>> Nodes4 \<< SWAP 3 GET OBJ\-> DROP \->STR " Out To: " SWAP + SWAP \->STR " Out From: " SWAP + SWAP + SWAP \->STR " Control To: " SWAP + SWAP + SWAP \->STR " Control From: " SWAP + SWAP + + \>> Nodes2 \<< SWAP 3 GET OBJ\-> DROP \->STR " To: " SWAP + SWAP \->STR " From: " SWAP + SWAP + + \>> F 10247.5 EQ FEQ PPAR { (1000,-.163546000382) (5000,1.14826715787) F 0 (0,0) FUNCTION Y } out 3 CST { { GROB 21 8 FFFFF1FDFDF1FAFAF1177781FFAFF1FFDFF1FFFFF1FFFFF1 { pR sR } } { GROB 21 8 FFFFF1FFAFF1FFAFF1102081FFAFF1FFAFF1FFFFF1FFFFF1 { pC sR } } { GROB 21 8 FFFFF1FFFFF1F55DF1FAAAF11AA281FFFFF1FFFFF1FFFFF1 { pL sL } } { GROB 21 8 FFFFF1F9CFF1F6BFF11B60E1F6BFF1F9CFF1FFFFF1FFFFF1 { pIs sIs } } { GROB 21 8 FFFFF1F7FFF1F7FFF1F5FFF1340EF1F5FFF1F7FFF1F7FFF1 { pVs sVs } } { "ICIS" { pIcIs sIcIs } } { "VCIS" { pVcIs sVcIs } } { "CLEAR" CLC } COMPILE F\->V { GROB 21 8 FFFFF1FFCFF110CBF1FFC7F1FF70E1FFC7F1F1CBF1FDCFF1 { pOUT sOUT } } { GROB 21 8 FFFFF13FF7F1DEF3E1EDF7F1FB77F1F7B3E1FFC7F1FFFFF1 Amplitude } { "\O/" PHASE } { "FRNG" XRNG } { GROB 21 8 FF1EF1F3EEF17CFEF17FFEF13008F1BFFBF1BFFBF1BFFBF1 Print } } COMPILE \<< MAXnodes Cre 1 Circuit SIZE FOR j Circuit j GET DUP 1 GET "c" SWAP + OBJ\-> NEXT \>> Term4 \<< \-> m v in1 in2 on1 on2 \<< m v NEG on1 in1 PUTM m v NEG on2 in2 PUTM m v on1 in2 PUTM m v on2 in1 PUTM \>> \>> Term2 \<< \-> m v n1 n2 \<< m v n1 n1 PUTM m v n2 n2 PUTM m v NEG n1 n2 PUTM m v NEG n2 n1 PUTM \>> \>> PUTV \<< DUP IF 0 > THEN 1 \->LIST SWAP 'I' 3 ROLLD 3 PICK 3 PICK GET + PUT ELSE DROP2 END \>> PUTM \<< OVER OVER * IF 0 > THEN 2 \->LIST SWAP 3 PICK 3 PICK GET + PUT ELSE 4 DROPN END \>> I [ (.24,0) (0,0) (0,0) ] MatL [[ 14.7058823529 -14.7058823529 0 ] [ -14.7058823529 14.7058823529 0 ] [ 0 0 0 ]] MatC [[ 0 0 0 ] [ 0 .0000001 -.0000001 ] [ 0 -.0000001 .0000001 ]] MatR [[ .02 0 0 ] [ 0 0 0 ] [ 0 0 .1 ]] Cre \<< DUP DUP 2 \->LIST 0 CON DUP 'MatR' STO DUP 'MatC' STO 'MatL' STO 1 \->LIST (0,0) CON 'I' STO \>> MAXnodes \<< 0 1 Circuit SIZE FOR m Circuit m GET 3 GET DUP SIZE 1 SWAP FOR n DUP n GET ROT MAX SWAP NEXT DROP NEXT \>> CLC \<< { } 'Circuit' STO \>> iVcIs \<< 4 \->LIST SWAP 1 \->LIST SWAP "VcIs" 3 ROLLD 3 \->LIST 1 \->LIST Append \>> iIcIs \<< 4 \->LIST 3 ROLLD 2 \->LIST SWAP "IcIs" 3 ROLLD 3 \->LIST 1 \->LIST Append \>> \->ENG \<< SWAP ABS SWAP \-> v u \<< "1_" u + OBJ\-> v * v XPON 3 / FLOOR -4 MAX 3 MIN 5 + { "p" "n" "\Gm" "m" "" "k" "M" "G" } SWAP GET u + "1_" SWAP + OBJ\-> CONVERT \>> \>> \->SI \<< DUP TYPE IF 1 > THEN UBASE OBJ\-> DROP END \>> Nodes \<< DUP " Node From" + "" INPUT OBJ\-> SWAP " Node To" + "" INPUT OBJ\-> \>> iVs \<< 2 \->LIST 3 ROLLD 2 \->LIST SWAP "Vs" 3 ROLLD 3 \->LIST 1 \->LIST Append \>> iIs \<< Passive "Is" 3 ROLLD 3 \->LIST 1 \->LIST Append \>> iL \<< Passive "L" 3 ROLLD 3 \->LIST 1 \->LIST Append \>> iC \<< Passive "C" 3 ROLLD 3 \->LIST 1 \->LIST Append \>> Append \<< Circuit SWAP + 'Circuit' STO \>> iR \<< Passive "R" 3 ROLLD 3 \->LIST 1 \->LIST Append \>> Passive \<< 2 \->LIST SWAP 1 \->LIST SWAP \>> Circuit { { "Vs" { 12 50 } { 0 1 } } { "L" { .068 } { 1 2 } } { "C" { .0000001 } { 2 3 } } { "R" { 10 } { 0 3 } } { "R" { 1000 } { 5 3 } } } END