AmplifierWithOpAmpDetailed
Inverting operational amplifier circuit built using a detailed op-amp model.
This circuit implements an inverting amplifier configuration utilizing an OpAmpDetailed
component. An input signal, generated by input_signal1
(a sine wave with 12V amplitude, 1kHz frequency) and conditioned by voltage_source_1
, is applied to the inverting input terminal of the operational amplifier via the input resistor
(R_in = 10kΩ). The non-inverting input of the op-amp is connected to the circuit ground. The operational amplifier is powered by voltage_source_2
(+15V) andvoltage_source_3
(-15V), which are driven byinput_signal2
andinput_signal3
respectively. The output of the amplifier is connected to a loadresistor2
(10kΩ). The voltage gain of this inverting amplifier is primarily determined by the ratio of the feedback resistorresistor1
(R_f = 20kΩ) to the input resistor
. Given the component values R
of resistor
) and R
of resistor1
), the ideal gain is -2. The behavior of OpAmpDetailed
will introduce non-ideal characteristics.
Usage
AmplifierWithOpAmpDetailed()
Behavior
Source
# Inverting operational amplifier circuit built using a detailed op-amp model.
#
# This circuit implements an inverting amplifier configuration utilizing an `OpAmpDetailed` component.
# An input signal, generated by `input_signal1` (a sine wave with 12V amplitude, 1kHz frequency)
# and conditioned by `voltage_source_1`, is applied to the inverting input terminal of the operational
# amplifier via the input `resistor` (R_in = 10kΩ). The non-inverting input of the op-amp is
# connected to the circuit ground. The operational amplifier is powered by `voltage_source_2` (+15V)
# and `voltage_source_3` (-15V), which are driven by `input_signal2` and `input_signal3` respectively.
# The output of the amplifier is connected to a load `resistor2` (10kΩ).
# The voltage gain of this inverting amplifier is primarily determined by the ratio of the feedback
# resistor `resistor1` (R_f = 20kΩ) to the input `resistor`.
# Given the component values $R_{in} = 10k\Omega$ (parameter `R` of `resistor`) and
# $R_f = 20k\Omega$ (parameter `R` of `resistor1`), the ideal gain is -2.
# The behavior of `OpAmpDetailed` will introduce non-ideal characteristics.
test component AmplifierWithOpAmpDetailed
# Detailed operational amplifier model instance, forming the core of the amplifier.
op_amp = OpAmpDetailed() [{
"Dyad": {"placement": {"icon": {"x1": 400, "y1": 550, "x2": 600, "y2": 750, "rot": 0}}}
}]
# Input resistor (R_in), value 10kOhm, connecting the input signal to the op-amp's inverting input.
resistor = Resistor(R=10000) [{
"Dyad": {"placement": {"icon": {"x1": 100, "y1": 510, "x2": 300, "y2": 710, "rot": 0}}}
}]
# Feedback resistor (R_f), value 20kOhm, from op-amp output to inverting input, sets gain.
resistor1 = Resistor(R=20000) [{
"Dyad": {"placement": {"icon": {"x1": 550, "y1": 0, "x2": 750, "y2": 200, "rot": 0}}}
}]
# Load resistor, value 10kOhm, connected from the op-amp output to ground.
resistor2 = Resistor(R=10000) [{
"Dyad": {
"placement": {"icon": {"x1": 800, "y1": 700, "x2": 1000, "y2": 900, "rot": 90}}
}
}]
# Ideal voltage source component for applying the input AC signal.
voltage_source_1 = VoltageSource() [{
"Dyad": {"placement": {"icon": {"x1": 100, "y1": 850, "x2": 300, "y2": 1050, "rot": 0}}}
}]
# Ideal voltage source component for the positive power supply (+15V).
voltage_source_2 = VoltageSource() [{
"Dyad": {"placement": {"icon": {"x1": 550, "y1": 300, "x2": 750, "y2": 500, "rot": 0}}}
}]
# Ideal voltage source component for the negative power supply (-15V).
voltage_source_3 = VoltageSource() [{
"Dyad": {
"placement": {"icon": {"x1": 550, "y1": 850, "x2": 750, "y2": 1050, "rot": 90}}
}
}]
# Sine wave signal generator (12V amplitude, 1kHz) for the amplifier's input.
input_signal1 = BlockComponents.Sine(amplitude=12, frequency=1000, offset=0) [{
"Dyad": {
"placement": {"icon": {"x1": 100, "y1": 1200, "x2": 300, "y2": 1400, "rot": 270}}
}
}]
# Constant signal generator providing +15V for the positive op-amp supply.
input_signal2 = BlockComponents.Constant(k=15) [{
"Dyad": {"placement": {"icon": {"x1": 950, "y1": 150, "x2": 1150, "y2": 350, "rot": 0}}}
}]
# Constant signal generator providing -15V for the negative op-amp supply.
input_signal3 = BlockComponents.Constant(k=-15) [{
"Dyad": {
"placement": {"icon": {"x1": 400, "y1": 1200, "x2": 600, "y2": 1400, "rot": 0}}
}
}]
# Electrical ground reference component for the circuit.
ground = Ground() [{
"Dyad": {
"placement": {"icon": {"x1": 800, "y1": 1200, "x2": 1000, "y2": 1400, "rot": 0}}
}
}]
relations
connect(input_signal1.y, voltage_source_1.V) [{"Dyad": {"edges": [{"S": 1, "E": 2}]}}]
connect(input_signal2.y, voltage_source_2.V) [{
"Dyad": {
"edges": [
{
"S": 1,
"M": [{"x": 1200, "y": 250}, {"x": 1200, "y": 550}, {"x": 650, "y": 550}],
"E": 2
}
]
}
}]
connect(input_signal3.y, voltage_source_3.V) [{
"Dyad": {
"edges": [
{
"S": 1,
"M": [
{"x": 650, "y": 1300},
{"x": 650, "y": 1150},
{"x": 500, "y": 1150},
{"x": 500, "y": 950}
],
"E": 2
}
]
}
}]
initial resistor2.i = 0
initial op_amp.q_fp1 = 0
initial op_amp.q_fr1 = 0
initial op_amp.q_fr2 = 0
initial op_amp.q_fr3 = 0
connect(ground.g, voltage_source_1.n, op_amp.p, resistor2.n, voltage_source_3.n, voltage_source_2.n) [{
"Dyad": {
"edges": [
{"S": 1, "E": -2},
{"S": -3, "E": 2},
{"S": -3, "M": [{"x": 350, "y": 690}], "E": 3},
{"S": -2, "E": 4},
{"S": -1, "E": 5},
{"S": -2, "M": [{"x": 1050, "y": 1100}, {"x": 1050, "y": 400}], "E": 6},
{"S": -1, "E": -2},
{"S": -1, "M": [{"x": 350, "y": 1100}], "E": -3}
],
"junctions": [{"x": 650, "y": 1100}, {"x": 900, "y": 1100}, {"x": 350, "y": 950}]
}
}]
connect(resistor.n, op_amp.n, resistor1.p) [{
"Dyad": {
"edges": [
{"S": 1, "E": -1},
{"S": -1, "E": 2},
{"S": -1, "M": [{"x": 350, "y": 100}], "E": 3}
],
"junctions": [{"x": 350, "y": 610}]
}
}]
connect(resistor1.n, op_amp.outp, resistor2.p) [{
"Dyad": {
"edges": [
{"S": 1, "M": [{"x": 900, "y": 100}], "E": -1},
{"S": 2, "E": -1},
{"S": 3, "E": -1}
],
"junctions": [{"x": 900, "y": 650}]
}
}]
connect(resistor.p, voltage_source_1.p) [{
"Dyad": {"edges": [{"S": 1, "M": [{"x": 50, "y": 610}, {"x": 50, "y": 950}], "E": 2}]}
}]
connect(op_amp.p_supply, voltage_source_2.p) [{"Dyad": {"edges": [{"S": 1, "M": [{"x": 500, "y": 400}], "E": 2}]}}]
connect(op_amp.n_supply, voltage_source_3.p) [{
"Dyad": {"edges": [{"S": 2, "M": [{"x": 650, "y": 800}, {"x": 500, "y": 800}], "E": 1}]}
}]
metadata {
"Dyad": {
"tests": {
"case1": {
"stop": 0.1,
"atol": {"op_amp.outp.v": 0.4},
"expect": {"signals": ["op_amp.outp.v", "voltage_source_1.p.v"]}
}
}
}
}
end
Flattened Source
# Inverting operational amplifier circuit built using a detailed op-amp model.
#
# This circuit implements an inverting amplifier configuration utilizing an `OpAmpDetailed` component.
# An input signal, generated by `input_signal1` (a sine wave with 12V amplitude, 1kHz frequency)
# and conditioned by `voltage_source_1`, is applied to the inverting input terminal of the operational
# amplifier via the input `resistor` (R_in = 10kΩ). The non-inverting input of the op-amp is
# connected to the circuit ground. The operational amplifier is powered by `voltage_source_2` (+15V)
# and `voltage_source_3` (-15V), which are driven by `input_signal2` and `input_signal3` respectively.
# The output of the amplifier is connected to a load `resistor2` (10kΩ).
# The voltage gain of this inverting amplifier is primarily determined by the ratio of the feedback
# resistor `resistor1` (R_f = 20kΩ) to the input `resistor`.
# Given the component values $R_{in} = 10k\Omega$ (parameter `R` of `resistor`) and
# $R_f = 20k\Omega$ (parameter `R` of `resistor1`), the ideal gain is -2.
# The behavior of `OpAmpDetailed` will introduce non-ideal characteristics.
test component AmplifierWithOpAmpDetailed
# Detailed operational amplifier model instance, forming the core of the amplifier.
op_amp = OpAmpDetailed() [{
"Dyad": {"placement": {"icon": {"x1": 400, "y1": 550, "x2": 600, "y2": 750, "rot": 0}}}
}]
# Input resistor (R_in), value 10kOhm, connecting the input signal to the op-amp's inverting input.
resistor = Resistor(R=10000) [{
"Dyad": {"placement": {"icon": {"x1": 100, "y1": 510, "x2": 300, "y2": 710, "rot": 0}}}
}]
# Feedback resistor (R_f), value 20kOhm, from op-amp output to inverting input, sets gain.
resistor1 = Resistor(R=20000) [{
"Dyad": {"placement": {"icon": {"x1": 550, "y1": 0, "x2": 750, "y2": 200, "rot": 0}}}
}]
# Load resistor, value 10kOhm, connected from the op-amp output to ground.
resistor2 = Resistor(R=10000) [{
"Dyad": {
"placement": {"icon": {"x1": 800, "y1": 700, "x2": 1000, "y2": 900, "rot": 90}}
}
}]
# Ideal voltage source component for applying the input AC signal.
voltage_source_1 = VoltageSource() [{
"Dyad": {"placement": {"icon": {"x1": 100, "y1": 850, "x2": 300, "y2": 1050, "rot": 0}}}
}]
# Ideal voltage source component for the positive power supply (+15V).
voltage_source_2 = VoltageSource() [{
"Dyad": {"placement": {"icon": {"x1": 550, "y1": 300, "x2": 750, "y2": 500, "rot": 0}}}
}]
# Ideal voltage source component for the negative power supply (-15V).
voltage_source_3 = VoltageSource() [{
"Dyad": {
"placement": {"icon": {"x1": 550, "y1": 850, "x2": 750, "y2": 1050, "rot": 90}}
}
}]
# Sine wave signal generator (12V amplitude, 1kHz) for the amplifier's input.
input_signal1 = BlockComponents.Sine(amplitude=12, frequency=1000, offset=0) [{
"Dyad": {
"placement": {"icon": {"x1": 100, "y1": 1200, "x2": 300, "y2": 1400, "rot": 270}}
}
}]
# Constant signal generator providing +15V for the positive op-amp supply.
input_signal2 = BlockComponents.Constant(k=15) [{
"Dyad": {"placement": {"icon": {"x1": 950, "y1": 150, "x2": 1150, "y2": 350, "rot": 0}}}
}]
# Constant signal generator providing -15V for the negative op-amp supply.
input_signal3 = BlockComponents.Constant(k=-15) [{
"Dyad": {
"placement": {"icon": {"x1": 400, "y1": 1200, "x2": 600, "y2": 1400, "rot": 0}}
}
}]
# Electrical ground reference component for the circuit.
ground = Ground() [{
"Dyad": {
"placement": {"icon": {"x1": 800, "y1": 1200, "x2": 1000, "y2": 1400, "rot": 0}}
}
}]
relations
connect(input_signal1.y, voltage_source_1.V) [{"Dyad": {"edges": [{"S": 1, "E": 2}]}}]
connect(input_signal2.y, voltage_source_2.V) [{
"Dyad": {
"edges": [
{
"S": 1,
"M": [{"x": 1200, "y": 250}, {"x": 1200, "y": 550}, {"x": 650, "y": 550}],
"E": 2
}
]
}
}]
connect(input_signal3.y, voltage_source_3.V) [{
"Dyad": {
"edges": [
{
"S": 1,
"M": [
{"x": 650, "y": 1300},
{"x": 650, "y": 1150},
{"x": 500, "y": 1150},
{"x": 500, "y": 950}
],
"E": 2
}
]
}
}]
initial resistor2.i = 0
initial op_amp.q_fp1 = 0
initial op_amp.q_fr1 = 0
initial op_amp.q_fr2 = 0
initial op_amp.q_fr3 = 0
connect(ground.g, voltage_source_1.n, op_amp.p, resistor2.n, voltage_source_3.n, voltage_source_2.n) [{
"Dyad": {
"edges": [
{"S": 1, "E": -2},
{"S": -3, "E": 2},
{"S": -3, "M": [{"x": 350, "y": 690}], "E": 3},
{"S": -2, "E": 4},
{"S": -1, "E": 5},
{"S": -2, "M": [{"x": 1050, "y": 1100}, {"x": 1050, "y": 400}], "E": 6},
{"S": -1, "E": -2},
{"S": -1, "M": [{"x": 350, "y": 1100}], "E": -3}
],
"junctions": [{"x": 650, "y": 1100}, {"x": 900, "y": 1100}, {"x": 350, "y": 950}]
}
}]
connect(resistor.n, op_amp.n, resistor1.p) [{
"Dyad": {
"edges": [
{"S": 1, "E": -1},
{"S": -1, "E": 2},
{"S": -1, "M": [{"x": 350, "y": 100}], "E": 3}
],
"junctions": [{"x": 350, "y": 610}]
}
}]
connect(resistor1.n, op_amp.outp, resistor2.p) [{
"Dyad": {
"edges": [
{"S": 1, "M": [{"x": 900, "y": 100}], "E": -1},
{"S": 2, "E": -1},
{"S": 3, "E": -1}
],
"junctions": [{"x": 900, "y": 650}]
}
}]
connect(resistor.p, voltage_source_1.p) [{
"Dyad": {"edges": [{"S": 1, "M": [{"x": 50, "y": 610}, {"x": 50, "y": 950}], "E": 2}]}
}]
connect(op_amp.p_supply, voltage_source_2.p) [{"Dyad": {"edges": [{"S": 1, "M": [{"x": 500, "y": 400}], "E": 2}]}}]
connect(op_amp.n_supply, voltage_source_3.p) [{
"Dyad": {"edges": [{"S": 2, "M": [{"x": 650, "y": 800}, {"x": 500, "y": 800}], "E": 1}]}
}]
metadata {
"Dyad": {
"tests": {
"case1": {
"stop": 0.1,
"atol": {"op_amp.outp.v": 0.4},
"expect": {"signals": ["op_amp.outp.v", "voltage_source_1.p.v"]}
}
}
}
}
end
Test Cases
This is setup code, that must be run before each test case.
using ElectricalComponents
using ModelingToolkit, OrdinaryDiffEqDefault
using Plots
using CSV, DataFrames
snapshotsdir = joinpath(dirname(dirname(pathof(ElectricalComponents))), "test", "snapshots")
"/home/actions-runner-10/.julia/packages/ElectricalComponents/bmmPM/test/snapshots"
Test Case case1
@mtkbuild model_case1 = AmplifierWithOpAmpDetailed()
u0_case1 = []
prob_case1 = ODEProblem(model_case1, u0_case1, (0, 0.1))
sol_case1 = solve(prob_case1)
retcode: Success
Interpolation: 3rd order Hermite
t: 4954865-element Vector{Float64}:
0.0
8.134315885636067e-9
1.1736722048261559e-8
2.1604151127447103e-8
2.985035140374734e-8
4.3099175169262416e-8
5.998037956087132e-8
8.353753610510942e-8
1.1619953473017416e-7
1.664330489853791e-7
⋮
0.09993089586889937
0.09993695365715871
0.0999440606438676
0.0999519083964991
0.09996055108437175
0.09997026807238182
0.09998145975114792
0.09999465730445987
0.1
u: 4954865-element Vector{Vector{Float64}}:
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.001, 0.0]
[-5.210849273074702e-6, -8.658323876536206e-5, -0.0002459179830513934, -0.00021051672329396278, -1.0972194178214729e-8, -1.0972194178200028e-8, -0.0008627262388338218, -5.198999244018477e-11]
[-1.0789689397887153e-5, -0.00012199001939547564, -0.00030882756316310265, -0.00028081107631802656, -3.4529497101619986e-8, -3.4529497101589744e-8, -0.000918034564413413, -3.3809629720770434e-11]
[-3.3342327225301665e-5, -0.0002322051073678206, -0.0004804399386551722, -0.0004507533485464858, -2.079754571502547e-7, -2.079754571502244e-7, -0.0012394862858072717, 6.824208797300813e-11]
[-6.092424829212858e-5, -0.00034897145334343934, -0.0006591582641585801, -0.0006225084334287382, -5.243750765648772e-7, -5.243750765648113e-7, -0.00159899159230758, 1.702688152868839e-10]
[-0.00012645376202336656, -0.0005902699574421954, -0.0010142225860002986, -0.0009683707939449243, -1.5216616470021731e-6, -1.5216616470021103e-6, -0.0022345311779579436, 3.0732561387789157e-10]
[-0.0002562370698964521, -0.0009873303626110298, -0.0015514516335103775, -0.001497997758593859, -4.11015682378042e-6, -4.1101568237803696e-6, -0.0030730377936935365, 3.622976417869361e-10]
[-0.0005386438813026333, -0.0016801327531891705, -0.002404593647798685, -0.002344170425799753, -1.1562719308338706e-5, -1.1562719308338559e-5, -0.004251428301479844, 6.23126647427301e-11]
[-0.001150502602062841, -0.002839370687562592, -0.003721707165986267, -0.0036548688297853953, -3.3366455698623644e-5, -3.3366455698623454e-5, -0.005883798098863065, -1.4884759285920349e-9]
[-0.0026444807629242583, -0.0049109774042519995, -0.005936519966401101, -0.005864035273937961, -0.00010762519495925536, -0.00010762519495925535, -0.008382413277595719, -7.905181228012005e-9]
⋮
[10.109598148400693, -0.022065736840157366, -0.0220672858137154, -0.022067182897642198, 10.275374407862877, 10.27537440786295, -0.022070895457509294, 0.0010161140592060242]
[9.262658562775016, -0.022440023446794657, -0.022441428735953832, -0.022441335363432457, 9.431265623020318, 9.431265623020392, -0.022444703595511338, 0.0009326423773210259]
[8.252013845214655, -0.022837281648475885, -0.02283851904801424, -0.022838436811645657, 8.423629812741602, 8.423629812741678, -0.022841402916375823, 0.0008329999226702222]
[7.116995430222789, -0.02322274417869141, -0.023223807405973428, -0.023223736722571206, 7.29153412891425, 7.291534128914335, -0.023226285646458827, 0.0007210499359689024]
[5.847093899306771, -0.023581984651843472, -0.023582861990576926, -0.023582803656507934, 6.024359025394633, 6.0243590253947294, -0.02358490706296623, 0.0005957422713271908]
[4.398938286546985, -0.02390300882482765, -0.02390367475199001, -0.023903630482344066, 4.578644361978922, 4.578644361979022, -0.0239052269240211, 0.0004527792589943118]
[2.7110258338962243, -0.024162427610391134, -0.02416284446900292, -0.024162816778380634, 2.8927135070312904, 2.8927135070313996, -0.02416381581971475, 0.00028606184141811953]
[0.7040071419995184, -0.024314858584993715, -0.02431497818935214, -0.024314970291146484, 0.8868774062439877, 0.8868774062441203, -0.0243152562715796, 8.770974916738043e-5]
[-0.11064235115904038, -0.02432914939393276, -0.02432915076168407, -0.024329150738787074, 0.07234934624408097, 0.07234934624420906, -0.024329153050869693, 7.16309820204201e-6]
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.op_amp.outp.v])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "AmplifierWithOpAmpDetailed_case1_sig0.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.op_amp.outp.v], width=2, label="Actual value of op_amp.outp.v")
if !isnothing(dfr_case1)
scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of op_amp.outp.v")
end
plt
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.voltage_source_1.p.v])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "AmplifierWithOpAmpDetailed_case1_sig1.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.voltage_source_1.p.v], width=2, label="Actual value of voltage_source_1.p.v")
if !isnothing(dfr_case1)
scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of voltage_source_1.p.v")
end
plt
Related
Examples
Experiments
Analyses
Tests