Moscow, Azovskaya 14
+7 (495) 310-97-15
Mo-Fr: 9.00 - 18.00 (Moscow time)
Order a call
Callback
Your name *
Enter phone *
Your Email *
Call me back
Automatic PID tuning

Auto PID Tuning

The purpose of this article is to convey in an open and accessible form to the service engineers of APCS systems a simple and uncomplicated way to create a functional block capable of finding the optimal control coefficients (auto-tuning). It all started with the fact that I was completely tortured by poorly working PID controllers. The image and reputation of a service engineer who sets up an automated control system sometimes depends heavily on his technical ability to select PID coefficients (there is usually no time for this).


PID what is it?  It is a control algorithm designed to stabilize a process that has memory. It remembers the statistics of the behavior of the circuit over a certain period and makes dynamic adjustments to the behavior of the OUT output, depending on the entered coefficients.

Since my process is inert and slow, the D coefficient did not interest me at all. As a basis for the selection of coefficients, I used the "more-less" methodology with the analysis of the curve of the process variable. In other words, he created an algorithm that analyzes everything on its own and understands where it has a lot and where it has little. It turned out to be some approximation to the auto-tuning of the PID controller.

A way to create a function block capable of finding the optimal PID control gains

To be honest, to implement this idea, we had to create algorithms:

1. Simulator of the process curve with an element of a strong inertial link (heater heats the air in the ventilation duct)

2. Block LAG - exponential analog signal smoother

3. Block that calculates whether the curve is increasing or decreasing

4. Actually the block of automatic selection of coefficients

5. Block remembering the history of transitions (remembering 12 steps)

Everything works, though it takes a very long time to analyze.

This is how the autotuning algorithm looks like - state machine

PID Autotuning

This is how the graph looks at the beginning of work (periodic fluctuations are visible)

PID Autotuning

Coefficient selection schedule (beginning). This is how the schedule looked after an hour of work.PID Autotuning

PID coefficient selection chart (already much better)

This is what the graph looked like after 20 minutes: 

PID Autotuning

PID coefficient selection schedule (already almost the norm)

PID Autotuning

The schedule is almost back to normal.

Below is the code of the functional block, if it is useful to someone, I will be glad:

FUNCTION_BLOCK PID_Tuning

VAR_INPUT

PV:REAL;

SP:REAL;

END_VAR

VAR_OUTPUT

Delta_old:REAL; (*memorized value of the curve height from the very bottom to the very top*)

Delta_I:REAL;(*Absolute difference in 5 min*)

delta_SP:REAL; (*Real time total delta curve*)

Delta_SPH:REAL; (*curve height value from setpoint to top of curve*)

Delta_SPL:REAL; (*curve height value from set point to bottom of curve*)

Hi_val:REAL; (*maximum function value for a period of 5 minutes*)

Lo_val:REAL; (*minimum function value for a period of 5 minutes*)

Hi_val_TMP:REAL; (*time variable for calculating the maximum value of the function for a period of 5 minutes*)

Lo_val_TMP:REAL; (*time variable for calculating the minimum value of the function for a period of 5 minutes*)

Hi_val_old:REAL; (*remembered value*)

Lo_val_old:REAL; (*remembered value*)

