Alguien del foro me pidió que le mostrara un FB PID en ST.He pensado que mejor mostrarlo aquí.
Este es el CALL TREE o árbol de llamadas del FB.

Lo primero que necesitamos para el FB es medir el ciclo de scan. Para eso esta la función T_PLC_US que basicamente recoge en un DWORD una marca de tiempo del plc. Luego el las funciones derivada e integral calcula el ciclo de scan restando la marca de tiempo actual – anterior.
FT_DERIV
DECLARACIÓN DE VARIABLES
FUNCTION_BLOCK FT_DERIV
VAR_INPUT
in : REAL;
K : REAL := 1;
run : BOOL := 1;
END_VAR
VAR_OUTPUT
out : REAL;
END_VAR
VAR
old: REAL;
tx: DWORD;
last: DWORD;
init: BOOL;
END_VAR
(*
version 1.4 6. nov. 2008
programmer hugo
tested by oscat
FT_deriv calculates the derivate over the signal "in" with Faktor "K".
a run input enables or stops the calculation, if left unconnected its true and therfore the calculation is executed.
if K is not specified the default is 1.
*)PROGRAMA
(* read system time *) tx := T_PLC_US(); (* init on firsat startup *) IF NOT init THEN init := TRUE; last := tx; old := in; ELSIF run AND tx - last > 0 THEN out := (in - old) / DWORD_TO_REAL(tx - last) * 1000000.0 * K; last := tx; old := in; ELSE out := 0; END_IF; (* hm 3.1.2007 rev 1.1 added init code for startup set the default for K to 1 hm 15. sep 2007 rev 1.2 replaced Time() with T_PLC_US for compatibility and performance reasons increased accuracy and work in microseconds internally hm 29 oct 2007 rev 1.3 prohibit calculation when tx - last = 0 to avoid division by 0 and increase accuracy on fast systems hm 6. nov. 2008 rev 1.4 improved performance *)
Como se puede ver, básicamente el programa hace este calculo (in – old) / tiempo de ciclo de scan * K.
Lógicamente (in – old) es el error del proceso.
FT_PIWL
DECLARACION DE VARIABLES
FUNCTION_BLOCK FT_PIWL
VAR_INPUT
IN : REAL;
KP : REAL := 1.0;
KI : REAL := 1.0;
LIM_L : REAL := -1E38;
LIM_H : REAL := 1E38;
RST : BOOL;
END_VAR
VAR_OUTPUT
Y : REAL;
LIM : BOOL;
END_VAR
VAR
init: BOOL;
tx: DWORD;
tc : REAL;
t_last: DWORD;
in_last : REAL;
i: REAL;
p: REAL;
END_VAR
(*
version 1.2 25. jan. 2009
programmer hugo
tested by oscat
FT_PIWL is a PI controller.
The PID controller works according to the fomula Y = IN *(KP+ KI * INTEG(e) ).
a rst will reset the integrator to 0
lim_h and Lim_l set the possible output range of the controller.
the output flag lim will signal that the output limits are active.
the integrator ist equipped with anti wind-up circuitry which limits trhe total output ranke to lim_l and lim_h
default values for KP = 1, KI = 1, ILIM_L = -1E37, iLIM_H = +1E38.
*)PROGRAMA
(* initialize at power_up *) IF NOT init OR RST THEN init := TRUE; in_last := in; t_last := T_PLC_US(); i := 0; tc := 0; ELSE (* read last cycle time in Microseconds *) tx := T_PLC_US(); tc := DWORD_TO_REAL(tx - t_last); t_last := tx; (* calculate proportional part *) p := KP * IN; (* run integrator *) i := (IN + in_last) * 5E-7 * KI * tc + i; in_last := IN; (* calculate output Y *) Y := p + i; (* check output for limits *) IF Y >= LIM_H THEN Y := LIM_H; IF ki <> 0 THEN i := LIM_H - p; ELSE i := 0; END_IF; LIM := TRUE; ELSIF Y <= LIM_L THEN Y := LIM_L; IF ki <> 0 THEN i := LIM_L - p; ELSE i := 0; END_IF; LIM := TRUE; ELSE LIM := FALSE; END_IF; END_IF; (* revision history hm 13. jun. 2008 rev 1.0 original version hm 27. oct. 2008 rev 1.1 integrator will not be adjusted when ki = 0 hm 25. jan 2009 rev 1.2 module will also work with negative K *)
Igualmente, en este caso el calculo integral es este:
i := (IN + inlast) * 5E-7 * KI * tc + i;
inlast := IN;
Visto de otra forma:
integral = [(Error + Error anterior) * Cte * Ciclo scan ] + integral anterior.





























