Je savais pas trop ou poster, soit dans tutoriel ou régulation ou codesys ?
Le sujet à déjà été évoqué mais comme je viens de retravailler dessus.
J'ai utilisé la méthode de Åström-Hägglund décrite dans les photos ci jointes, elle fonctionne bien et permet de gagner du temps par rapport à Ziegler et Nichols. Elle permet aussi de ne pas trop "pousser" le système et de garder le contrôle sur le process.
Je poste le code réalisé sur Codesys V2.3, j'ai utilisé les fonctions statistiques et mesure de fréquence de la biblio "Util" fourni par 3S.
Code : Tout sélectionner
FUNCTION_BLOCK CALC_PID
VAR_INPUT
bEN : BOOL; (* Démarre la séquence par le front montant *)
rSP : REAL; (* Point de consigne *)
rPV: REAL; (* Mesure process *)
byCY: BYTE:=20; (* Nombre de cycle du réglage automatique *)
bRST: BOOL; (* Remise à zéro *)
rL_VAL: REAL; (* Valeur basse pour la sortie *)
rH_VAL: REAL; (* Valeur haute pour la sortie *)
byPERF: BYTE; (* 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 *)
rTV: REAL; (* Temps de dérivée *)
END_VAR
VAR
PU: REAL; (* Gain ultime *)
TU: REAL; (* Période ultime *)
b: REAL; (* Amplitude de PV *)
a: REAL; (* Amplitude de SQ_VAL *)
b_Stat: STATISTICS_REAL;
Tu_Freq: FREQ_MEASURE;
status: BYTE;
cpt: BYTE;
TrigEn: R_TRIG;
TrigEnd: R_TRIG;
End: BOOL;
END_VAR
VAR CONSTANT
PI: REAL:=3.14159265358979323846264338327950288;
END_VAR
(*** Séquence autotune ***)
IF bRST THEN
status:=0;
END_IF
TrigEn(CLK:= bEN);
CASE status OF
0: (* Attente Démarrage autotune *)
rSQ_VAL:=rL_VAL;
IF TrigEn.Q THEN
b_Stat.RESET:=TRUE;
Tu_freq.RESET:=TRUE;
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 >= byCY THEN
status:=1;
End:=TRUE;
ELSE
status:=1;
END_IF
END_IF
END_CASE
(*** Calcul des paramètres ***)
(* min/max et freq de PV *)
b_Stat(
IN:= rPV,
RESET:= ,
MN=> ,
MX=> ,
AVG=> );
(* Nbre de période de FREQ_MEASURE *)
Tu_Freq.PERIODS:=(byCY/2)-1;
Tu_Freq.PERIODS:=LIMIT(1, Tu_Freq.PERIODS, 10);
Tu_Freq(
IN:= rPV > rSP,
PERIODS:=,
RESET:= ,
OUT=> ,
VALID=> );
b_Stat.RESET:=FALSE;
Tu_freq.RESET:=FALSE;
TrigEnd(CLK:= End AND Tu_Freq.OUT <> 0);
IF TrigEnd.Q THEN
(* amp de SQ_VAL *)
a:=rH_VAL-rL_VAL;
(* amp de PV *)
b:=b_Stat.MX-b_Stat.MN;
(* Gain et période ultime *)
PU:=(4 * b)/(PI * a);
TU:=1/Tu_Freq.OUT;
(* Valeur PID *)
CASE byPERF 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