This is a story about simulating the frequency response of an emitter follower circuit using traditional electrical engineering circuit analysis of loop equations. John Engelbrecht March 19, 2016
The way that engineers solve circuits is to draw a schematic and use "loop equations" to solve for all currents. This is taught in undergraduate electrical engineering in the first year. Matrix algebra is needed for this, and spreadsheets like Excel can do it. It is tedious to develop the equations. The alternative is using software to do the simulation, and that works fine and doesn't lose any insight. There are free circuit solvers available.
But I learned that Ruby language can handle complex numbers in matrices, and there is a .inverse method. This was so fascinating that I spent five days getting it working. (It took that long to learn that Ruby arrays and matrices are different.) (Freq response involves Laplace transform and s=j 2 pi freq = j omega, pretty intense complex numbers.) I used The Ruby Way 3rd ed.
The details of the three loop equations are not shown, it is routine algebra.
The Ruby Program
# ft5GHzsimv8.rb Ruby in ver 5, get in Vout's missing beta on I2. This gives a very credible gain,
# nasty resonance at 3GHz. Use ver 6 to see where resonance coming from. Ver 8 tries some values to try to stimulate osc.
require 'matrix'
require 'complex'
require 'mathn'
# v7 rbb , rbe , le , lc , beta , re , cbc , cbe , rx = 400.0 , 250.0 , 3.0e-9 , 1.0e-9 , 70.0 , 150.0 , 0.7e-12 , 9.3e-12 , 7
rbb , rbe , le , lc , beta , re , cbc , cbe , rx = 40.0 , 250.0 , 13.0e-9 , 1.0e-7 , 70.0 , 20.0 , 10.7e-12 , 29.3e-12 , 3 # ver 8
# values above are jerked around to make it oscillate, this is no longer a 5GHz transistor, and wiring inductances are way high
# this is for 7 mA, Rbe 250 ohms, falloff of CE gain starting at 71MHz, Beta 70, Cbc guess .7 pF, Cbe 9.3 pF, ft 5GHz
beta1 = 1.0 + beta ; f = 1.0e6
v = Matrix.column_vector([1,0,0]) # this is the voltage matrix on the right of the matrix eqn, input is top element, 1 Volt
# z * i = v 3x3 3x1 3x1 this is the matrix version of Ohm's Law, V = I * R
curr = Matrix.column_vector(3)
trans = File.new("5GHz_EF_sim.txt","w") # write a data file to drive
trans.puts "Rbb Rbe em. inductance coll. inductance Beta Re Cbc Cbe Rx"
trans.puts rbb; trans.puts rbe ;trans.puts le;trans.puts lc;trans.puts beta;trans.puts re;trans.puts cbc;trans.puts cbe;
while f < 10e9 do
w = f * 2 * Math::PI ; combo = (w*le).im + re # s le + re
z00 = rbb+rbe+combo*beta1 ; z01 = rbe + beta*combo ; z02 = rbe + beta1*combo;
z10 = rbe; z11 = rbe+(1.0/(w*cbe).im) ; z12 = rbe ; # these are from the 3 loop equations complex numbers
z20 = (beta * w * lc).im + rbe + beta1*combo ; z21 = (beta * w * lc).im + rbe + beta*combo ;
z22 = (beta1 * w * lc).im + (1.0/(w * cbc).im) + rx + rbe + beta1*combo
z = Matrix[[z00,z01,z02],[z10,z11,z12],[z20,z21,z22]] # the impedance matrix
zinv = z.inverse # the great thing about Ruby is having a matrix inverse method that handles complex numbers!
# http://rubylearning.com/blog/2013/04/04/ruby-matrix-the-forgotten-library/
curr = zinv * v # the currents are known for a given freq, now find output voltage
vout = re * (curr[0,0]*beta1 + curr[1,0] * beta + curr[2,0] * beta1 )
puts vout.polar # to console
puts f/1.0e6 ; puts "-----" ; trans.puts "freq in GHz polar Vout"; # to file
trans.puts f/1.0e9 ; trans.puts vout.polar
# warning, on column vector it seems you have to specify the col. no. as the second item, 0
f *= 1.1
end
trans.close # close the drive file
The Ruby program above is delightfully small when you ignore the comments.
---------some of the data file--------------------
Rbb Rbe em. inductance coll. inductance Beta Re Cbc Cbe
40.0 250.0 1.3e-08 1.0e-07 70.0 20.0 1.07e-11 2.93e-11
freq in GHz polar Vout
0.001
0.830452944401002 # a reasonable low-freq gain for emitter follower
-0.00698500136849333
freq in GHz polar Vout
0.0011
0.830462098487036
-0.0076836387945652
freq in GHz polar Vout
0.00121
0.830473175243993
-0.00845218541361263
freq in GHz polar Vout
...
freq in GHz polar Vout
0.0547636992374931
0.982347756389918 # gain is peaking up
-0.513209297038782
freq in GHz polar Vout
0.0602400691612424
1.01659437298076
-0.606438068992896
freq in GHz polar Vout
0.0662640760773666
1.05473658786922
-0.730079289567898
freq in GHz polar Vout
0.0728904836851033
1.08882937128943
-0.89829589263082
freq in GHz polar Vout
0.0801795320536137
1.09572051523189 # the gain is more than 1, this is where the ckt would do em.-foll. oscillation
-1.12842401355991
freq in GHz polar Vout
0.088197485258975
1.02985870602274
-1.42849957428855
freq in GHz polar Vout
0.0970172337848726
0.855277705994229
-1.76978818173674
freq in GHz polar Vout
0.10671895716336
0.612887061111917
...
freq in GHz polar Vout
0.490370725297852
0.247399107567201
-0.447012069055398
...
freq in GHz polar Vout
1.53899339938804
0.142764067465331
-1.07043087700055
...
freq in GHz polar Vout
9.41234365126862
0.0259441350197038
-1.48599590014427
The gain peak in the chart is where oscillation would happen--but I realize that gain actually has to go infinite to be oscillation. But it would be at the freq of the peak.
This was a neat experience to have a modern programming language facilitate an analysis that was really difficult, even with computers, when I was in college in 1970.