Examples
Non Inverting Amplifier
Here is an example of a typical schematic with exception handling.
#!/usr/bin/env python3
from svg_schematic import (
Schematic, Amp, Dot, Ground, Label, Pin, Resistor, Source, Wire
)
from inform import Error, error, os_error
try:
with Schematic(filename = "noninverting.svg", line_width=2):
vin = Source(kind='sine')
Label(C=vin.p, name='Vin', loc='n')
Ground(C=vin.n)
amp = Amp(pi=vin.p, xoff=100, kind='oa')
Label(C=amp.ni, xoff=-25, name='Vf', loc='n')
Wire([vin.p, amp.pi])
out = Pin(C=amp.o, xoff=50, name='out', w=2)
Wire([amp.o, out.C])
oj = Dot(C=amp.o, xoff=25)
r1 = Resistor(p=amp.ni, off=(-25, 50), name='R1', orient='v')
Wire([r1.N, amp.ni], kind='|-')
r2 = Resistor(C=amp.C, yoff=75, name='R2')
Wire([r1.p, r2.W], kind='|-')
Wire([oj.C, r2.E], kind='|-')
fj = Dot(C=r2.W, xoff=-25)
Ground(C=r1.n)
except Error as e:
e.report()
except OSError as e:
error(os_error(e))
Inverting Amplifier
This schematic uses line_width = 1
give the schematic a lighter look.
It uses a 16 point serif font.
#!/usr/bin/env python3
from svg_schematic import (
Schematic, Amp, Dot, Ground, Label, Pin, Resistor, Source, Wire
)
from inform import Error, error, os_error
try:
with Schematic(
filename = "inverting.svg",
font_size=16,
font_family='serif'
):
vin = Pin(kind='in', name='in', w=1.5)
vout = Pin(C=vin.C, xoff=350, kind='out', name='out', w=2)
Wire([vin.C, vout.C])
rin = Resistor(W=vin.C, xoff=25, name='Rin')
vg = Dot(C=rin.E, xoff=25)
rfb = Resistor(W=vg.C, xoff=25, name='Rfb')
oj = Dot(C=rfb.E, xoff=25)
amp = Amp(C=rfb.C, yoff=75, orient='-', kind='oa')
Wire([oj.C, amp.o], kind='|-')
gnd = Ground(C=amp.pi, xoff=-25, orient='h|')
Wire([gnd.C, amp.pi])
Wire([vg.C, amp.ni], kind='|-')
Label(C=vg.C, name='Vg', loc='sw')
except Error as e:
e.report()
except OSError as e:
error(os_error(e))
Charge Pump
This example has a transparent background and so all wires terminate at
terminals rather than passing underneath components. The labels are intended to
be rendered by Latex.
It sets line_width
to 2 give the schematic a heavier look.
#!/usr/bin/env python3
from svg_schematic import Schematic, Capacitor, Diode, Ground, Pin, Wire, Dot, with_x
from inform import Error, error, os_error
try:
with Schematic(
filename = "charge-pump.svg", line_width=2, background='none'):
vin = Pin(kind='in', name=r'$V_{\rm in}$', w=2)
p1 = Pin(C=vin.C, yoff=150, kind='in', name=r'$\phi_1$', w=2)
p2 = Pin(C=p1.C, yoff=50, kind='in', name=r'$\phi_2$', w=2)
d1 = Diode(a=vin.C, xoff=25, orient='h')
c1 = Capacitor(p=d1.c, off=(25, 25), orient='v')
d2 = Diode(a=d1.c, xoff=50, orient='h')
c2 = Capacitor(p=d2.c, off=(25, 25), orient='v')
d3 = Diode(a=d2.c, xoff=50, orient='h')
c3 = Capacitor(p=d3.c, off=(25, 25), orient='v')
d4 = Diode(a=d3.c, xoff=50, orient='h')
c4 = Capacitor(p=d4.c, off=(25, 25), orient='v')
d5 = Diode(a=d4.c, xoff=50, orient='h')
c5 = Capacitor(p=d5.c, off=(25, 25), orient='v')
vout = Pin(C=d5.c, xoff=75, kind='out', name=r'$V_{\rm out}$', w=2)
Ground(t=c5.n)
Wire([vin.t, d1.a])
Wire([d1.c, d2.a])
Wire([d2.c, d3.a])
Wire([d3.c, d4.a])
Wire([d4.c, d5.a])
Wire([d5.c, vout.t])
Wire([with_x(vin.t, c1.C), c1.p])
Wire([with_x(vin.t, c2.C), c2.p])
Wire([with_x(vin.t, c3.C), c3.p])
Wire([with_x(vin.t, c4.C), c4.p])
Wire([with_x(vin.t, c5.C), c5.p])
Wire([p1.t, c1.n], kind='-|')
Wire([p2.t, c2.n], kind='-|')
co = Dot(C=with_x(p1.C, c2.C), color='white') # wire cross over
Wire([p1.t, c3.n], kind='-|')
Wire([p2.t, c4.n], kind='-|')
except Error as e:
e.report()
except OSError as e:
error(os_error(e))
Inverter
This example has a transparent background and so all wires terminate at
terminals rather than passing underneath components. The labels are intended to
be rendered by Latex.
It sets line_width
to 2 give the schematic a heavier look.
#!/usr/bin/env python3
from svg_schematic import Schematic, MOS, Ground, Gate, Label, Pin, Wire, midpoint
from inform import Error, error, os_error
try:
with Schematic(filename = 'inverter.svg', line_width=2, background='none'):
# transistor version
mp = MOS(kind='p')
mn = MOS(N=mp.S, kind='n')
vin = Pin(C=midpoint(mp.g, mn.g), xoff=-50, kind='in', name=r'$V_{\rm in}$', w=2)
vout = Pin(C=midpoint(mp.d, mn.d), xoff=50, kind='out', name=r'$V_{\rm out}$', w=2)
Label(C=mp.s, loc='n', name=r'$V_{\rm dd}$')
Ground(C=mn.s)
Wire([vin.t, mp.g], kind='-|')
Wire([vin.t, mn.g], kind='-|')
Wire([vout.t, mp.d], kind='-|')
Wire([vout.t, mn.d], kind='-|')
# gate version
inv = Gate(N=mn.S, yoff=25, kind='inv')
vin = Pin(t=inv.i, xoff=-25, kind='in', name=r'$V_{\rm in}$', w=2)
vout = Pin(t=inv.o, xoff=25, kind='out', name=r'$V_{\rm out}$', w=2)
Wire([inv.o, vout.t])
Wire([inv.i, vin.t])
except Error as e:
e.report()
except OSError as e:
error(os_error(e))
Oscillator
This example has a transparent background and so all wires terminate at
terminals rather than passing underneath components. The labels are intended to
be rendered by Latex.
This schematic uses line_width = 2
give the schematic a heavier look.
#!/usr/bin/env python3
from svg_schematic import (
Schematic, Capacitor, MOS, Inductor, Label, Source, Wire, Crossing,
midpoint, shift, shift_y,
)
from inform import Error, error, os_error
try:
with Schematic(filename = "oscillator.svg", background='none', line_width=2):
# resonator
vdd = Label(loc='n', nudge=10, name=r'$V_{\rm dd}$')
Wire([vdd.C, shift_y(vdd.C, 25)])
ll = Inductor(p=shift(vdd.C, -125, 25), orient='v', name=r'$\frac{1}{2} L$')
lr = Inductor(p=shift(vdd.C, 125, 25), orient='v|', name=r'$\frac{1}{2} L$')
c = Capacitor(C=midpoint(ll.n, lr.n), orient='h', name='$C$')
Wire([ll.p, lr.p])
Wire([ll.n, c.p])
Wire([lr.n, c.n])
# gain stage
ml = MOS(d=ll.n, yoff=75, orient='|')
mr = MOS(d=lr.n, yoff=75, orient='')
Wire([ll.n, ml.d])
Wire([lr.n, mr.d])
cross = Crossing(C=midpoint(ml.g, mr.g), yoff=-50, orient='v', pass_under='white')
Wire([ml.g, cross.pi], kind='-|')
Wire([mr.g, cross.ni], kind='-|')
Wire([lr.n, cross.po], kind='|-')
Wire([ll.n, cross.no], kind='|-')
Wire([ml.s, shift_y(ml.s, 12), shift_y(mr.s, 12), mr.s])
Source(p=midpoint(ml.s, mr.s), yoff=12, kind='idc', value=r'$I_{\rm ss}$')
except Error as e:
e.report()
except OSError as e:
error(os_error(e))
Passive Low Pass Filter
This example uses QuantiPhy to compute the values
for the components in a low pass filter and then constructs the schematic using
those values. It sets line_width
to 2 and employs dots at wire junctions to
give the schematic a heavier look.
"""
Draw a 5th Order Low Pass Passive Filer with Maximally Flat Envelope Delay
Use the following parameters:
Fo = 1MHz — 3dB corner frequency
Rref = 50Ω — termination impedance
Design equations:
ω0 = 2*π*Fo
Lscale = Rref/ω0
Cscale = 1/(Rref*ω0)
Rs = 1.0000 * Rref "Ω"
C1 = 0.2715 * Cscale "F"
L2 = 0.6541 * Lscale "H"
C3 = 0.8892 * Cscale "F"
L4 = 1.1034 * Lscale "H"
C5 = 2.2873 * Cscale "F"
"""
try:
from svg_schematic import (
Schematic, Capacitor, Dot, Ground, Inductor, Label, Resistor, Pin,
Source, Wire
)
from inform import Error, error, os_error
from quantiphy import Quantity
from math import pi
except ImportError:
print(
'Run `pip install --user -r requirements.txt`',
'to install missing packages.'
)
raise SystemExit
Quantity.set_prefs(map_sf=Quantity.map_sf_to_greek, prec=2)
globals().update(
Quantity.extract(__doc__, predefined={'π': pi})
)
try:
with Schematic(filename = 'mfed.svg', line_width=2, background = 'none'):
vin = Source(kind='sine')
Ground(C=vin.n)
rs = Resistor(name='Rs', value=Rref, n=vin.p, xoff=25)
Wire([vin.p, rs.n])
c1 = Capacitor(name='C1', value=C1, p=rs.p, xoff=25)
Ground(C=c1.n)
l2 = Inductor(name='L2', value=L2, n=c1.p, xoff=25)
Wire([rs.p, l2.n])
c3 = Capacitor(name='C3', value=C3, p=l2.p, xoff=25)
Ground(C=c3.n)
l4 = Inductor(name='L4', value=L4, n=c3.p, xoff=25)
Wire([l2.p, l4.n])
c5 = Capacitor(name='C5', value=C5, p=l4.p, xoff=25)
Ground(C=c5.n)
rl = Resistor(name='Rl', value=Rref, p=c5.p, xoff=100, orient='v')
Ground(C=rl.n)
out = Pin(name='out', C=rl.p, xoff=50, w=2)
Wire([l4.p, out.t])
Label(S=c3.N, yoff=-50, name=f'{Fo} LPF', loc='s')
Dot(C=c1.p)
Dot(C=c3.p)
Dot(C=c5.p)
Dot(C=rl.p)
except Error as e:
e.report()
except OSError as e:
error(os_error(e))
Buck Regulator
This example uses a white dot as a pass-under (on the line that runs from ramp generator to the comparator.
#!/usr/bin/env python3
from svg_schematic import (
Schematic, Amp, Box, Capacitor, Converter, Dot, Ground, Inductor, Label, MOS,
Pin, Resistor, Switch, Wire, shift, shift_x, shift_y, with_x, with_y, midpoint
)
from inform import Error, error, os_error
try:
with Schematic(
filename = "buck.svg", line_width=2, background='none'):
pvdd = Pin(kind='in', name='pvdd', w=3)
avdd = Pin(C=pvdd.C, yoff=50, kind='in', name='avdd', w=3)
Wire([avdd.C, shift_x(avdd.C, 50)])
lvl = Pin(C=avdd.C, yoff=90, kind='in', name='lvl', w=3)
reference = Converter(i=lvl.C, xoff=75, name='ref')
lvl2ref = Wire([lvl.C, reference.i])
Label(C=lvl2ref.m, kind='slash', name='6', loc='se')
amp = Amp(pi=reference.o, xoff=50, kind='oa', name='amp')
Wire([reference.o, amp.pi])
C1 = Capacitor(p=amp.C, off=(-12.5, 75), orient='h')
R1 = Resistor(p=C1.p, xoff=12.5, orient='h')
C2 = Capacitor(C=midpoint(R1.C, C1.C), yoff=50, orient='h')
Wire([C1.n, with_y(C1.n, amp.o)], kind='-|')
Wire([R1.n, amp.ni], kind='|-')
Wire([C2.p, R1.n], kind='-|')
Wire([C2.n, C1.n], kind='-|')
cmp = Amp(pi=amp.o, xoff=125, kind='comp', name='cmp')
Wire([amp.o, cmp.pi])
gd = Box(i=cmp.o, xoff=50, name='gate', value='drivers')
Wire([cmp.o, gd.i])
pfet = MOS(g=gd.N, yoff=-50, kind='p', orient='h')
Wire([pfet.g, gd.N])
Wire([pfet.s, pvdd.C])
nfet = MOS(g=gd.o, xoff=25, kind='n', orient='v')
Wire([nfet.g, gd.o])
Wire([nfet.d, pfet.d], kind='|-')
Ground(C=nfet.s)
ind = Inductor(n=with_x(pfet.d, nfet.E), orient='h')
Wire([pfet.d, ind.n])
cap = Capacitor(p=ind.p, orient='v')
Ground(C=cap.n)
out = Pin(C=ind.p, xoff=100, kind='out', name='out', w=3)
out_wire = Wire([ind.p, out.C])
fb = shift_y(R1.n, 100)
Rt = Resistor(n=with_x(fb, out_wire.m), orient='v')
Rb = Resistor(p=with_x(fb, out_wire.m), orient='v')
Wire([Rt.p, with_y(Rt.p, out.C)])
Ground(C=Rb.n)
RG = Box(o=C1.n, yoff=175)
rg2cmp = Wire([RG.o, cmp.ni], kind='-|-')
Dot(C=with_y(rg2cmp.m, fb), color='white')
Wire([shift_x(RG.C, -30), shift(RG.C, -25, 25), shift(RG.C, 25, -25), shift_x(RG.C, 30)])
Label(C=RG.S, loc='s', name='ramp_gen')
Wire([R1.n, fb, Rt.n], kind='|-')
en = Pin(C=lvl.C, yoff=250, kind='in', name='en', w=3)
Wire([en.C, shift_x(en.C, 50)])
avss = Pin(C=en.C, yoff=50, kind='in', name='avss', w=3)
Wire([avss.C, shift_x(avss.C, 50)])
except Error as e:
e.report()
except OSError as e:
error(os_error(e))
Pipelined ADC
This block diagram has a white background and so could route wires under
components rather than wiring to terminals, but it largely does not.
It uses line_width = 2
give the diagram a heavier look.
#!/usr/bin/env python3
from svg_schematic import (
Schematic, Amp, Box, Label, Pin, Source, Wire,
midpoint, shift_x, shift, with_x, with_y,
)
from inform import Error, error, os_error
try:
with Schematic(filename = 'pipeline-adc.svg', line_width=2):
# Stage 1
i = Pin(kind='in', name='in')
s1 = Box(NW=i.t, off=(25,-62.5), w=10.5, h=4.5, background='lightgray')
Label(C=s1.SE, loc='nw', name='Stage 1')
adc = Box(W=i.t, off=(75,100), name='2 bit', value='Flash')
dac = Box(i=adc.o, xoff=50, name='2 bit', value='DAC')
sh = Box(C=with_x(i.t, midpoint(adc.C, dac.C)), name='SAH')
sum = Source(W=with_x(i.t, dac.E), xoff=25, kind='sum', orient='h|')
Label(C=sum.W, loc='nw', name='+')
Label(C=sum.S, loc='se', name='−')
amp = Amp(i=sum.E, xoff=25, kind='se', name='4×')
Wire([i.t, sh.i])
Wire([sh.o, sum.W])
Wire([sum.E, amp.i])
Wire([shift_x(i.t, 50), adc.i], kind='|-')
Wire([adc.o, dac.i])
Wire([dac.o, sum.S], kind='-|')
# Stages 2, 3, 4
s2 = Box(N=dac.S, off=(25,75), name='Stage 2')
s3 = Box(W=s2.E, xoff=50, name='Stage 3')
s4 = Box(W=s3.E, xoff=50, name='4 bit', value='Flash')
Wire([s2.o, s3.i])
Wire([s3.o, s4.i])
Wire([
amp.o,
shift_x(amp.o, 50),
shift(s1.SE, 25,25),
shift(s2.NW, -25, -25),
shift_x(s2.W, -25),
s2.W,
])
# Error correction
ec = Box(NW=s2.SW, off=(-75, 50), name='Digital Error Correction', w=9, h=1)
out = Pin(t=shift_x(ec.o, 50), kind='out', name='out', w=2)
Wire([ec.o, out.t])
Label(C=shift_x(ec.E, 25), kind='slash', loc='s', name='8')
w1 = Wire([midpoint(adc.o, dac.i), with_y(midpoint(adc.o, dac.i), ec.N)])
w2 = Wire([s2.S, with_y(s2.S, ec.N)])
w3 = Wire([s3.S, with_y(s3.S, ec.N)])
w4 = Wire([s4.S, with_y(s4.S, ec.N)])
Label(C=w1.e, yoff=-25, kind='slash', loc='w', name='2', nudge=8)
Label(C=w2.e, yoff=-25, kind='slash', loc='w', name='2', nudge=8)
Label(C=w3.e, yoff=-25, kind='slash', loc='w', name='2', nudge=8)
Label(C=w4.e, yoff=-25, kind='slash', loc='w', name='4', nudge=8)
except Error as e:
e.report()
except OSError as e:
error(os_error(e))
Receiver
This block diagram has a white background and so could route the wires
underneath the components, but does not.
It uses line_width = 2
give the diagram a heavier look.
It looks small because it is quite wide, and it is scaled to fit the page.
#!/usr/bin/env python3
from svg_schematic import (
Schematic, shift_x, shift_y, Amp, Box, Ground, Label, Pin, Source, Wire
)
with Schematic(
filename = 'receiver.svg',
font_size = 12,
font_family = 'sans',
outline = 'none',
pad = 20,
line_width = 2,
) as schematic:
# Input from horn antenna
rf_in = Pin(kind='in', name='L-band Horn', w=3)
Label(C=rf_in.C, yoff=15, loc='w', name='fc=1420MHz', w=3.5, nudge=14)
Label(C=rf_in.C, yoff=30, loc='w', name='BW=15MHz', w=3.5, nudge=14)
# First preamp
rf_preamp1 = Amp(i=rf_in.t, xoff=25, kind='se', name='RF Preamp1')
Label(C=rf_preamp1.S, loc='s', name='A>=26dB')
Wire([rf_in.t, rf_preamp1.i])
# Second preamp
rf_preamp2 = Amp(i=rf_preamp1.o, xoff=25, kind='se', name='RF Preamp2')
Label(C=rf_preamp2.S, loc='s', name='A>=26dB')
Wire([rf_preamp1.o, rf_preamp2.i])
# RF band-pass filter
rf_bpf = Box(i=rf_preamp2.o, xoff=25, name='RF BPF')
l = Label(C=rf_bpf.S, loc='s', name='fc=1380MHz')
Label(C=l.S, name='BW=320MHz')
Wire([rf_preamp2.o, rf_bpf.i])
# First RF amplifier
rf_amp1 = Amp(i=rf_bpf.o, xoff=25, kind='se', name='RF Amp1')
Label(C=rf_amp1.S, loc='s', name='A<=20dB')
Wire([rf_bpf.o, rf_amp1.i])
# Second RF amplifier
rf_amp2 = Amp(i=rf_amp1.o, xoff=25, kind='se', name='RF Amp2')
Label(C=rf_amp2.S, loc='s', name='A<=20dB')
Wire([rf_amp1.o, rf_amp2.i])
# RF mixer
rf_mixer = Source(W=rf_amp2.o, xoff=25, kind='mult')
Label(C=rf_mixer.N, loc='n', name='DSB')
Wire([rf_amp2.o, rf_mixer.W])
# RF local oscillator
rf_lo = Source(
p=rf_mixer.S, yoff=50, kind='sine',
name='fo=1230MHz', value='P=10dBm'
)
Ground(t=rf_lo.n)
Wire([rf_mixer.S, rf_lo.N])
# IF band-pass filter
if_bpf = Box(i=rf_mixer.E, xoff=25, name='IF BPF')
l= Label(C=if_bpf.S, loc='s', name='fc=190MHz')
Label(C=l.S, name='BW=22MHz')
Wire([rf_mixer.E, if_bpf.i])
# IF amplifier
if_amp = Amp(i=if_bpf.o, xoff=25, name='IF Amp')
Label(C=if_amp.S, loc='s', name='A=20dB')
Wire([if_bpf.o, if_amp.i])
# IF mixer
if_mixer = Source(W=if_amp.o, xoff=20, kind='mult')
Label(C=if_mixer.N, loc='n', name='SSB')
Wire([if_amp.o, if_mixer.W])
# IF local oscillator
if_lo = Source(
p=if_mixer.S, yoff=50, kind='sine',
name='fo=190MHz', value='P=10dBm'
)
Ground(t=if_lo.n)
Wire([if_mixer.S, if_lo.p])
# Baseband low-pass filter
bb_lpf = Box(i=if_mixer.E, xoff=25, name='BB LPF')
Label(C=bb_lpf.S, loc='s', name='BW=2MHz (var)')
Wire([if_mixer.E, bb_lpf.i])
# Analog-to-digital converter
adc = Box(i=bb_lpf.o, xoff=25, name='ADC')
Label(C=adc.S, loc='s', name='Fclk=var')
Wire([bb_lpf.o, adc.i])
# Output
bb_out = Pin(t=adc.o, xoff=50, kind='out', name='out', w=1.5)
w = Wire([adc.o, bb_out.t])
Label(C=w.m, kind='slash', loc='s', name='8')
Network Map
This is another block diagram.
from svg_schematic import Schematic, Box, Wire, Label, shift_x, shift_y
with Schematic(filename='network-map.svg', line_width=2):
# work network
work = Box(w=6.5, h=4.5, stroke_dasharray="4 2")
Label(C=work.SW, loc='ne', name='work')
bastion = Box(S=work.S, yoff=-25, w=5.5, h=2, color='lightgray')
Wire([bastion.E, shift_x(bastion.E, 75)])
Label(C=bastion.SW, loc='ne', name='bastion')
www = Box(NE=bastion.N, off=(-12.5, 25), w=2, h=1, color='white', name='www')
mail = Box(NW=bastion.N, off=(12.5, 25), w=2, h=1, color='white', name='mail')
dump = Box(SW=bastion.NW, yoff=-25, w=2.5, h=1, name='dump')
laptop = Box(SE=bastion.NE, yoff=-25, w=2.5, h=1, name='my laptop', stroke_dasharray="2 2")
# home network
home = Box(N=work.S, yoff=50, w=6.5, h=2, stroke_dasharray="4 2")
Label(C=home.SW, loc='ne', name='home')
laptop = Box(SW=home.SW, off=(25, -25), w=2.5, h=1, color='lightgray', name='my laptop', stroke_dasharray="2 2")
media = Box(SE=home.SE, off=(-25, -25), w=2.5, h=1, name='media')
Wire([media.E, shift_x(media.E, 75)])
# internet
internet = Wire([shift_x(work.NE, 50), shift_x(home.SE, 50)], line_width=4)
Label(C=internet.e, loc='s', name='internet')
# external network
github = Box(NW=internet.b, off=(50, 25), w=3, h=1, name='github')
Wire([github.W, shift_x(github.W, -50)])
cloud = Box(N=github.S, yoff=25, w=3, h=1, name='vps')
Wire([cloud.W, shift_x(cloud.W, -50)])
backups = Box(N=cloud.S, yoff=25, w=3, h=1, name='backups')
Wire([backups.W, shift_x(backups.W, -50)])
hotspot = Box(N=backups.S, yoff=25, w=3, h=2, stroke_dasharray="4 2")
Label(C=hotspot.SW, loc='ne', name='a wifi hotspot')
laptop = Box(C=hotspot.C, w=2, h=1, name='my laptop', stroke_dasharray="2 2")