Skip to content
copperhead.sh
Get started

Examples / TI op amp handbook / Differential amplifiers

Difference amplifier

SBOA092B page 74, Difference Amplifier: the subtractor with gain. RI = 1 kΩ and RO = 100 kΩ in both legs; E1 into the inverting input, E2 divided by RI over RO onto the non-inverting input.

E_O = -(R_O / R_I)(E1 - E2) = 100 (E2 - E1)
the schematic, drawn by copperhead from the circuit's netlist
The schematic, drawn by copperhead from the circuit's netlist

The schematic is drawn by copperhead’s drafting engine from this circuit’s netlist, with KiCad’s own library symbols, and it opens in KiCad as figure/difference_amplifier.kicad_sch. The op amp is KiCad’s generic one, since the handbook’s are ideal, and each terminal is a test point named as the program names it. KiCad reads back from the sheet exactly the connections the circuit has; draw_figures.py refuses to write one that does not.

the interconnect view, fang's own projection
The interconnect view, fang's own projection

The interconnect view is fang’s own projection. It names the parts as the program does, so it reads against the code below.

The figure gives every value, so nothing is chosen. The two legs’ ratios are required to match, and the matched ratio is the claim, a_d = 100.

out/simulation.txt, from the decks under out/spice/:

RunMeasuredClaimed
difference, E1 = 1.02 V, E2 = 1.05 V: E_O3 V3 V, holds
difference: E_O / (E2 - E1)99.99100 (a_d) ± 0.1%, holds
common_mode, E1 = E2 = 2 V: E_O-7.8 fV0 V ± 100 µV, holds

The gain is 99.99 rather than 100 because the model’s open-loop gain is 10^6 against a noise gain of 101. The 30 mV difference rides on about 1 V of common mode, and the output carries only the difference.

Terminal window
fang check examples/ti_opamp_handbook/differential_amplifiers/difference_amplifier/difference_amplifier.py
python examples/regenerate.py ti_opamp_handbook/differential_amplifiers/difference_amplifier # needs ngspice
examples/ti_opamp_handbook/differential_amplifiers/difference_amplifier/difference_amplifier.py
"""The difference amplifier, SBOA092B page 74.
Show 11 more lines
E_O = -(R_O / R_I)(E1 - E2) = 100 (E2 - E1)
The subtractor above it on the page with gain: R_I = 1 kOhm and R_O =
100 kOhm in both legs. E1 goes through R_I into the inverting input with R_O
back from the output; E2 is divided by R_I over R_O onto the non-inverting
input. Matched ratios make the output the difference alone, times 100.
The figure gives every value, so nothing was chosen. The bench drives a small
difference, and then the same voltage on both inputs.
"""
import sys
from pathlib import Path
# The handbook's shared parts and bench live in the folder above the sections.
sys.path.insert(0, str(Path(__file__).resolve().parents[2]))
from fang.lang import Parameter, System, kOhm, require
from fang.parts import Resistor
from fang.rationale import Cites
from fang.simulation import OperatingPoint
from handbook import (
Bench,
Claim,
Ground,
OpAmp,
Run,
Terminal,
equals,
over,
ratio,
)
class DifferenceAmplifier(System):
"""The subtractor with R_I = 1 kOhm and R_O = 100 kOhm in both legs."""
figure = Cites(
"E_O = -(R_O/R_I)(E1 - E2) = 100(E2 - E1). Subtractor with amplification",
document="SBOA092B, Handbook of Operational Amplifier Applications",
locator="page 74, Difference Amplifier",
)
a_d = Parameter("1", default=100 * ratio, description="E_O / (E2 - E1)")
e1 = Terminal()
e2 = Terminal()
common = Terminal()
e_out = Terminal()
r_in_top = Resistor(resistance=1 * kOhm)
r_out_top = Resistor(resistance=100 * kOhm)
r_in_bottom = Resistor(resistance=1 * kOhm)
r_out_bottom = Resistor(resistance=100 * kOhm)
amp = OpAmp()
ground = Ground()
def architecture(self):
# The top leg: E1 into the summing point, R_O back from E_O.
self.e1.probe >> self.r_in_top.p1
self.r_in_top.p2 >> self.amp.inverting.signal
self.amp.inverting.signal >> self.r_out_top.p1
self.r_out_top.p2 >> self.amp.output.signal
self.amp.output.signal >> self.e_out.probe
# The bottom leg: E2 divided by R_I over R_O onto the + input.
self.e2.probe >> self.r_in_bottom.p1
self.r_in_bottom.p2 >> self.amp.non_inverting.signal
self.amp.non_inverting.signal >> self.r_out_bottom.p1
self.r_out_bottom.p2 >> self.ground.node
# The grounded terminal between E1 and E2.
self.common.probe >> self.ground.node
def constraints(self):
# The two legs' ratios match, which is what makes it subtract, and
# the matched ratio is the gain.
require(
equals(
over(self.r_out_top.resistance, self.r_in_top.resistance),
over(self.r_out_bottom.resistance, self.r_in_bottom.resistance),
)
)
require(equals(self.a_d, over(self.r_out_top.resistance, self.r_in_top.resistance)))
BENCH = Bench(
page=74,
title="Difference Amplifier",
runs=[
Run(
"difference",
OperatingPoint(),
drive={"e1": "DC 1.02", "e2": "DC 1.05"},
measure={
"e_o": "v({e_out.1})",
"gain": "v({e_out.1}) / (v({e2.1}) - v({e1.1}))",
},
claims=[
Claim("e_o", 3.0, within=0.001, unit="V",
note="100 x (1.05 V - 1.02 V): 30 mV of difference on 1 V of common mode"),
Claim("gain", "a_d", within=0.001),
],
),
Run(
"common_mode",
OperatingPoint(),
drive={"e1": "DC 2", "e2": "DC 2"},
measure={"e_o": "v({e_out.1})"},
claims=[Claim("e_o", 0, within=1e-4, absolute=True, unit="V",
note="2 V on both inputs: nothing to subtract")],
),
],
)

The parts, then the nets and the pads on them.

out/netlist.txt
GND1 Ground -
R1 1 kOhm -
R2 1 kOhm -
R3 100 kOhm -
R4 100 kOhm -
TP1 Terminal -
TP2 Terminal -
TP3 Terminal -
TP4 Terminal -
U1 OpAmp -
Net-(GND1-Pad1) GND1.1 R3.2 TP1.1
Net-(R1-Pad1) R1.1 TP3.1
Net-(R1-Pad2) R1.2 R3.1 U1.IN+
Net-(R2-Pad1) R2.1 TP2.1
Net-(R2-Pad2) R2.2 R4.1 U1.IN-
Net-(R4-Pad2) R4.2 TP4.1 U1.OUT

Every check that ran, and every one left undecided.

out/checks.txt
2 checks, 0 failed, 0 undecided

What the elaborated graph contains, by entity kind.

out/graph.txt
1 block
10 component
20 connection
2 constraint
1 evidence
3 interface
16 pin
16 port
69 total
snapshot sha256:5edee7bf6f32f2f0f5f097ee144b88931c5eaad512bad550f75ad0f4427d4199

All of it, including the KiCad netlist, is in examples/ti_opamp_handbook/differential_amplifiers/difference_amplifier/out/. Rebuild it with:

Terminal window
fang build examples/ti_opamp_handbook/differential_amplifiers/difference_amplifier/difference_amplifier.py