Bode plotting a damped LC filter

I want to make a bode plot of this LC filter:

image

plotting something like the right graph:

I know how to connect resistor, inductor and capacitor using ModelingToolkitStandardLibrary.jl , and how to plot bode plots using ControlSystems.jl, but I have no idea on how to combine those two.

There’s this: Linear Analysis · ModelingToolkitStandardLibrary.jl where I can somehow get the state space model of the circuit, but I’m not sure where to connect the analysis points

What have you tried so far? If you post your code, I can help you get the Bode plot.

See also these two references

1 Like

I tried this on a simpler RC filter circuit:

using ModelingToolkitStandardLibrary.Electrical
using ModelingToolkit, Plots
using ControlSystems
using ModelingToolkit: t_nounits as t

R = 1.0
C = 1.0
V = 1.0
@named resistor = Resistor(R = R)
@named capacitor = Capacitor(C = C, v = 0.0)
@named ground = Ground()
@named filter_input = Voltage()
@named filter_output = Voltage()

#= input ---- [resistor] -----|---------- output
                            _________
                            capacitor
                            ---------
                              |
                            ground

=#


filt_ckt = [connect(filter_input.p,  resistor.p)
            connect(resistor.n, capacitor.p)
            connect(capacitor.n, ground.g)
            connect(capacitor.p,  filter_output.p)
]

@named filt_ckt = ODESystem(filt_ckt, t,
    systems = [resistor, capacitor, filter_input, filter_output, ground])


linearize(filt_ckt, [filter_input.v],[filter_output.v])

linearize errored out:

julia> linearize(filt_ckt, [filter_input.v],[filter_output.v])
ERROR: Some parameters are missing from the variable map.
Please provide a value or default for the following variables:

Any[filter_input₊v(t)]

Stacktrace:
 [1] ModelingToolkit.MTKParameters(sys::ODESystem, p::Dict{…}, u0::Dict{…}; tofloat::Bool, use_union::Bool, eval_expression::Bool, eval_module::Module)
   @ ModelingToolkit ~/.julia/packages/ModelingToolkit/7em8Z/src/systems/parameter_buffer.jl:91
 [2] linearization_function(sys::ODESystem, inputs::Vector{…}, outputs::Vector{…}; simplify::Bool, initialize::Bool, op::Dict{…}, p::SciMLBase.NullParameters, zero_dummy_der::Bool, initialization_solver_alg::NonlinearSolve.GeneralizedFirstOrderAlgorithm{…}, eval_expression::Bool, eval_module::Module, warn_initialize_determined::Bool, kwargs::@Kwargs{})
   @ ModelingToolkit ~/.julia/packages/ModelingToolkit/7em8Z/src/systems/abstractsystem.jl:2027
 [3] linearization_function
   @ ~/.julia/packages/ModelingToolkit/7em8Z/src/systems/abstractsystem.jl:1978 [inlined]
 [4] linearize(sys::ODESystem, inputs::Vector{…}, outputs::Vector{…}; op::Dict{…}, t::Float64, allow_input_derivatives::Bool, zero_dummy_der::Bool, kwargs::@Kwargs{})
   @ ModelingToolkit ~/.julia/packages/ModelingToolkit/7em8Z/src/systems/abstractsystem.jl:2429
 [5] linearize(sys::ODESystem, inputs::Vector{Num}, outputs::Vector{Num})
   @ ModelingToolkit ~/.julia/packages/ModelingToolkit/7em8Z/src/systems/abstractsystem.jl:2425
 [6] top-level scope
   @ ~/pcb123/new_receiver/Notebooks/power_emi_filter.jl:35
Some type information was truncated. Use `show(err)` to see complete types.

You have forgotten to connect several components to ground. Here’s an example that works

using ModelingToolkitStandardLibrary.Electrical
using ModelingToolkitStandardLibrary.Blocks
using ModelingToolkit, Plots
using ControlSystemsBase
using ModelingToolkit: t_nounits as t

R = 1.0
C = 1.0
V = 1.0
@named resistor = Resistor(R = R)
@named capacitor = Capacitor(C = C, v = 0.0)
@named ground = Ground()
@named filter_input = Voltage()
@named filter_output = VoltageSensor()

#= input ---- [resistor] -----|---------- output
                            _________
                            capacitor
                            ---------
                              |
                            ground

=#


filt_ckt = [connect(filter_input.p,  resistor.p)
            connect(resistor.n, capacitor.p, filter_output.p)
            connect(filter_input.n, capacitor.n, ground.g, filter_output.n)
]

@named filt_ckt = ODESystem(filt_ckt, t,
    systems = [resistor, capacitor, filter_input, filter_output, ground])



op = Dict(
    filter_input.V.u => 0,
)
matrices, simplified_sys = linearize(filt_ckt, [filter_input.V.u],[filter_output.v]; op)

using ControlSystemsMTK

lsys = named_ss(filt_ckt, [filter_input.V.u],[filter_output.v]; op)
bodeplot(lsys)

image

I load ControlSystemsMTK here to make interfacing CS and MTK smoother.

1 Like

Now I want to send a square wave to the filter input, so I added discrete event from Event Handling and Callback Functions · ModelingToolkit.jl

filt_ckt4 = [connect(filter_input.p,  resistor.p)
    connect(resistor.n, capacitor.p, filter_output.p)
    connect(filter_input.n, capacitor.n, ground.g, filter_output.n)
]


@named filt_ckt = ODESystem(filt_ckt4, t, 
    systems = [resistor, capacitor, filter_input, filter_output, ground], discrete_events=[[1.0] => [filter_input.V.u ~ 1]])

(for now I want to make a single step)

I feed it to structural_simplify so it doesn’t complain, and make a ODEProblem

simplified_eqn,b = structural_simplify(filt_ckt, (filter_input.V.u, filter_output.v); )
oprob = ODEProblem(simplified_eqn, [filter_input.V.u => 0], (0,2); fully_determined = true)

It then complains:

julia> oprob = ODEProblem(simplified_eqn, [filter_input.V.u => 0], (0,2); fully_determined = true)
ERROR: KeyError: key filter_input₊V₊u(t) not found
Stacktrace:

But I already put filter_input.V.u in the initial condition dictionary

julia> filter_input.V.u
filter_input₊V₊u(t)


julia> [filter_input.V.u => 0]
1-element Vector{Pair{Num, Int64}}:
 filter_input₊V₊u(t) => 0

See ModelingToolkitStandardLibrary.Blocks.Step.

Events in MTK have a list of known issues, try to use the step block instead, and for a square wave, try Blocks.Sine followed by Blocks.Sign

1 Like