Pyvolt makes circuit specification and simulation easy.
Install pyvolt using pip install -e .
after cloning the repository.
Import pyvolt using import pyvolt as pv
and import pyvolt.components as comp
.
circuit = pv.Circuit()
Create a VoltageSource
, Resistor
, Diode
, Switch
, or Transistor
and add it to the circuit.
Use of Python's walrus (:=
) operator is optional, but enables users to create and add components
in one line.
circuit.add(voltage_source := comp.VoltageSource(name="V", v=5))
circuit.add(resistor := comp.Resistor(name="r1", ohm=150))
circuit.add(diode := comp.Diode(name="LED", v_f=2))
Pyvolt uses the >>
operator to connect components instead of defining nodes explicitly:
voltage_source.vplus >> resistor.n1
resistor.n2 >> diode.anode
diode.cathode >> voltage_source.vminus
The circuit's ground is set by connecting it to any other component terminal. The node connected to the circuit ground is defined as having a voltage of zero.
circuit.gnd >> voltage_source.vminus
circuit.compile()
Here is the output of circuit.compile()
on the circuit defined in this tutorial:
Compiled circuit
----------------
Node 0: v=5.0
V.vplus: i=0.02
r1.n1: i=-0.02
Node 1: v=2.0
LED.anode: i=-0.02
r1.n2: i=0.02
Node 2: v=0.0
V.vminus: i=-0.02
LED.cathode: i=0.02
Ground.gnd: i=0.0
----------------
We interpret this output as follows:
- The node with
V.vplus
andr1.n1
has voltage 5V, with 20 milliamps of current flowing fromV.vplus
intor1.n1
- The node with
LED.anode
andr1.n2
has voltage 2V, with 20 milliamps of current flowing fromr1.n2
toLED.anode
- The node with
V.vminus
,LED.cathode
, andGround.gnd
has voltage 0V, with 20 milliamps of current flowing fromLED.cathode
toV.vminus
Pyvolt's convention is positive currents flowing out of components and negative currents flowing into components.
After a circuit has been compiled, we can use the inspect_voltage
and inspect_current
methods:
print("V before diode:", circuit.inspect_voltage(diode.anode)) # V before diode: 2.0
print("I before resistor:", circuit.inspect_current(resistor.n1)) # I before resistor: -0.02
We can define custom components by calling the new_node_ref(name)
method inside of Component
classes for each connection the component has. We can set the target voltage or current of a node or branch by calling set_voltage
or set_current
on the node reference, respectively.
class Arduino(pv.Component):
def __init__(self, name: str = "", n_pins: int = 5):
super().__init__(name)
self.pin_connections: list[pv.NodeRef] = [self.new_node_ref(f"pin{i}") for i in range(n_pins)]
self.gnd_connection = self.new_node_ref("gnd")
def pin(self, pin):
return self.pin_connections[pin]
@property
def gnd(self):
return self.gnd_connection
def pin_on(self, pin):
self.pin_connections[pin].set_voltage(5)
def pin_off(self, pin):
self.pin_connections[pin].set_voltage(0)
Then, we can use it just like any other component:
circuit = pv.Circuit()
circuit.add(arduino := Arduino(name="arduino", n_pins=2))
circuit.add(r2 := comp.Resistor(name="r2", ohm=300))
arduino.pin(0) >> r2.n1
# ...