blob: da3b92c2aa33d7618696b06a1e643c13252c5cb5 (
plain) (
tree)
|
|
(* @NESTEDCOMMENTS := 'Yes' *)
(* @PATH := '' *)
(* @OBJECTFLAGS := '0, 8' *)
(* @SYMFILEFLAGS := '2048' *)
FUNCTION_BLOCK FB_PID
VAR_INPUT (* ex.: positioning *)
IN_xEnable : BOOL := TRUE;
IN_xReset : BOOL;
IN_rW : REAL; (* ex -> target position *)
IN_rX : REAL; (* ex -> actual position *)
IN_rKp : REAL := 1.0;
IN_rKi : REAL := 1.0;
IN_rKd : REAL := 1.0;
IN_xLimit : BOOL := FALSE;
IN_rLimit : REAL := 1024;
IN_rTa : REAL; (* sampling rate in s *)
END_VAR
VAR_OUTPUT
OUT_rY : REAL; (* ex. -> set speed *)
END_VAR
VAR
rESum : REAL;
rE_old : REAL;
rE : REAL;
xWithinLimits : BOOL;
rY_tmp : REAL;
dwReset: DWORD;
END_VAR
(*
PID CONTROLLER
Author: mo
Date: 2019-02
|z
w e y v
-->( )--->[controller]---->[system]---->
^x |
| |
----------------------------------
Set up PID using Ziegler-Nichols-Method:
1) Ki = 0, Kd = 0
2) increase Kp until periodic oscillation occurs (and never stops swinging)
3) this value is Kp_crit
4) measured period length is T_crit
5) use this table
Kp = 0.6 * Kp_crit
Tn = 0.5 * T_crit
Tv = 0.12 * T_crit
-> with [Ki = Kp / Tn] and [Kd = Kp * Tv]:
Kp = 0.6 * Kp_crit
Ki = Kp / (0.5 * T_crit)
Kd = Kp * (0.12 * T_crit)
e.g.
Kp_crit = 25
T_crit = 2s
Kp = 0.6 * 25 = 15
Ki = 15 / (0.5 * 2s) = 15
Kd = 15 * (0.12 * 2s) = 3,6
*)
(* @END_DECLARATION := '0' *)
IF IN_xEnable
AND NOT IN_xReset
THEN
rE := IN_rW - IN_rX;
xWithinLimits := NOT IN_xLimit
OR (IN_xLimit AND rY_tmp >= -IN_rLimit AND rY_tmp < IN_rLimit);
IF xWithinLimits THEN
rESum := rEsum + rE;
END_IF
rY_tmp := (IN_rKp*rE) + (IN_rKi*IN_rTa*rEsum) + (IN_rKd*(rE-rE_old)/IN_rTa);
OUT_rY := rY_tmp;
IF NOT xWithinLimits THEN
IF OUT_rY >= 0 THEN OUT_rY := IN_rLimit; ELSE OUT_rY := -IN_rLimit; END_IF
END_IF
rE_old := rE;
END_IF
IF IN_xReset THEN
rESum := 0;
rE_old := 0;
dwReset := dwReset + 1;
END_IF
END_FUNCTION_BLOCK
|
in each repos: see "about"-tab (if existing) for more details / README.
dark theme is a modded version of: https://gist.github.com/Yoplitein/f4b671a2ec70c9e743fa