Re: PID autotune - la méthode du relais
Posté : 04 nov. 2016, 10:53
Salut damiette,
Le code SCL pour Step7 V5.5 si tu veux intégrer dans le TIA il y a quelques modifs à prévoir (voir les anciens post)
====================================================================================================
Le FB de mesure de fréquence
====================================================================================================
====================================================================================================
Le FB de la méthode du relais (c'est ce bloc qu'il faut appelé dans le programme)
====================================================================================================
Le code SCL pour Step7 V5.5 si tu veux intégrer dans le TIA il y a quelques modifs à prévoir (voir les anciens post)
====================================================================================================
Le FB de mesure de fréquence
====================================================================================================
Code : Tout sélectionner
FUNCTION_BLOCK FREQ_MEASURE
TITLE = 'FREQ_MEASURE'
//
//Adaptation du FB FREQ_MEASURE de la lib Util de 3S.
//La mesure ne doit pas dépasser 24D20H31M23S647MS car le débordement de l'horloge système n'est pas testé.
//
VERSION : '1.0'
AUTHOR : Cyril93
NAME : FREQ_MEA
FAMILY : MESURE
//KNOW_HOW_PROTECT
VAR_INPUT
IN: BOOL; (* input signal *)
PERIODS: INT :=1; (* out is the average frequency during PERIODS (number of periods) between 1 to 10 *)
RESET: BOOL; (* reset measurement *)
END_VAR
VAR_OUTPUT
OUT: REAL; (* frequency [Hz]*)
VALID: BOOL; (* FALSE: not yet PERIODS measurements done OR time distance between two rising edges > 3*OUT *)
END_VAR
VAR
OLDIN: BOOL;
INIT: BOOL;
OLDT: TIME;
DIFF: DINT;
ADIFF: ARRAY[0..9] OF DINT;
V: INT;
B:INT;
I: INT;
END_VAR
BEGIN
IF RESET THEN
B:=0;
V:=0;
INIT:=FALSE;
VALID:=FALSE;
OUT:=0;
RETURN;
END_IF;
IF IN AND NOT OLDIN THEN (*rising edge *)
IF INIT THEN
DIFF := TIME_TO_DINT(TIME_TCK()-OLDT);
IF Diff > 0 THEN
ADIFF[B] := DIFF;
B := (B+1) MOD PERIODS;
V:=MIN(IN1:=V+1, IN2:=PERIODS);
IF V=PERIODS THEN
OUT := 0;
FOR I:=0 TO PERIODS-1 DO
OUT := OUT + ADIFF[I];
END_FOR;
OUT := 1000.0 * PERIODS / OUT;
VALID:=TRUE;
ELSE
VALID:=FALSE;
END_IF;
END_IF;
END_IF;
INIT := TRUE;
OLDT := TIME_TCK();
ELSIF INIT AND VALID AND TIME_TO_DINT(TIME_TCK()-OLDT) > 3000*OUT THEN
VALID:=FALSE;
V:=0;
B:=0;
END_IF;
OLDIN:=IN;
END_FUNCTION_BLOCK
Le FB de la méthode du relais (c'est ce bloc qu'il faut appelé dans le programme)
====================================================================================================
Code : Tout sélectionner
FUNCTION_BLOCK CALC_PID
TITLE = 'CALC_PID'
//
//Auto-réglage des constantes PID par la méthode du relais de Astrom-Hagglund.
//
VERSION : '1.1'
AUTHOR : Cyril93
NAME : CALC_PID
FAMILY : REGUL
//KNOW_HOW_PROTECT
VAR_INPUT
bEN : BOOL; (* Démarre la séquence par le front montant *)
rSP : REAL; (* Point de consigne *)
rPV: REAL; (* Mesure process *)
iCY: INT:=2; (* Nombre de cycle du réglage automatique (minimum 2)*)
bRST: BOOL; (* Remise à zéro *)
rL_VAL: REAL; (* Valeur basse pour la sortie *)
rH_VAL: REAL; (* Valeur haute pour la sortie *)
iPERF: INT; (* Performances des constantes PID : 0=rapides, 1=normales, 2=lentes *)
END_VAR
VAR_OUTPUT
bEND: BOOL; (* Fin séquence *)
rSQ_VAL: REAL; (* Sortie onde carrée pour l'exitation du process *)
rKP: REAL; (* Gain proportionnel *)
rTN: REAL; (* Temps d'intégrale en s *)
rTV: REAL; (* Temps de dérivée en s *)
END_VAR
VAR
PU: REAL; (* Gain ultime *)
TU: REAL; (* Période ultime *)
b: REAL; (* Amplitude de PV *)
a: REAL; (* Amplitude de SQ_VAL *)
Tu_Freq: FREQ_MEASURE;
b_Min: REAL;
b_Max: REAL;
EdgeEnd: BOOL;
FlagEnd: BOOL;
End: BOOL;
status: INT;
cpt: INT;
old_bEN: BOOL;
RstFreq: BOOL;
PerFreq: INT;
END_VAR
CONST
PI := REAL#3.14159265358979323846264338327950288;
END_CONST
BEGIN
(*** Séquence autotune ***)
IF bRST THEN
status:=0;
END_IF;
CASE status OF
0: (* Attente Démarrage autotune *)
rSQ_VAL:=rL_VAL;
IF bEN AND NOT old_bEN THEN
RstFreq:=TRUE;
b_Min:=3.402823E+38 ;
b_Max:=-3.402823E+38 ;
rKP:=0;
rTN:=0;
rTV:=0;
cpt:=0;
bEND:=FALSE;
status:=1;
End:=FALSE;
END_IF;
1: (* Onde carrée haute *)
rSQ_VAL:=rH_VAL;
IF rPV > rSP THEN
rSQ_VAL:=rL_VAL;
cpt:=cpt+1;
status:=2;
END_IF;
2: (* Onde carrée basse et fin de séquence *)
IF rPV < rSP THEN
cpt:=cpt+1;
IF cpt >= iCY THEN
status:=1;
End:=TRUE;
ELSE
status:=1;
END_IF;
END_IF;
END_CASE;
old_bEN:=bEN;
(*** Calcul des paramètres ***)
(* min/max et freq de PV *)
IF rPV<b_Min THEN
b_Min:=rPV;
END_IF;
IF rPV>b_Max THEN
b_Max:=rPV;
END_IF;
(* Nombre de période pour le bloc FREQ_MEASURE *)
PerFreq:=(iCY/2)-1;
PerFreq:=LIMIT(MN:=1, IN:=PerFreq, MX:=10);
Tu_Freq(
IN := rPV > rSP ,
PERIODS :=PerFreq ,
RESET := RstFreq);
RstFreq:=FALSE;
(* Calcul sur front montant de End et valeur de sortie de FREQ_MEASURE ok *)
EdgeEnd:= End AND Tu_Freq.OUT <> 0 AND NOT FlagEnd;
FlagEnd:= End AND Tu_Freq.OUT <> 0;
IF EdgeEnd THEN
(* amp de SQ_VAL *)
a:=rH_VAL-rL_VAL;
(* amp de PV *)
b:=b_Max-b_Min;
(* Gain et période ultime *)
PU:=(4 * b)/(PI * a);
TU:=1/Tu_Freq.OUT;
(* Valeur PID *)
CASE iPERF OF
0:(* Performances rapides *)
rKP:= 0.6 * PU;
rTN:= 0.5 * TU;
rTV:= 0.125 * TU;
1:(* Performances normales *)
rKP:= 0.25 * PU;
rTN:= 0.5 * TU;
rTV:= 0.125 * TU;
2:(* Performances lentes *)
rKP:= 0.15 * PU;
rTN:= 0.5 * TU;
rTV:= 0.125 * TU;
END_CASE;
bEND:=TRUE;
status:=0;
END_IF;
END_FUNCTION_BLOCK