Engee documentation
Notebook

DC motor control

This example shows a comparison of three DC motor control methods.:

  • Direct control
  • Feedback management
  • LQR regulation.

Let's compare these methods in terms of sensitivity to load disturbances.

Setting the task

In DPT with armature control, the input voltage is controls the angular velocity of the motor shaft.

xxdcdemofigures_01.png

This example shows two ways to control the DPT to reduce sensitivity. load changes (changes in the torque generated by the engine load).

xxdcdemofigures_02.png

A simplified model of a DC motor is shown above. Torque parameter simulates load disturbances. It is necessary to minimize the speed fluctuations caused by such disturbances.

Let's set the engine parameters. In this example, the physical constants are:

In [ ]:
Pkg.add(["LinearAlgebra", "RobustAndOptimalControl", "ControlSystems", "ControlSystemsBase"])
In [ ]:
import Pkg; 
Pkg.add("ControlSystemsBase")
Pkg.add("RobustAndOptimalControl")
Pkg.add("LinearAlgebra")
   Resolving package versions...
  No Changes to `~/.project/Project.toml`
  No Changes to `~/.project/Manifest.toml`
   Resolving package versions...
  No Changes to `~/.project/Project.toml`
  No Changes to `~/.project/Manifest.toml`
   Resolving package versions...
    Updating `~/.project/Project.toml`
  [37e2e46d] + LinearAlgebra
  No Changes to `~/.project/Manifest.toml`
In [ ]:
using ControlSystems, ControlSystemsBase, RobustAndOptimalControl, LinearAlgebra

R = 2.0 ;   
L = 0.5;     
Km = 0.1;   
Kb = 0.1;    
Kf = 0.2;    
J = 0.02;    

Let's build a DPT model with two inputs (,) and one exit (To begin with, we will define the description of the blocks of the block diagram presented above in the form of transfer functions.

In [ ]:
h1 = tf([Km], [L, R])
h2 = tf([1], [J, Kf]) 
Out[0]:
TransferFunction{Continuous, ControlSystemsBase.SisoRational{Float64}}
    1.0
-----------
0.02s + 0.2

Continuous-time transfer function model

Let's establish a connection between the blocks. We will assign the names of the input and output signals, define the summing blocks, and establish a relationship between the blocks using the function connect().

We name the input and output signals.

In [ ]:
H1 = named_ss(h1, x = :xH1, u = :uH1, y = :yH1)
H2 = named_ss(h2, x = :xH2, u = :uH2, y = :yH2)
Kb = named_ss(ss(Kb), x = :xKb, u = :uKb, y = :yKb)

We indicate the signals that come in and out of the summing blocks.

In [ ]:
Sum1 = sumblock("uH1 = Va - yKb")
Sum2 = sumblock("uH2 = yH1 + Td")

We establish correspondences between the outputs and inputs of the blocks.

In [ ]:
connections = [
    :uH1 => :uH1;
    :yH1 => :yH1;
    :uH2 => :uH2;
    :yH2 => :uKb;
    :yKb => :yKb;   
]

We set the external input signals and the output signal.

In [ ]:
w1 = [:Va, :Td]
z1 = [:yH2]

Passing the parameters to the function connect() to get a model of the systems.

In [ ]:
dcm = connect([H2, H1, Kb, Sum1, Sum2], connections; z1, w1, verbose = true)

Now let's look at the reaction to a single step-by-step effect.

In [ ]:
V_a = dcm[1,1];
plot(stepinfo(step(V_a,2.5)))
Out[0]:

When applying a single step action to the input () the steady-state value of the output signal is 0.244.

Direct control of the DC motor

The first control option is direct control. We will supply the desired angular velocity value to the input system (), and also simulate the effect of an external moment () on the system.

xxdcdemofigures_03.png

Direct communication gain factor must be set to the inverse of the DC gain from before .

In [ ]:
Kff = 1/dcgain(V_a)[1]
Out[0]:
4.099999999999999

To evaluate the effectiveness of a feed-forward structure in the face of load disturbances, simulate the response to a step-by-step command With indignation between seconds:

In [ ]:
t = 0:0.01:15
Td = -0.1 * (5 .< t .< 10)          
u = hcat( ones( length(t) ), Td )       

