Hi All, I am trying to model a converter using ModellingToolkit whose control lies in a c file. The control is being called at a regular interval using ccall and periodic callback. It seems impossible to integrate the variable updated from c file into the model as it is not reflecting as an unknown.
In the code the function InvVoltage uses Vinv to get a control output from C code. During the calculations it takes the initial value of Vinv and does not update with the time.
Does anyone have an idea how to resolve this.
Below is the code for reference.
using ModelingToolkit, Plots, OrdinaryDiffEq, Setfield
using ModelingToolkit: t_nounits as t, D_nounits as D
using Plots
using DiffEqCallbacks
using DifferentialEquations
# External C function
const libsource = "/mnt/c/Users/ASoni/Documents/JuliaProgramms/libsource1.so"
Vinv = Ref(0.0)
function get_amplitude!(integrator)
x = integrator.u[1]
Vinv[] = ccall((:get_volt, libsource),Cfloat,(Cfloat,),Float32(t))
end
# Define the Pin connector
function Pin(; name)
@variables v(t) i(t) [connect = Flow]
sys = System(Equation[], t, [v, i], []; name)
sys = @set sys.connector_type = ModelingToolkit.connector_type(sys)
return sys
end
# Define Ground component
function Ground(; name)
@named g = Pin()
eqs = [g.v ~ 0]
System(eqs, t, [], []; systems = [g], name)
end
# Define OnePort base component
function OnePort(; name)
@named p = Pin()
@named n = Pin()
@variables v(t) i(t)
eqs = [
v ~ p.v - n.v
0 ~ p.i + n.i
i ~ p.i
]
System(eqs, t, [v, i], []; systems = [p, n], name)
end
# Define Resistor component
function Resistor(; name, R = 1.0)
@named oneport = OnePort()
@unpack v, i = oneport
@parameters R = R # Sets the default resistance
eqs = [v ~ i * R]
extend(System(eqs, t, [], [R]; name), oneport)
end
# Define Capacitor component
function Capacitor(; name, C = 1.0)
@named oneport = OnePort()
@unpack v, i = oneport
@parameters C = C
eqs = [D(v) ~ i / C]
extend(System(eqs, t, [], [C]; name), oneport)
end
# Define Inductor component
function Inductor(; name, L = 0.01)
@named oneport = OnePort()
@unpack v, i = oneport
@parameters L = L
eqs = [D(i) ~ v / L]
extend(System(eqs, t, [], [L]; name), oneport)
end
# Define ConstantVoltage source
function ConstantVoltage(; name, V = 1.0*sin(2*pi*t*50))
@named oneport = OnePort()
@unpack v = oneport
@parameters V = V
eqs = [V ~ v]
extend(System(eqs, t, [], [V]; name), oneport)
end
# Define ConstantVoltage source
function InvVoltage(; name)
@named oneport = OnePort()
@unpack v = oneport
@parameters A = 1.0
eqs = [v ~ A*Vinv[]]
extend(System(eqs, t, [], [A]; name), oneport)
end
# Build the RL circuit
@named resistor = Resistor(R = 0.001)
@named capacitor = Capacitor(C = 1.0)
@named inductor = Inductor(L = 0.0005)
@named source1 = ConstantVoltage(V = 1.0*sin(2*pi*t*50))
#@named source2 = ConstantVoltage(V = 1.0*sin(2*pi*t*50 - 0.1))
@named source2 = InvVoltage(A = 1.0)
@named ground = Ground()
rl_eqs = [
connect(source1.p, resistor.p)
connect(resistor.n, inductor.p)
connect(inductor.n, source2.p)
connect(source2.n, source1.n)
connect(source1.n, ground.g)
]
@named rl_model = System(rl_eqs, t; systems = [resistor, inductor, source1, source2, ground])
rl_model = mtkcompile(rl_model)
u0 = [
rl_model.inductor.i => 0.0
]
u1 = [
rl_model.source2.v => 0.0
]
############################################################
# 20-kHz controller
############################################################
cb = PeriodicCallback(get_amplitude!,50e-6)
prob = ODEProblem(rl_model, u1, (0, 0.1))
sol = solve(prob, callback = cb)
#p = plot!(sol)
p = plot(sol, idxs = [rl_model.inductor.i, rl_model.source1.v],
title = "RL Circuit Demonstration",
labels = ["Inductor Current" "Source Voltage"])
display(p)
gui()
readline()