RotationalEMFTest
A test circuit for a rotational electromechanical transducer (RotationalEMF) driven by a sinusoidal voltage and connected to an inertial load.
This model simulates a rotational electromechanical device (RotationalEMF
) whose electrical terminals are excited by a sinusoidal voltage. The housing of the RotationalEMF
is mechanically fixed, while its rotor is connected to a rotational Inertia
. A Sine
signal generator provides the input for a VoltageSource
, which in turn applies voltage to the RotationalEMF
. This setup allows for testing the dynamic response of the RotationalEMF
and the connected inertia to electrical stimulation. The primary behavior demonstrated is the conversion of electrical energy (sinusoidal voltage) into mechanical motion (rotation of the inertia) and the generation of torque.
Usage
RotationalEMFTest()
Behavior
Source
# A test circuit for a rotational electromechanical transducer (RotationalEMF) driven by a sinusoidal voltage and connected to an inertial load.
#
# This model simulates a rotational electromechanical device (`RotationalEMF`) whose electrical terminals are excited by a sinusoidal voltage. The housing of the `RotationalEMF` is mechanically fixed, while its rotor is connected to a rotational `Inertia`. A `Sine` signal generator provides the input for a `VoltageSource`, which in turn applies voltage to the `RotationalEMF`. This setup allows for testing the dynamic response of the `RotationalEMF` and the connected inertia to electrical stimulation. The primary behavior demonstrated is the conversion of electrical energy (sinusoidal voltage) into mechanical motion (rotation of the inertia) and the generation of torque.
test component RotationalEMFTest
# Electromechanical transducer converting electrical to rotational energy and vice-versa, with coupling constant k=1.
rot_emf = RotationalEMF(k=1) [{
"Dyad": {"placement": {"icon": {"x1": 300, "y1": 700, "x2": 500, "y2": 900, "rot": 0}}}
}]
# Represents a mechanically fixed point, providing a stationary reference for the EMF housing.
fixed = RotationalComponents.Fixed() [{
"Dyad": {"placement": {"icon": {"x1": 0, "y1": 700, "x2": 200, "y2": 900, "rot": 180}}}
}]
# Generates a sinusoidal signal (amplitude=1, frequency=1 rad/s, offset=0, start_time=0) to define the voltage source's behavior.
input_signal = BlockComponents.Sine(amplitude=1, frequency=1, offset=0, start_time=0) [{
"Dyad": {"placement": {"icon": {"x1": 300, "y1": 100, "x2": 500, "y2": 300, "rot": 0}}}
}]
# Ideal voltage source whose output voltage is driven by the input_signal.
sine_voltage = VoltageSource() [{
"Dyad": {"placement": {"icon": {"x1": 500, "y1": 400, "x2": 700, "y2": 600, "rot": 0}}}
}]
# Rotational inertia with moment of inertia J=100 kg.m^2, representing the mechanical load.
inertia = RotationalComponents.Inertia(J=100) [{
"Dyad": {"placement": {"icon": {"x1": 600, "y1": 700, "x2": 800, "y2": 900, "rot": 0}}}
}]
relations
connect(input_signal.y, sine_voltage.V) [{"Dyad": {"edges": [{"S": 1, "M": [{"x": 600, "y": 200}], "E": 2}]}}]
connect(fixed.spline, rot_emf.housing) [{"Dyad": {"edges": [{"S": 1, "E": 2}]}}]
connect(rot_emf.p, sine_voltage.p) [{"Dyad": {"edges": [{"S": 1, "M": [{"x": 400, "y": 500}], "E": 2}]}}]
connect(sine_voltage.n, rot_emf.n) [{
"Dyad": {
"edges": [
{
"S": 1,
"M": [
{"x": 750, "y": 500},
{"x": 750, "y": 650},
{"x": 550, "y": 650},
{"x": 550, "y": 950},
{"x": 400, "y": 950}
],
"E": 2
}
]
}
}]
connect(rot_emf.rotor, inertia.spline_a) [{"Dyad": {"edges": [{"S": 1, "E": 2}]}}]
metadata {
"Dyad": {
"tests": {"case1": {"stop": 10, "expect": {"signals": ["rot_emf.tau", "rot_emf.phi"]}}}
}
}
end
Flattened Source
# A test circuit for a rotational electromechanical transducer (RotationalEMF) driven by a sinusoidal voltage and connected to an inertial load.
#
# This model simulates a rotational electromechanical device (`RotationalEMF`) whose electrical terminals are excited by a sinusoidal voltage. The housing of the `RotationalEMF` is mechanically fixed, while its rotor is connected to a rotational `Inertia`. A `Sine` signal generator provides the input for a `VoltageSource`, which in turn applies voltage to the `RotationalEMF`. This setup allows for testing the dynamic response of the `RotationalEMF` and the connected inertia to electrical stimulation. The primary behavior demonstrated is the conversion of electrical energy (sinusoidal voltage) into mechanical motion (rotation of the inertia) and the generation of torque.
test component RotationalEMFTest
# Electromechanical transducer converting electrical to rotational energy and vice-versa, with coupling constant k=1.
rot_emf = RotationalEMF(k=1) [{
"Dyad": {"placement": {"icon": {"x1": 300, "y1": 700, "x2": 500, "y2": 900, "rot": 0}}}
}]
# Represents a mechanically fixed point, providing a stationary reference for the EMF housing.
fixed = RotationalComponents.Fixed() [{
"Dyad": {"placement": {"icon": {"x1": 0, "y1": 700, "x2": 200, "y2": 900, "rot": 180}}}
}]
# Generates a sinusoidal signal (amplitude=1, frequency=1 rad/s, offset=0, start_time=0) to define the voltage source's behavior.
input_signal = BlockComponents.Sine(amplitude=1, frequency=1, offset=0, start_time=0) [{
"Dyad": {"placement": {"icon": {"x1": 300, "y1": 100, "x2": 500, "y2": 300, "rot": 0}}}
}]
# Ideal voltage source whose output voltage is driven by the input_signal.
sine_voltage = VoltageSource() [{
"Dyad": {"placement": {"icon": {"x1": 500, "y1": 400, "x2": 700, "y2": 600, "rot": 0}}}
}]
# Rotational inertia with moment of inertia J=100 kg.m^2, representing the mechanical load.
inertia = RotationalComponents.Inertia(J=100) [{
"Dyad": {"placement": {"icon": {"x1": 600, "y1": 700, "x2": 800, "y2": 900, "rot": 0}}}
}]
relations
connect(input_signal.y, sine_voltage.V) [{"Dyad": {"edges": [{"S": 1, "M": [{"x": 600, "y": 200}], "E": 2}]}}]
connect(fixed.spline, rot_emf.housing) [{"Dyad": {"edges": [{"S": 1, "E": 2}]}}]
connect(rot_emf.p, sine_voltage.p) [{"Dyad": {"edges": [{"S": 1, "M": [{"x": 400, "y": 500}], "E": 2}]}}]
connect(sine_voltage.n, rot_emf.n) [{
"Dyad": {
"edges": [
{
"S": 1,
"M": [
{"x": 750, "y": 500},
{"x": 750, "y": 650},
{"x": 550, "y": 650},
{"x": 550, "y": 950},
{"x": 400, "y": 950}
],
"E": 2
}
]
}
}]
connect(rot_emf.rotor, inertia.spline_a) [{"Dyad": {"edges": [{"S": 1, "E": 2}]}}]
metadata {
"Dyad": {
"tests": {"case1": {"stop": 10, "expect": {"signals": ["rot_emf.tau", "rot_emf.phi"]}}}
}
}
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 = RotationalEMFTest()
u0_case1 = []
prob_case1 = ODEProblem(model_case1, u0_case1, (0, 10))
sol_case1 = solve(prob_case1)
retcode: Success
Interpolation: 3rd order Hermite
t: 45-element Vector{Float64}:
0.0
9.999999999999999e-5
0.0010999999999999998
0.011099999999999997
0.050784137892691775
0.1133829487424738
0.191644891105999
0.2936084163925959
0.4184983331005152
0.5751396248233639
⋮
7.684915529389811
7.986681414428846
8.25722721731883
8.521456194377711
8.83549189247025
9.099472757655487
9.470267466874974
9.7314070007879
10.0
u: 45-element Vector{Vector{Float64}}:
[-0.0]
[3.1415925502355376e-8]
[3.801311978771164e-6]
[0.00038691875723072223]
[0.008033745377996374]
[0.03870786249505734]
[0.10209857892095617]
[0.20221973172562124]
[0.29789384703539257]
[0.3008998580674771]
⋮
[0.2224942357005495]
[0.0006192398610979312]
[0.16643016111145612]
[0.31691653962136546]
[0.07779740893221518]
[0.03016362779826914]
[0.3155524352589041]
[0.1777265823640727]
[2.234751943810411e-5]
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.rot_emf.tau])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "RotationalEMFTest_case1_sig0.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.rot_emf.tau], width=2, label="Actual value of rot_emf.tau")
if !isnothing(dfr_case1)
scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of rot_emf.tau")
end
plt
df_case1 = DataFrame(:t => sol_case1[:t], :actual => sol_case1[model_case1.rot_emf.phi])
dfr_case1 = try CSV.read(joinpath(snapshotsdir, "RotationalEMFTest_case1_sig1.ref"), DataFrame); catch e; nothing; end
plt = plot(sol_case1, idxs=[model_case1.rot_emf.phi], width=2, label="Actual value of rot_emf.phi")
if !isnothing(dfr_case1)
scatter!(plt, dfr_case1.t, dfr_case1.expected, mc=:red, ms=3, label="Expected value of rot_emf.phi")
end
plt
Related
Examples
Experiments
Analyses
Tests