State:INT; (*Process status*)
END_VAR
VAR_IN_OUT
P:REAL;
I:REAL;
D:REAL;
END_VAR
VAR
BLINK: BLINK; (*will give a pulse every 5 minutes *)
F_TRIG,F_TRIG1:F_TRIG; (**)
TON,TON1:TON;(**)
Count:INT;
State1,State2,State3,State4,State5,State6,State7,State8,State9,State10,State11,State12:INT; (*State machine switch *)
State_mem:State_mem;
Diff_SP:REAL;(*Разница между Delta_SPH и Delta_SPL*)
STBL:STBL;
INC1,DEC1,STBL1:BOOL;
TIME_ET:TIME;
TIME_UP:TIME;
TIME_DOWN:TIME;
TIME_UP_DOWN:TIME:=T#6m;
END_VAR
(* @END_DECLARATION := ‘0’ *)
BLINK(ENABLE:=1 , TIMELOW:=TIME_UP_DOWN , TIMEHIGH:=T#100ms , OUT=> );
TON1(IN:=NOT TON1.Q,PT:=T#24h); TIME_ET:=TON1.ET;
STBL(
PV:=PV ,
PT:= T#100ms,
INC=>INC1 ,
DEC=>DEC1 ,
STBL=>STBL1 );

F_TRIG(CLK:=INC1);(* When the rise ends *)
F_TRIG1(CLK:ЮC1 );(* When will the decline end? *)

IF F_TRIG.Q THEN Hi_val_TMP:=PV; Lo_val_TMP:=PV; TIME_UP:=TIME_ET; END_IF;(*Запоминаем первое значение, наверху*)
IF F_TRIG1.Q THEN Hi_val_old:=Hi_val; Lo_val_old:=Lo_val; TIME_DOWN:=TIME_ET; TIME_UP_DOWN:=TIME_DOWN – TIME_UP; END_IF;(*Запоминаем следующее значение, внизу*)

IF NOT BLINK.OUT THEN
IF PV > Hi_val_TMP THEN Hi_val:=PV; Hi_val_TMP:=PV; END_IF;(* As soon as the value of the curve in the BLINK time period becomes larger, it will be remembered *)
IF PV < Lo_val_TMP THEN Lo_val:=PV; Lo_val_TMP:=PV; END_IF;(* As soon as the value of the curve in the BLINK time period becomes larger, it will be remembered *)
END_IF;
Delta_I:«S(Hi_val – Lo_val);

IF SP<Hi_val_TMP THEN Delta_SPH:=Hi_val – SP; END_IF;
IF SP>Lo_val_TMP THEN Delta_SPL:=SP – Lo_val; END_IF;(* We calculate the undershoot or overshoot we have *)
IF Hi_val_TMP>SP AND SP>Lo_val_TMP THEN Delta_SP:Юlta_SPH + Delta_SPL; ELSE Delta_SP:=5.5; END_IF;
Diff_SP:«S((Delta_SPH – SP) – (SP – Delta_SPL));
CASE State OF
0:(* Initialization. Gathering process data *)
TON(IN:ЮC1,PT:=T#10s);
IF TON.Q THEN TON(IN:ъLSE); State:=1; END_IF;
1:(*Принимаем решение что меняем P или I*)
IF Delta_I<=1.5 AND Diff_SP<0.5 THEN State:=2; END_IF; (*It was decided that the integral coefficient is already correct *)
IF Delta_I>1.5 THEN State:=5; END_IF; (*It was decided that the integral coefficient is not correct *)
2:(*P overshoot or undershoot assessment *)
IF Delta_SPH>Delta_SPL THEN State:=3; END_IF; (*So there is an override *)
IF Delta_SPH<Delta_SPL THEN State:=4; END_IF; (*So there is an imbalance *)
3:(*P перерегулирование *)
IF F_TRIG.Q AND P>0.2 THEN P:=P – 0.1; Delta_old:Юlta_I; Count:=Count+1; END_IF;
IF F_TRIG1.Q THEN State:; END_IF;
4:(*P underregulation *)
IF F_TRIG.Q THEN P:=P + 0.1; Delta_old:Юlta_I; Count:=Count+1; END_IF;
IF F_TRIG1.Q THEN State:; END_IF;
10:(*P comparison of the total delta curve of the old and new overshoot *)
IF Delta_old > Delta_I THEN State:=3; END_IF;(* So it's improved, repeat *)
IF Delta_old < Delta_I THEN State:=4; END_IF;(* So it got worse, repeat *)
IF Count =3 THEN Count :=0; State:=5; END_IF;(* No need to change endlessly P*)
IF Delta_I<1.0 THEN State:=1; END_IF;(* So the setup is over. *)
11:(*P comparison of total delta curve of old and new*)

IF Delta_old > Delta_I THEN State:=4; END_IF;(*So improved, repeat*)

IF Delta_old < Delta_I THEN State:=3; END_IF;(*So it got worse, repeat*)

IF Count =3 THEN Count :=0; State:=5; END_IF;(*No need to change P indefinitely*)

IF Delta_I<1.0 THEN State:=1; END_IF;(*The setting is over*)

5:(*I have periodic fluctuations, remember delta_I_old*)
I:=I + 1.0; Delta_old:Юlta_I; Count:=Count+1;
State:=6;
6:(*I прибавляем к коэвициенту + 0,1 *)
IF F_TRIG.Q THEN I:=I + 1.0; Delta_old:Юlta_I; Count:=Count+1; END_IF;
IF F_TRIG1.Q THEN State:=7; END_IF;(*Go to comparison*)

7:(*I compare old delta and new*)

IF Delta_old > Delta_I THEN State:=6; END_IF;(*So improved, repeat*)

IF Delta_old < Delta_I THEN State:=8; END_IF;(*So it got worse, repeat*)

IF Count =4 THEN Count :=0; State:=2; END_IF;(*No need to change I indefinitely*)

IF Delta_I<1.0 THEN State:=1; END_IF;(*The setting is over*)

8: (* I decrease the coefficient - 0.1 *)
IF F_TRIG.Q THEN I:=I – 1.0; Delta_old:Юlta_I; Count:=Count+1; END_IF;
IF F_TRIG1.Q THEN State:=9; END_IF;(*Go to comparison*)

9:(*I compare old delta and new*)

IF Delta_old > Delta_I THEN State:=8; END_IF;(*So improved, repeat*)

IF Delta_old < Delta_I THEN State:=6; END_IF;(*So it got worse, repeat*)

IF Count =4 THEN Count :=0; State:=2; END_IF;(*No need to change I indefinitely*)

IF Delta_I<1.0 THEN State:=1; END_IF;(*It means that the setting is over*)
END_CASE;
State_mem(
IN:=State ,
IN1=>State1 ,
IN2=>State2 ,
IN3=>State3 ,
IN4=>State4 ,
IN5=>State5 ,
IN6=>State6 ,
IN7=>State7 ,
IN8=>State8 ,
IN9=>State9 ,
IN10=>State10 ,
IN11=>State11 ,
IN12=>State12 );
END_FUNCTION_BLOCK

If that doesn't work, please contact us and we'll try to help

#automatic, #tuning, #PID, #selectionofcoefficients, #autotuning

Be the first to comment

You comment add