Circuit Theory Notes¶
I've recently been going through the ARRL handbook (again), and decided I would make notes on it this time. We're going to speed run through the begining though, because I (and probably most people reading this) am relatively familiar with it.
from sympy import *
import math
Basics of Current, Voltage, and Resistance¶
Current is how many electrons are flowing through a stick of metal. "Voltage" is actually called potential difference, but no one says that so I'm going to keep saying "voltage". The voltage is how bad the electrons want to make it there. Resistance is exactly how it sounds, how hard it is for the electrons to make their way through the stick of metal.
To make a metaphor for no reason, imagine you were stood in a field and I was pelting rocks at you and calling you names. The number of rocks I throw at you per second is the current, the force with which I throw them at you is the voltage, and the air resistance against the rocks is the resistance.
The opposite of resistance in conductance. It's simply 1/resistance, and so I ignore it.
Voltage, current, and resistance are related (by definition) through Ohm's Law:
def ohms_law(E, I ,R):
'''
E is the potential difference in Volts.
I is the current in Amperes.
R is the resistance in Ohms.
'''
return Eq(R, E/I)
Resistance is inversely porportional to the cross-sectional area of the path it travels, that's to say, a thicker cable has a lower resistance. It also goes up portionally to how long the path it must travel is, so if a cable has 1 Ohm of resitance, and I double its length, it now has 2 Ohms of resitance.
Copper wire 289.3mm wide amd 1,000 feet long has a resistance of about 0.1239.
Using this as our base-case and the portionality laws above, we can comput the resistance of other kinds of copper cable. The units here were meant to match that of the ARRL handbook, and as such are a weird mix of metric and imperial...
def resistance_of_copper_cable(D, L, R):
'''
Resistance of a coppr cylinder with:
D = diameter in mm.
L = length in feet.
R = resistance in Ohms.
'''
return Eq(R, (L/1000) * ((pi*(189.3/2)**2)/(pi*(D/2)**2)) * 0.1239)
So if I have 100 feet of copper cable, and it's 10mm in diameter, the resistance in ohms will be...
resistance_of_copper_cable(10, 100, Symbol("R"))
resistance_of_copper_cable(10, 100, Symbol("R"))
Then we can use copper as a reference point, and compare other metals to it. The following table compares the resitivity of various metals in terms of copper.
Material | n Times the Resistance of Copper |
---|---|
Copper | 1 (duh) |
Aluminum | 1.6 |
Brass | 3.7 - 4.9 |
Gold | 1.40 |
Iron | 5.68 |
Lead | 12.80 |
Nickel | 5.10 |
Silver | 0.94 |
Steel | 7.6-12.7 |
Zinc | 3.40 |
Tin | 6.70 |
So if a certain length and thickness of copper cable gives me 10 Ohms of resistance, the same cable in gold would be 1.4 * 10 Ohms = 14 Ohms of resistance.
Resistors in Series and Parallel¶
Keeping in mind that we're speed-running this section, we'll say that resistors in series can be added like so:
def resistors_in_series(total_resistance, resistances: list):
'''
The equation of total resistance of n resistors in series, where:
R_total is the total resistance in Ohms.
R_0...n is the individual resistance of each resistors, in Ohms.
'''
return Eq(total_resistance, sum(resistances))
and in parallel like this:
def resistors_in_parallel(total_resistance, resistances: list):
'''
The equation of total resistance of n resistors in parallel, where:
R_total is the total resistance in Ohms.
resistances is the individual resistance of each resistors, in Ohms.
'''
r = [ 1.0 / i for i in resistances ]
r = 1.0 / sum(r)
return Eq(total_resistance, r)
resistors_in_parallel(Symbol("R_total"), [1, 3, 2, 1])
solve(resistors_in_parallel(Symbol("22"), [1, 3, Symbol("R_3"), 1]), Symbol("R_3"))
[-3.0*22/(7.0*22 - 3.0)]
Current In Parallel¶
We can use Ohm's law to find the current in each resistors in a parallel circuit, then the total current of the circuit is the sum of these individual currents. That's to say, current in parallel adds.
def current_in_parallel(total_current, currents: list):
'''
The equation of total current of elements in parallel, where:
total_current is the total resistance in Amperes.
currents is a list of all the individual currents, in Amperes.
'''
return Eq(total_current, sum(currents))
Power and Energy¶
Power is measured in watts, and it represents the total throughput of energy per second. One Watt is one Joule per Second. If we go back to our example, where you are stood in a field and I am throwing rocks at your head and calling you names and informing you that I will be having sex with your mother, then the amount of injury you sustain per second is power. See, if I throw one rock at you, but I throw it very very hard (with a lot of voltage) then it can hurt you just as badly as many rocks thrown at you at a lesser force (voltage). Based off this we can define power as the following:
def power_equation(P, E, I):
'''
This equation defines powere where:
P is the power in Watts.
E is the potential difference in Volts.
I is the current in Amperes.
'''
return Eq(P, I*E)
By substituting in Ohms law we can get the following equations.
p, e, i ,r = symbols("P E I R")
e = solve(ohms_law(e, i, r), e)[0]
power_equation(p, e, i)
p, e, i ,r = symbols("P E I R")
i = solve(ohms_law(e, i , r), i)[0]
power_equation(p, e, i)
Frequency and Period¶
The "period" of a sin wave is how long it takes to complete a cycle. The frequency is the inverse of period. We measure frequency in Hertz (Hz) which is a fun way to say "cycles per second".
AC Circuits¶
Alternating current circuits have current flowing both ways. This is different than pulsating DC (direct current).
t = Symbol('t')
p1 = plot(sin(t)+1, title="Pulsating DC Current vs AC Current", ylabel="Current", show=False)
p2 = plot(sin(t), title="", ylabel="Current", show=False)
p1.append(p2[0])
p1.show()
The important distinction here is that in pulsating DC we still only have current flowing in one direction. In AC we have current flowing both ways, so if a component isn't rated for it- he blows up. The later also has some fun electromagnetic properties that we'll see later.
Electromagnetic waves travel at the speed of light, which is about $3.00*10^8$ meters per second. The wavelength of an electromagnetic wave is given by the following:
def wavelength_equation(wavelength, frequency):
'''
Computes the wavelength of an electromagnetic wave based off it's
frequency, where:
wavelength is the wavelength in meters.
frequency is the frequency in hertz.
'''
return Eq(wavelength, 3e8/frequency)
wavelength_equation(Symbol("lambda"), 4e6)
Phase¶
Phase is the difference in timing between two sin waves. The sin waves below have a phase difference of 45 degrees ($\pi/2$ in real units).
t = Symbol('t')
p1 = plot(sin(t + pi/2), title="Phase Shifted AC Currents", ylabel="Current", show=False)
p2 = plot(sin(t), title="", ylabel="Current", show=False)
p1.append(p2[0])
p1.show()
There are two special cases with phase that are important to keep in mind. One is when the sine waves are 180 degrees ($\pi$ in radians) apart. The other is the above, when they are 90 degrees ($\pi/2$ radians) apart. The first is special because when one wave is at it's lowest point, the other is at it's highest (it's peak). The second is important because when one wave is at 0 the other is at it's peak.
Measuring Power In AC¶
With AC, there are multiple ways to measure current, voltage, and power:
- Instantaneous Voltage and Current: This is just the current/power/voltage at any given moment. For a pure sin wave it would just be $sin(t)$.
- Peak power, which is simply peak voltage times peak current.
- Peak-to-peak current and voltage, which are twice peak current or voltage respectively.
- RMS Voltage and Current root-mean-squared voltage and current
- Peak Envelope Power
- Average Current and Voltage
Instantaneous Values¶
This is exactly what it sounds like. The value of the current/voltage/power at a given instance in time.
Peak Power¶
This is the maximum value of the current/voltage in one cycle. For pure sine Ohms law still applies, so: $$E_{peak}*I_{peak}=P_{peak}$$
def peak_ac_power_from_average_dc_power(peak_ac_power, average_dc_power):
'''
This equation maps the relationship between the peak AC power of a
pure sine wave to the equivalent average DC power, in terms of heating
identical resistors to the same temperature.
Where:
peak_ac_power is the peak AC power in Watts.
average_dc_power is the average DC power in Watts.
'''
return Eq(peak_ac_power, 2*average_dc_power)
Peak-to-Peak¶
Peak-to-peak is the total distance in voltage/current that the sine waves makes in its largest sweep, every cycle. So for normal sine waves, which go from -1 to +1, the peak-to-peak value is 2.
Root-Mean-Squared¶
RMS voltage and current are meant to compare AC power and DC power based off how much of each it would take to heat a resistor to the same temperature. You'll sometimes see this called the effective values of AC voltage and current. For pure sin waves, the required peak AC value is twice that of it's DC counterpart. So
def rms_value_from_peak_value(rms_value, peak_value):
'''
This equation maps the peak current/voltage to the RMS
current/voltage. Where:
rms_value is the value in Volts or Amperes.
peak_value is the value in Volts or Amperes.
'''
return Eq(rms_value, peak_value/sqrt(2))
Average Values¶
Average values are more obvious. They are the sum of the absolute value of the instantaneous values divided by the length of a cycle. We can derive what this would be for sine waves with no phase shift as follows:
2*integrate((sin(t)), (t, 0, pi))/(2*pi)
Peak Envelope Power¶
Peak envelope power is the average power of a single radio frequenchy cycle at the crest of the modulation.

Capacitance and Capacitors¶
Capacitors store charge by baiting electrons to go on to plates, just to find out they aren't connected. If we then remove the way in, the electrons are trapped there are forced to do our bidding. We can use lots of stuff to separate the plates, that stuff is called a dielectric. Sometimes we use a lot of plates, and sometimes we roll the plates up like a cinnamon roll. How big our cinnamon roll is determines how many electrons we can trap.
def energy_in_a_capacitor(energy, voltage, capacitance):
'''
This equation can be used to calculate how much energy is stored in
a capacitor, where:
energy is the energy stored in the capacitor, in Joules.
voltage is the potential difference accross the plates, in Volts.
Capacitrance is the capacitance of the capacitor in Farads.
'''
return Eq(energy, (voltage**2)*capacitance/2)
The capacitrance of a capacitor depends on the area of the plates, the materials we use to make it, and how much energy can jump between the plates, related like so:
def capacitance_of_a_capacitor(capacitance, area, spacing, dielectric, permittivity=8.85e-14):
'''
This equation can be used to calculate the capacitance of a capacitor, where:
capacitance is in Farads.
area is in cm^2.
spacing is the distance between the plates in cm.
dielectric is the dielectric constant of the insulating material.
permittivity is the permittivity of free space, about 8.85x10^-14 F/c
'''
return Eq(capacitance, area*dielectric*permittivity/distance)
Capacitors in parallel act like resistors in series, and capacitors in series act like resistors in parallel.
def capacitors_in_parallel(total_capacitance, capacitances: list):
return Eq(total_capacitance, sum(capacitances))
def capacitors_in_series(total_capacitance, capacitances: list):
'''
This equation calculates the total capacitorance of N capacitors in series, where:
total_capacitance is the total capacitance in Farads.
capacitacnes is a list of all the individual capacitances in Farads.
'''
c = [ 1.0 / i for i in capacitances ]
c = 1.0 / sum(c)
return Eq(total_capacitance, c)
capacitors_in_series(Symbol("total"), [1, 3, 4, 1, 2, 3])
capacitors_in_parallel(Symbol("total"), [1, 3, 4, 1, 2, 3])
Usually capacitors charge and discharge really quickly, but not instantly They follow an exponential function, something like this.
def capacitor_voltage_while_charging(capacitor_voltage, input_voltage, time, resistance, capacitance):
'''
This equation shows the increase in voltage as a capacitor charges, where:
capacitor_voltage is in Volts.
input_voltage is the voltage being placed across the capacitor to charge it, in Volts.
time is time since charging began, in seconds.
resistance is the resistance in the charging circuit in Ohms.
capacitance is the total capacitance of the capacitor, in Farads.
'''
c1 = input_voltage*(1 - math.e**(-time/(resistance*capacitance)))
return Eq(capacitor_voltage, c1)
_cap = 2.0
_res = 2.0
plot(
capacitor_voltage_while_charging(Symbol("v"), 100, Symbol("t"), _res, _cap).rhs,
xlim=(0, 2.5*_res*_cap),
ylabel='Voltage',
xlabel="time",
ylim=(0, 100)
)
<sympy.plotting.plot.Plot at 0x77c4e40fb200>
def capacitor_voltage_while_discharging(capacitor_voltage, input_voltage, time, resistance, capacitance):
'''
This equation shows the decrease in voltage as a capacitor discharges, where:
capacitor_voltage is in Volts.
input_voltage is the voltage being drawn from the capacitor, in Volts.
time is time since charging began, in seconds.
resistance is the resistance in the charging circuit in Ohms.
capacitance is the total capacitance of the capacitor, in Farads.
'''
c1 = input_voltage*(math.e**(-time/(resistance*capacitance)))
return Eq(capacitor_voltage, c1)
plot(
capacitor_voltage_while_discharging(Symbol("v"), 100, Symbol("t"), _res, _cap).rhs,
xlim=(0, 2.5*_res*_cap),
ylabel='Voltage',
xlabel="time",
ylim=(0, 100)
)
<sympy.plotting.plot.Plot at 0x77c4da1a6120>
Capacitors in AC¶
Capacitors in AC are just like capacitors in DC except for one rule. Whereas charged capacitors in DC appear like open circuits, capacitors in AC circuits can both pass and limit current. Instead of converting energy to heat, capacitors store it and return it to the circuit.
The current going into/out of the capacitor, and the voltage across the capacitor are phase shifted such the current leads the voltage by about $\pi/2$ radians (90 degrees).
Capacitive Reactance¶
Capacitive reactance is an opposition to the change of voltage across an element. Capacitive reactance $X_C$ is inversely proportional to the signal frequency and the capacitance.
def capacitive_reactance_formula(capacitive_reactance, frequency, capacitance):
'''
This equation defines capacitive reactance as inversely proportional to
frequency and capacitance, where:
capacitive_reactance is in Ohms.
capacitance is given in Farads.
frequency is given in Hertz
'''
return Eq(capacitive_reactance, 1/(2*pi*frequency*capacitance))
Even though capacitive reactance is specified in Ohms, it does not dissapate energy as heat, it's stored and returned to the circuit the next cycle.
The inverse of capacitive reactance is called susceptance. This topic as a whole will come back later maybe make more sense with some applications. But for now, it's okay to think of reactance simply as a measure of a capacitor's ability to restrict the flow of alternating currents.
Magnetic Fields¶
Magnetic Fields¶
Magnetic fields surround magnets. They contain lines of magnetic flux. All magnetic field lines are closed, which means they form a loop (north to south pole). We measure the strength of magnetic flux lines in Maxwells ($1 Mx = 1V/s$). Magnetic flux density simply refers to the average number of lines per square centimer, we call that the Gauss ($Mx/cm^2$).
Sometimes we measure magnetic flux with the Weber ($Wb = 10^8Mx$). 1 Volt of electromotive force will be created in a loop of wire in which magnetic flux through the loop changes at the rate of 1 weber per second.
Paramagnetic substances are very weakly attracted to a magnet and include materials such as platinum, aluminum, and oxygen. Diamagnetic substance such as copper, carbon, and water, are weakly repelled by a magnet.
When current flows through a conductor, it makes a magnetic field. If you point your right thumb in the direction of the travelling (conventional) current, your fingers will curl in the direction of the magnetic field.

Magnetomotive Force and Field Strength¶
Magnetomotive force ($\Im$) is like the electromotive force, but for magnetic fields. We measure it in Gilberts ($1 Gb = 0.79577 A$). This is distinct from the magnetic field strenght ($H$) measured in Oersteds ($1 Oe = 1Gb/cm$).
def magnetomotive_force_of_an_inductor(magnetomotive_strength, number_turns, current):
'''
This equation calculates the magnetomotive force of a coil of wire, where:
magnetomotive_strength is in gilberts.
number_turns is the total number of turns in the coil creating the field.
current is the DC current in the coil in Amperes.
'''
return Eq(magnetomotive_strength, 10*number_turns*current/(4*math.pi))
def magnetic_field_strength(magnetic_field_strength, magnetomotive_strength, mean_magnetic_path):
'''
This equation calcualtes the magnetic field strength of an inductor where:
magnetic_field_strength is in Oersteds.
mean_magnetic_path is the mean mangetic path length in centimeters.
magnetomotive_strength is in gilberts.
'''
return Eq(magnetic_field_strength, magnetomotive_strength/mean_magnetic_path)
Magnetic Core Properties¶
If you wrap wire around a bit of metal, it becomes a stronger magnet. How many times stronger is called the permeability. Brass has a permeability less than one, so it makes electromagnets weaker. Higher permeability means it's easier to establish a magnetic field in the material. Permiability is like electrical conductivity, but for magnetic fields. Just like how we related conductivity to copper, we related permeability to air.
def permeability_definition(permeability, flux_density, magnetic_field_strength):
'''
Computes the permeability of a material where
permeability is in Henrys.
flux_density is in Gauss.
magnetic_field_strength is in Oersteds.
'''
return Eq(permeability, flux_density/magnetic_field_strength)
Reluctance¶
Reluctance is the reciprocal of permeability (like resistance is to conductivity). Reluctance is related to magnetic force and flux density similarly to Ohm's law.
def reluctance_definition(reluctance, magnetomotive_force, flux_density):
'''
Defines the relationship between reluctance, magnetomotive force, and flux density (which is
similar to Ohm's law) where:
reluctance is in Ampere turns per Weber (inverse Henrys).
magnetomotive_force is in Gilberts.
flux_density is in Gauss.
'''
return Eq(reluctance, magnetomotive_force/flux_density)
Hysteresis¶
When we put a magnetic field on some metal, it maintains some of the magnetyness. The about it retains is called retentivity. Retentivity can be a pain in the butt if we're using AC. The current will go in whatever direction to start, he goes through an inductor, sets up a magnetic field, gets a good thing going on... then BAM! We flip the current the other way around, now not only does he have to rebuild everything, he also has to take down all the crud he built before! You can waste a lost of energy this way.
Saturation¶
The permeability of a magnetic material varies depending with the flux density we're using. At first, flux density goes up REALLY FAST as we increase the magnetizing force, but then it starts to taper off (we get less flux density per gilbert). Since permeability is a measure of how much flux density we get out of our coil compared to air, we get a lower permeability as we get a weaker magnet.
When the ratio of gilebrt-to-gauss gets really high, we've hit "saturation".
As long as we keep the coil current below the saturation level, the inductance of the coil is essentially constant. The datasheet for inductors usually specifies the saturation flux density. Saturation flux density ($\Phi$) can be calculated for AC and DC currents from the following equations:
def flux_density_saturation_dc(flux_density, dc_current, number_of_turns, inductance_index, area):
'''
Compute the flux density point of an inductor being operated with DC current, where:
flux_density is the maximum flux density in gauss.
number_of_turns is the number of wire turns on the inductor.
area is the equivalent area of the magnetic path in qsuare inches (from the data sheet).
dc_current is in amperes
inductance index also comes from the data sheet lmao.
'''
return Eq(flux_density, dc_current*number_of_turns*inductance_index/(10*area))
def flux_density_saturation_ac(flux_density, rms_ac_voltage, frequency, number_of_turns, area):
'''
Compute the flux density point of an inductor being operated with AC current, where:
flux_density is the maximum flux density in gauss.
number_of_turns is the number fo wire turns on the inductor.
area is the equivalent area of the magnetic path in square inches (from the data sheet).
rms_ac_voltage is the root-mean-squared voltage of the operating wave.
frequency is in Mega-Hertz.
'''
return Eq(flux_density, 3.49*rms_ac_voltage/(frequency*number_of_turns*area))
Eddy Currents¶
When an alternating current creates a magnetic field, the magnetic field creates a voltage (in the inductor's core, which is usually conductive), that voltage then creates a current going the other direction. These are called Eddy Currents and they are a pain in the ass. Usually they just cause energy to be dissapated as heat. Iron cores are especially vulnerable to this. We can try to avoid Eddy currents by making our inductors out of thin strips of metal.
Inductance¶
Inductors¶
Inductors make magnetic fields when you put electrons through them. This happens due to magic. Since magic is not allowed to violate the conservation of energy, when they make these magnetic fields they apply a "negative" voltage back to the circuit (so there's a voltage drop across them while they're making their magnetic fields). They're similar to capacitors but instead of storing the energy on a plate they use magnetic fields.

Some inductors and their respective electrical symbols
The "negative" voltage that comes out of the inductor is given by the following equation:
def induced_voltage_equation(voltage_induced, inductance, current_change):
'''
How much opposing voltage is induced in an inductor:
voltage_induces is the induced back-voltage, in Volts.
inductance is the inductance of the inductor, in Henries.
current_change is the rate of change of the current in Amperes per second.
'''
return Eq(voltage_induced, -inductance*current_change)
We measure inductance in Henries. An inductance of 1 Henry generates an induced voltage of one Volt the inducing current is varying at a rate of one Ampere per second. The energy stored in the magnetic field of an inductor is given by the following formula:
def energy_in_magnetic_field(energy, current, inductance):
'''
Computes the energy stored in the magnetic field of an inductor, where:
energy is the energy in the field in Joules.
inductance is the inductance of the inductor in Henries.
current is the current going through the inductor, in Amperes).
'''
return Eq(energy, (current**2) * inductance/2)
You might note it's similar to the equation that calculates the amount of energy in a capacitor. Isn't that nifty?
Magnetic Coupling¶
The magnetic flux we setup in one coil can induce a voltage in another coil. That's called magnetic coupling! We score magnetic coupling with some value between 0 and 1, called the coefficient of coupling. When every magnetic flux lines from coil A bump into coil B- the coils have a coupling coefficient of 1. If none of them do, they have a coefficient of 0.
Inductance in Series and parallel¶
Provided none of the inductors are coupled, then inductance in series and parallel is just like resistance:
def inductance_in_series(total_inductance, individual_inductances: list):
return Eq(total_inductance, sum(individual_inductances))
def inductors_in_parallel(total_inductance, individual_inductances: list):
'''
This equation calculates the total inductance of N inductors in series, where:
total_inductance is the total capacitance in Henries.
individual_inductances is a list of all the individual inductors in Henries.
'''
c = [ 1.0 / i for i in indivudual_inductances ]
c = 1.0 / sum(c) # I'll let you guess why this is a C :3
return Eq(total_inductance, c)
But again, this assumes none of the inductors are coupled.
"Charging" and "Discharing" an Inductor¶
Inductance might add together like resistors, but they store energy like capacitors! While a inductor is "charging" (is recieving power from the power supply) the current is given by the following equation:
def current_entering_an_inductor(current, voltage, resistance, time, inductance):
'''
This equation models the direct current going through an inductor while it is "charging", where:
current is in Amperes (at the time t).
voltage is the voltage of the power supply (in Volts).
resistance is the resistance of the circuit in Ohms.
inductance is the inductance of the inductor in Henries.
'''
return Eq(curent, (voltage/resistance) * (1 - math.e**(-time*resistance/inductacne)))
def current_exiting_an_inductor(current, voltage, resistance, time, inductance):
'''
This equation models the direct current coming out of an inductor while it is "discharging", where:
current is in Amperes (at the time t).
voltage is the voltage of the power supply (in Volts).
resistance is the resistance of the circuit in Ohms.
inductance is the inductance of the inductor in Henries.
'''
return Eq(curent, (voltage/resistance) * (math.e**(time*resistance/inductacne)))