Engee documentation
Notebook

Synthesis of the regulator

An example from the webinar "Engee capabilities for modeling Control Systems"

In [ ]:
using ControlSystems

Ways to connect systems

In [ ]:
W1 = tf(10, [9, 0.04, 0.01]);
W2 = tf(15, [2, 0.01, 0.7]);
Serial connection
Послед.png
In [ ]:
W = W1 * W2
Out[0]:
TransferFunction{Continuous, ControlSystemsBase.SisoRational{Float64}}
                                  150.0
-------------------------------------------------------------------------
18.0s^4 + 0.17s^3 + 6.320399999999999s^2 + 0.0281s + 0.006999999999999999

Continuous-time transfer function model
In [ ]:
W = series(W1, W2)
Out[0]:
TransferFunction{Continuous, ControlSystemsBase.SisoRational{Float64}}
                                                150.0
------------------------------------------------------------------------------------------------------
18.0s^4 + 0.16999999999999998s^3 + 6.320399999999999s^2 + 0.028099999999999997s + 0.006999999999999999

Continuous-time transfer function model
Parallel connection
![parallel png](attachment:parallel png)
In [ ]:
W = W1 + W2
Out[0]:
TransferFunction{Continuous, ControlSystemsBase.SisoRational{Float64}}
                         155.0s^2 + 0.7s + 7.15
-------------------------------------------------------------------------
18.0s^4 + 0.17s^3 + 6.320399999999999s^2 + 0.0281s + 0.006999999999999999

Continuous-time transfer function model
In [ ]:
W = parallel(W1, W2)
Out[0]:
TransferFunction{Continuous, ControlSystemsBase.SisoRational{Float64}}
                         155.0s^2 + 0.7s + 7.15
-------------------------------------------------------------------------
18.0s^4 + 0.17s^3 + 6.320399999999999s^2 + 0.0281s + 0.006999999999999999

Continuous-time transfer function model

Serial controller

In the first example, we will use the frequency characteristics to select a serial controller.

image.png
Management object
In [ ]:
s = tf("s")
sys = (1s+2)/(0.2*s^2 +1.2*s+1)
Out[0]:
TransferFunction{Continuous, ControlSystemsBase.SisoRational{Float64}}
    1.0s + 2.0
-------------------
0.2s^2 + 1.2s + 1.0

Continuous-time transfer function model
Characteristics of the Management Object
In [ ]:
p1 = ControlSystems.marginplot(sys)
p2 = plot(stepinfo(step(feedback(sys),0:0.01:5); settling_th=0.05), legend=:bottomright)
plot(p1, p2, layout = (1, 2))
Out[0]:
Requirements:
  • No static error
  • Overshoot <15%
  • Transition time <2 s
  • Phase margin >60°
The regulator is an integrating link

A system with zero astaticity order, therefore, in order to meet the requirement of no static error, we will first add an integrating link as a regulator.:

In [ ]:
controller = 1/s
p1 = ControlSystems.marginplot(sys*controller)
p2 = plot(stepinfo(step(feedback(sys*controller),0:0.01:10); settling_th=0.05), legend=:bottomright)
plot(p1, p2, layout = (1, 2))
Out[0]:
The regulator is an integrating link + Gain factor

The system has become accurate. But it's quite slow, so we'll add a gain factor.

In [ ]:
k = 5.6 # @param {type:"slider",min:0,max:10,step:0.1}
controller = k*1/s
p1 = ControlSystems.marginplot(sys*controller)
p2 = plot(stepinfo(step(feedback(sys*controller),0:0.01:5); settling_th=0.05), legend=:bottomright)
plot(p1, p2, layout = (1, 2))
Out[0]:
The regulator is an integrating link + Gain factor + Sequential phase-ahead correction device

It remains to increase the phase margin. It is necessary to change the slope of the frequency response in the medium frequency range in order to increase the stability of the system. To do this, we will add a sequential phase-ahead correction device.

In [ ]:
wz = 6.6 # @param {type:"slider",min:1,max:10,step:0.1}
wp = 20.6 # @param {type:"slider",min:1,max:100,step:0.1}
k = 6.8 # @param {type:"slider",min:0,max:10,step:0.1}
controller = k*1/s*(s+wz)/(s+wp)
p1 = ControlSystems.marginplot(sys*controller)
ControlSystems.bodeplot!(sys*k*1/s)
p2 = plot(stepinfo(step(feedback(sys*controller),0:0.01:5); settling_th=0.05), legend=:bottomright)
annotate!(p2, 2, 0.8, text("Regulator = $k*s*(s + "* string(round(1/wz, digits=3))*")/(s + "*string(round(1/wp, digits=3))*")", :left, 8, :black))
plot(p1, p2, layout = (1, 2))
Out[0]:

The resulting controller parameters can also be used in the model, for example, in the block Zeros and poles of the transfer function. You can verify this by examining the model. synthesis.engee.

The PID controller

In [ ]:
using EngeeControlSystems
PID controller in parallel form
In [ ]:
kp = 1.0
ki = 1.0
kd = 1.0
Tf = 0.01
pid_prl = Pid(kp, ki, kd, Tf) # continuous PID controller with first-order filter
Out[0]:
Pid(1.0, 1.0, 1.0, 0.01, nothing, nothing, nothing)
PID controller in standard form
In [ ]:
kp = 1.0
ti = 1.0
td = 1.0
n = 100
ts = 0.01
pid_std = PidStd(kp, ti, td, n, ts) # discrete PID controller with first-order filter
Out[0]:
PidStd(1.0, 1.0, 1.0, 100.0, 0.01, :forward_euler, :forward_euler)
In [ ]:
discr = c2d(pid_prl, ts)
Out[0]:
Pid(1.0, 1.0, 1.5819767068693265, 0.015819767068693265, 0.01, :forward_euler, :forward_euler)
In [ ]:
d2c(discr)
Out[0]:
Pid(1.0, 1.0, 1.0, 0.01, nothing, nothing, nothing)
In [ ]:
Ts_new = 0.02
d2d(pid_std, Ts_new)
Out[0]:
PidStd(1.0, 1.0, 2.0, 100.0, 0.02, :forward_euler, :forward_euler)
Auto-tuning the PID controller
In [ ]:
pi_c, info = pidtune(sys, :pi, :parallel)
Out[0]:
(Pid(0.3258464350718974, 3.352296639805523, 0.0, 0.0, nothing, nothing, nothing), (true, 3.2914794672549705, 59.999999999999986))
In [ ]:
Wzam = feedback(pi_c*sys)
t = 0:0.005:12.0
plot(stepinfo(step(Wzam, t)))
Out[0]:
In [ ]:
Wraz = pi_c*sys
ControlSystems.marginplot(Wraz)
Out[0]:

The result of the function pidtune it can be used in the model, for example, in the parameters of the PID controller block: Proportional coefficient: pi_c.kp and the Integral coefficient: pi_c.ki. An example is shown in the model synthesis.engee.