cl_ff = dcm * Diagonal( [Kff, 1] )   

h_1 = lsim( cl_ff, u, t )
plot( h_1, label = "Прямое управление, h_1(t)" )
plot!( t, Td, label = "Внешний возмущающий момент, Td" )
Out[0]:

Feedback system

Let's consider the second control option and describe the feedback control structure.

xxdcdemofigures_04.png

To ensure zero steady-state error, we use the controller in the form of an integrator with a gain factor.

To determine the gain K, you can use the root hodograph method applied to open-loop transmission ():

In [ ]:
rlocusplot( ss( tf( 1, [1, 0] ) ) * V_a )
Out[0]:

Hover over the curves to see the values of the gain and the corresponding pole. You can see that the trajectories of the two roots intersect the imaginary axis. At these points . In order for our system to remain stable, it is necessary to choose . Choose .

In [ ]:
K = 5;

We name the input and output signals.

In [ ]:
C = named_ss( tf( K,[1, 0] ), x=:xC, u=:e, y=:Va )
Out[0]:
NamedStateSpace{Continuous, Float64}
A = 
 0.0
B = 
 2.0
C = 
 2.5
D = 
 0.0

Continuous-time state-space model
With state  names: xC
     input  names: e
     output names: Va

We indicate the signals that come in and out of the summing blocks.

In [ ]:
sum = sumblock( "e = w_ref - yH2" )
Out[0]:
sumblock: NamedStateSpace{Continuous, Float64}
D = 
 1.0  -1.0

Continuous-time state-space model
With state  names: 
     input  names: w_ref yH2
     output names: e

We establish correspondences between the outputs and inputs of the blocks.

In [ ]:
connections1 = [
    :e => :e;
    :Va => :Va;
    :yH2 => :yH2
]
Out[0]:
3-element Vector{Pair{Symbol, Symbol}}:
   :e => :e
  :Va => :Va
 :yH2 => :yH2

Setting the external input signals and the output signal

In [ ]:
w1 = [ :w_ref, :Td ]
z1 = [ :yH2 ]
Out[0]:
1-element Vector{Symbol}:
 :yH2

Passing the parameters to the function connect() to get a model of the system.

In [ ]:
cl_rloc = connect( [sum, C, dcm], connections1; w1, z1 )
Out[0]:
NamedStateSpace{Continuous, Float64}
A = 
 0.0   -12.5      0.0
 0.0   -10.0      3.2
 1.25   -0.3125  -4.0
B = 
 2.0  0.0
 0.0  8.0
 0.0  0.0
C = 
 0.0  6.25  0.0
D = 
 0.0  0.0

Continuous-time state-space model
With state  names: xC##feedback#237 xH2##feedback#227##feedback#237 xH1##feedback#227##feedback#237
     input  names: w_ref Td
     output names: yH2

Let's plot the output signals for direct control and feedback control.

In [ ]:
h_2 = lsim( cl_rloc, u, t )       
plot( h_1, label = "Прямое управление, h_1(t)" )
plot!( h_2, label = "Управление с обратной связью, h_2(t)" )
plot!( t, Td, label = "Внешний возмущающий момент, Td" )
Out[0]:

The result of feedback control is significantly better than the direct control method. However, there are peaks at the beginning and end of the action .

DC motor control using a linear-quadratic regulator

To further improve performance, let's try to design a linear-quadratic regulator (LQR) for the feedback structure shown below.

xxdcdemofigures_05.png

In addition to the integral, the LQR circuit also uses a state vector. for control voltage synthesis . The resulting voltage has the form

where - armature current

To better suppress disturbances, we use the cost function, which "punishes" a large integral error. For example,

where

Let's calculate the optimal LQR gain for this cost function.

Adding an exit w/s to the model dcm.

In [ ]:
dc_aug = [ 1 ; ss( tf( 1,[1, 0] ) ) ] * V_a 
Out[0]:
NamedStateSpace{Continuous, Float64}
A = 
 0.0    6.25     0.0
 0.0  -10.0      3.2
 0.0   -0.3125  -4.0
B = 
 0.0
 0.0
 0.5
C = 
 0.0  6.25  0.0
 1.0  0.0   0.0
