|
| 1 | +# DC Motor with PI-controller |
| 2 | +In this example a PI-controller is setup for speed control of a DC-motor. First the needed packages |
| 3 | +are imported and the parameters of the model defined. |
| 4 | + |
| 5 | +```@example dc_motor_pi |
| 6 | +using ModelingToolkit |
| 7 | +using ModelingToolkitStandardLibrary.Electrical |
| 8 | +using ModelingToolkitStandardLibrary.Mechanical.Rotational |
| 9 | +using ModelingToolkitStandardLibrary.Blocks |
| 10 | +using OrdinaryDiffEq |
| 11 | +using Plots |
| 12 | +
|
| 13 | +@parameters t |
| 14 | +
|
| 15 | +R = 0.5 # [Ohm] |
| 16 | +L = 4.5e-3 # [H] |
| 17 | +k = 0.5 # [N.m/A] |
| 18 | +J = 0.02 # [kg.m²] |
| 19 | +f = 0.01 # [N.m.s/rad] |
| 20 | +tau_L_step = -3 # [N.m] |
| 21 | +nothing # hide |
| 22 | +``` |
| 23 | + |
| 24 | +The actual model can now be composed. |
| 25 | + |
| 26 | +```@example dc_motor_pi |
| 27 | +@named ground = Ground() |
| 28 | +@named source = Voltage() |
| 29 | +@named ref = Blocks.Step(height = 1, start_time = 0) |
| 30 | +@named pi_controller = Blocks.LimPI(k = 1.1, T = 0.035, u_max = 0.6, Ta = 0.035) |
| 31 | +@named feedback = Blocks.Feedback() |
| 32 | +@named R1 = Resistor(R = R) |
| 33 | +@named L1 = Inductor(L = L) |
| 34 | +@named emf = EMF(k = k) |
| 35 | +@named fixed = Fixed() |
| 36 | +@named load = Torque(use_support = false) |
| 37 | +@named load_step = Blocks.Step(height = tau_L_step, start_time = 3) |
| 38 | +@named inertia = Inertia(J = J) |
| 39 | +@named friction = Damper(d = f) |
| 40 | +@named speed_sensor = SpeedSensor() |
| 41 | +
|
| 42 | +connections = [connect(fixed.flange, emf.support, friction.flange_b) |
| 43 | + connect(emf.flange, friction.flange_a, inertia.flange_a) |
| 44 | + connect(inertia.flange_b, load.flange) |
| 45 | + connect(inertia.flange_b, speed_sensor.flange_a) |
| 46 | + connect(load_step.output, load.tau) |
| 47 | + connect(ref.output, feedback.input1) |
| 48 | + connect(speed_sensor.w_rel, feedback.input2) |
| 49 | + connect(feedback.output, pi_controller.err_input) |
| 50 | + connect(pi_controller.ctr_output, source.input) |
| 51 | + connect(source.p, R1.p) |
| 52 | + connect(R1.n, L1.p) |
| 53 | + connect(L1.n, emf.p) |
| 54 | + connect(emf.n, source.n, ground.g)] |
| 55 | +
|
| 56 | +@named model = ODESystem(connections, t, |
| 57 | + systems = [ |
| 58 | + ground, |
| 59 | + ref, |
| 60 | + pi_controller, |
| 61 | + feedback, |
| 62 | + source, |
| 63 | + R1, |
| 64 | + L1, |
| 65 | + emf, |
| 66 | + fixed, |
| 67 | + load, |
| 68 | + load_step, |
| 69 | + inertia, |
| 70 | + friction, |
| 71 | + speed_sensor, |
| 72 | + ]) |
| 73 | +nothing # hide |
| 74 | +``` |
| 75 | + |
| 76 | +Now the model can be simulated. Typical rotational mechanical systems are described via `DAE` |
| 77 | +(differential algebraic equations), however in this case ModelingToolkit can simplify the model enough |
| 78 | +so that it can be represented as a system of `ODEs` (ordinary differential equations). |
| 79 | + |
| 80 | +```@example dc_motor_pi |
| 81 | +sys = structural_simplify(model) |
| 82 | +prob = ODEProblem(sys, [], (0, 6.0)) |
| 83 | +sol = solve(prob, Rodas4()) |
| 84 | +
|
| 85 | +p1 = Plots.plot(sol.t, sol[inertia.w], ylabel = "Angular Vel. in rad/s", |
| 86 | + label = "Measurement", title = "DC Motor with Speed Controller") |
| 87 | +Plots.plot!(sol.t, sol[ref.output.u], label = "Reference") |
| 88 | +p2 = Plots.plot(sol.t, sol[load.tau.u], ylabel = "Disturbance in Nm", label = "") |
| 89 | +Plots.plot(p1, p2, layout = (2, 1)) |
| 90 | +nothing # hide |
| 91 | +``` |
| 92 | + |
| 93 | + |
0 commit comments