@@ -20,51 +20,54 @@ using ModelingToolkitStandardLibrary.Mechanical.Rotational
2020using ModelingToolkitStandardLibrary.Blocks
2121using OrdinaryDiffEq
2222using Plots
23-
24- R = 0.5 # [Ohm] armature resistance
25- L = 4.5e-3 # [H] armature inductance
26- k = 0.5 # [N.m/A] motor constant
27- J = 0.02 # [kg.m²] inertia
28- f = 0.01 # [N.m.s/rad] friction factor
29- tau_L_step = -0.3 # [N.m] amplitude of the load torque step
30- nothing # hide
3123```
3224
3325The actual model can now be composed.
3426
3527``` @example dc_motor_pi
36- systems = @named begin
37- ground = Ground()
38- source = Voltage()
39- ref = Blocks.Step(height = 1, start_time = 0)
40- pi_controller = Blocks.LimPI(k = 1.1, T = 0.035, u_max = 10, Ta = 0.035)
41- feedback = Blocks.Feedback()
42- R1 = Resistor(R = R)
43- L1 = Inductor(L = L)
44- emf = EMF(k = k)
45- fixed = Fixed()
46- load = Torque()
47- load_step = Blocks.Step(height = tau_L_step, start_time = 3)
48- inertia = Inertia(J = J)
49- friction = Damper(d = f)
50- speed_sensor = SpeedSensor()
28+ @mtkmodel DCMotor begin
29+ @parameters begin
30+ R = 0.5, [description = "Armature resistance"] # Ohm
31+ L = 4.5e-3, [description = "Armature inductance"] # H
32+ k = 0.5, [description = "Motor constant"] # N.m/A
33+ J = 0.02, [description = "Inertia"] # kg.m²
34+ f = 0.01, [description = "Friction factor"] # N.m.s/rad
35+ tau_L_step = -0.3, [description = "Amplitude of the load torque step"] # N.m
36+ end
37+ @components begin
38+ ground = Ground()
39+ source = Voltage()
40+ ref = Blocks.Step(height = 1, start_time = 0)
41+ pi_controller = Blocks.LimPI(k = 1.1, T = 0.035, u_max = 10, Ta = 0.035)
42+ feedback = Blocks.Feedback()
43+ R1 = Resistor(R = R)
44+ L1 = Inductor(L = L)
45+ emf = EMF(k = k)
46+ fixed = Fixed()
47+ load = Torque()
48+ load_step = Blocks.Step(height = tau_L_step, start_time = 3)
49+ inertia = Inertia(J = J)
50+ friction = Damper(d = f)
51+ speed_sensor = SpeedSensor()
52+ end
53+ @equations begin
54+ connect(fixed.flange, emf.support, friction.flange_b)
55+ connect(emf.flange, friction.flange_a, inertia.flange_a)
56+ connect(inertia.flange_b, load.flange)
57+ connect(inertia.flange_b, speed_sensor.flange)
58+ connect(load_step.output, load.tau)
59+ connect(ref.output, feedback.input1)
60+ connect(speed_sensor.w, :y, feedback.input2)
61+ connect(feedback.output, pi_controller.err_input)
62+ connect(pi_controller.ctr_output, :u, source.V)
63+ connect(source.p, R1.p)
64+ connect(R1.n, L1.p)
65+ connect(L1.n, emf.p)
66+ connect(emf.n, source.n, ground.g)
67+ end
5168end
5269
53- connections = [connect(fixed.flange, emf.support, friction.flange_b)
54- connect(emf.flange, friction.flange_a, inertia.flange_a)
55- connect(inertia.flange_b, load.flange)
56- connect(inertia.flange_b, speed_sensor.flange)
57- connect(load_step.output, load.tau)
58- connect(ref.output, feedback.input1)
59- connect(speed_sensor.w, :y, feedback.input2)
60- connect(feedback.output, pi_controller.err_input)
61- connect(pi_controller.ctr_output, :u, source.V)
62- connect(source.p, R1.p)
63- connect(R1.n, L1.p)
64- connect(L1.n, emf.p)
65- connect(emf.n, source.n, ground.g)]
66-
67- @named model = ODESystem(connections, t; systems)
70+ @named model = DCMotor()
6871nothing # hide
6972```
7073
@@ -75,12 +78,12 @@ so that it can be represented as a system of `ODEs` (ordinary differential equat
7578``` @example dc_motor_pi
7679sys = structural_simplify(model)
7780prob = ODEProblem(sys, unknowns(sys) .=> 0.0, (0, 6.0))
78- sol = solve(prob, Rodas4() )
81+ sol = solve(prob)
7982
80- p1 = plot(sol.t, sol[inertia.w], ylabel = "Angular Vel. in rad/s",
83+ p1 = plot(sol.t, sol[sys. inertia.w], ylabel = "Angular Vel. in rad/s",
8184 label = "Measurement", title = "DC Motor with Speed Controller")
82- plot!(sol.t, sol[ref.output.u], label = "Reference")
83- p2 = plot(sol.t, sol[load.tau.u], ylabel = "Disturbance in Nm", label = "")
85+ plot!(sol.t, sol[sys. ref.output.u], label = "Reference")
86+ p2 = plot(sol.t, sol[sys. load.tau.u], ylabel = "Disturbance in Nm", label = "")
8487plot(p1, p2, layout = (2, 1))
8588```
8689
@@ -89,8 +92,8 @@ plot(p1, p2, layout = (2, 1))
8992When implementing and tuning a control system in simulation, it is a good practice to analyze the closed-loop properties and verify robustness of the closed-loop with respect to, e.g., modeling errors. To facilitate this, we added two analysis points to the set of connections above, more specifically, we added the analysis points named ` :y ` and ` :u ` to the connections (for more details on analysis points, see [ Linear Analysis] ( @ref ) )
9093
9194``` julia
92- connect (speed_sensor. w, :y , feedback. input2)
93- connect (pi_controller. ctr_output, :u , source. V)
95+ connect (sys . speed_sensor. w, :y , feedback. input2)
96+ connect (sys . pi_controller. ctr_output, :u , source. V)
9497```
9598
9699one at the plant output (` :y ` ) and one at the plant input (` :u ` ). We may use these analysis points to calculate, e.g., sensitivity functions, illustrated below. Here, we calculate the sensitivity function $S(s)$ and the complimentary sensitivity function $T(s) = I - S(s)$, defined as
@@ -108,7 +111,7 @@ matrices_S, simplified_sys = Blocks.get_sensitivity(
108111 model, :y, op = Dict(unknowns(sys) .=> 0.0))
109112So = ss(matrices_S...) |> minreal # The output-sensitivity function as a StateSpace system
110113matrices_T, simplified_sys = Blocks.get_comp_sensitivity(
111- model, :y, op = Dict(inertia.phi => 0.0, inertia.w => 0.0))
114+ model, :y, op = Dict(model. inertia.phi => 0.0, model. inertia.w => 0.0))
112115To = ss(matrices_T...)# The output complementary sensitivity function as a StateSpace system
113116bodeplot([So, To], label = ["S" "T"], plot_title = "Sensitivity functions",
114117 plotphase = false)
0 commit comments