D = 
 0.0
 0.0

Continuous-time state-space model
With state  names: ##x#239 xH2##feedback#227 xH1##feedback#227
     input  names: Va
     output names: ##y#2411 ##y#2412

We set the weight matrices Q and R, and synthesize the controller using the function lqr.

In [ ]:
Q = [ 20 0 0; 0 1 0; 0 0 1 ]
R = 0.01
K_lqr = lqr( dc_aug, Q, R )
Out[0]:
1×3 Matrix{Float64}:
 44.7214  25.5262  14.1526

Then we get a closed system.

Adding an exit x using add_output(). But for this, we need the dcm variable to have the StateSpace data type, as required by the function. add_output(). Therefore, we make the conversion using ss().

In [ ]:
dcm_new = add_output(ss(dcm), I(2))
Out[0]:
StateSpace{Continuous, Float64}
A = 
 -10.0      3.2
  -0.3125  -4.0
B = 
 0.0  8.0
 0.5  0.0
C = 
 6.25  0.0
 1.0   0.0
 0.0   1.0
D = 
 0.0  0.0
 0.0  0.0
 0.0  0.0

Continuous-time state-space model

Let's add an integrating link.

In [ ]:
C = K_lqr * append( tf(1, [1, 0]), tf(1), tf(1) ) 
Out[0]:
TransferFunction{Continuous, ControlSystemsBase.SisoRational{Float64}}
Input 1 to output 1
44.72135954999597
-----------------
      1.0s

Input 2 to output 1
25.526213567574707
------------------
       1.0

Input 3 to output 1
14.152551403054153
------------------
       1.0

Continuous-time transfer function model

Description of the open-loop control system with LQR.

In [ ]:
OL = dcm_new * append( C, ss(1) ) 
Out[0]:
StateSpace{Continuous, Float64}
A = 
 -10.0      3.2  0.0
  -0.3125  -4.0  2.795084971874748
   0.0      0.0  0.0
B = 
 0.0   0.0                0.0                8.0
 0.0  12.763106783787354  7.076275701527076  0.0
 8.0   0.0                0.0                0.0
C = 
 6.25  0.0  0.0
 1.0   0.0  0.0
 0.0   1.0  0.0
D = 
 0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0

Continuous-time state-space model

Description of a closed-loop control system with LQR.

In [ ]:
CL = feedback( OL, I(3), U1=1:3, Y1=1:3 )
Out[0]:
StateSpace{Continuous, Float64}
A = 
 -10.0                  3.2                0.0
 -13.075606783787354  -11.076275701527077  2.795084971874748
 -50.0                  0.0                0.0
B = 
 0.0   0.0                0.0                8.0
 0.0  12.763106783787354  7.076275701527076  0.0
 8.0   0.0                0.0                0.0
C = 
 6.25  0.0  0.0
 1.0   0.0  0.0
 0.0   1.0  0.0
D = 
 0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0
 0.0  0.0  0.0  0.0

Continuous-time state-space model

Transfer function (w_ref,Td)$\to$ w

In [ ]:
cl_lqr = CL[ 1, 1:3:4 ]
Out[0]:
StateSpace{Continuous, Float64}
A = 
 -10.0                  3.2                0.0
 -13.075606783787354  -11.076275701527077  2.795084971874748
 -50.0                  0.0                0.0
B = 
 0.0  8.0
 0.0  0.0
 8.0  0.0
C = 
 6.25  0.0  0.0
D = 
 0.0  0.0

Continuous-time state-space model

Finally, let's compare the three DPT control circuits by plotting the output signals.

In [ ]:
h_3 = lsim( cl_lqr, u, t )
plot( [h_1, h_2, h_3], label=["Прямое управление, h_1(t)" "Управление с обратной связью, h_2(t)" "Регулирование LQR, h_3(t)"] )
plot!( t, Td, label = "Внешний возмущающий моомент, Td" )
Out[0]:

Analyzing the graph, you can see that the peaks of the output signal have become smaller compared to the previous control method.

Conclusion

In this example, the creation of a model of a control object, a DC motor, was considered. Three methods of DPT management are compared. As a result of the analysis of the received system responses, the LQR control method proved to be the most effective and best combated the effects of an external disturbing moment.