Hallo!
Anbei mal ein Software -PID Regler für einen SPS. Das ist zwar nicht
kompatibel, aber du kannst zumindest erkenn wie sowas gemacht wird
cu Afzelia
(* PID controller / PID-Regler *)<BR>
FUNCTION_BLOCK PID<BR>
VAR_INPUT<BR>
ACTUAL :REAL;
(* actual value, process variable / Istwer
t *)<BR>
SET_POINT:REAL; (* desired value, <FONT
COLOR=#0000FF>Set</FONT> point / Sollwert *)<BR>
KP:REAL; (* proportionality <FONT
COLOR=#0000FF>Const</FONT>. / Proportionalitätskoeff.&nbs
p; *)<BR>
TN:DWORD;
(* reset time / Nachstellzeit <FONT
COLOR=#0000FF>In</FONT> msec *)<BR>
TV:DWORD;
(* rate time, derivative time / Vorhaltzei
t <FONT COLOR=#0000FF>In</FONT> msec *)<BR>
Y_OFFSET:REAL; (* offset <FONT
COLOR=#0000FF>For</FONT> manipulated variable / Stel
lwert-Nullpunktsverschiebung *)<BR>
Y_MIN:REAL; (* minimum value <FONT
COLOR=#0000FF>For</FONT> manipulated variable / mini
maler Stellwert *)<BR>
Y_MAX:REAL; (* maximum value <FONT
COLOR=#0000FF>For</FONT> manipulated variable / maxi
maler Stellwert *)<BR>
MANUAL:BOOL; (* <FONT
COLOR=#0000FF>True</FONT>: manual / <FONT
COLOR=#0000FF>True</FONT>: manueller Betrieb *)<BR>
RESET:BOOL;<BR>
END_VAR<BR>
VAR_OUTPUT<BR>
Y:REAL; (* manipulated variable, <FONT
COLOR=#0000FF>Set</FONT> value / Stellgröße&nb
sp;*)<BR>
LIMITS_ACTIVE:BOOL:=<FONT COLOR=#0000FF>False</FONT>;<BR>
OVERFLOW:BOOL:=<FONT COLOR=#0000FF>False</FONT>;<BR>
END_VAR<BR>
VAR<BR>
CLOCK:TON;<BR>
I: INTEGRAL;<BR>
D: DERIVATIVE;<BR>
TMDIFF: DWORD;<BR>
<FONT COLOR=#0000FF>Error</FONT>: REAL;<BR>
INIT: BOOL:=<FONT COLOR=#0000FF>True</FONT>;<BR>
END_VAR<BR>
<BR>
<BR>
<BR>
<BR>
<FONT COLOR=#0000FF>If</FONT> TN>0 <FONT
COLOR=#0000FF>And</FONT> KP<> 0 <FONT
COLOR=#0000FF>And</FONT> (<FONT
COLOR=#0000FF>Not</FONT> OVERFLOW <FONT
COLOR=#0000FF>Or</FONT> RESET <FONT
COLOR=#0000FF>Or</FONT> MANUAL) <FONT
COLOR=#0000FF>Then</FONT><BR>
<FONT COLOR=#0000FF>Error</FONT> := SET_POINT-ACTUAL;
(* Regeldifferenz *)<BR>
<BR>
<FONT COLOR=#0000FF>If</FONT> RESET <FONT
COLOR=#0000FF>Or</FONT> MANUAL <FONT
COLOR=#0000FF>Or</FONT> INIT <FONT COLOR=#0000FF>Then</FONT>
(* Reset oder Handbetrieb *)<BR>
I(RESET:=<FONT COLOR=#0000FF>True</FONT>);<BR>
D(RESET:=<FONT COLOR=#0000FF>True</FONT>);<BR>
OVERFLOW:=<FONT COLOR=#0000FF>False</FONT>;<BR>
LIMITS_ACTIVE:=<FONT COLOR=#0000FF>False</FONT>;<BR>
<FONT COLOR=#0000FF>If</FONT> RESET <FONT
COLOR=#0000FF>Or</FONT> INIT <FONT
COLOR=#0000FF>Then</FONT><BR>
Y := Y_OFFSET;<BR>
INIT:=<FONT COLOR=#0000FF>False</FONT>;<BR>
END_IF;<BR>
TMDIFF:=0;<BR>
<FONT COLOR=#0000FF>Else</FONT><BR>
CLOCK;
(* Timer abfragen *)<BR>
TMDIFF:=TIME_TO_DWORD(CLOCK.ET);
(* Zeitdifferenz seit letztem Aufruf *)<BR>
END_IF;<BR>
<BR>
<FONT COLOR=#0000FF>If</FONT> TMDIFF>0 <FONT
COLOR=#0000FF>Then</FONT><BR>
CLOCK(<FONT COLOR=#0000FF>In</FONT>:=<FONT
COLOR=#0000FF>False</FONT>);
(* Timer neu starten *)<BR>
CLOCK(PT:=t#1h, <FONT COLOR=#0000FF>In</FONT>:=<FONT
COLOR=#0000FF>True</FONT>);<BR>
<BR>
D(<FONT COLOR=#0000FF>In</FONT>:=<FONT
COLOR=#0000FF>Error</FONT>, TM:=TMDIFF, RESET:=<FONT
COLOR=#0000FF>False</FONT>);
(* Differential abschätzen *)<BR>
I(<FONT COLOR=#0000FF>In</FONT>:=<FONT
COLOR=#0000FF>Error</FONT>, TM:=TMDIFF, RESET:=<FONT
COLOR=#0000FF>False</FONT>);
(* Integral abschätzen *)<BR>
<BR>
OVERFLOW := I.OVERFLOW;<BR>
<FONT COLOR=#0000FF>If</FONT> <FONT
COLOR=#0000FF>Not</FONT> OVERFLOW <FONT
COLOR=#0000FF>Then</FONT><BR>
Y:=Y_OFFSET+KP*(<FONT
COLOR=#0000FF>Error</FONT>+I.OUT/TN+D.OUT*TV);<BR>
<FONT COLOR=#0000FF>If</FONT> Y>1E30 <FONT
COLOR=#0000FF>Or</FONT> Y<-1E30 <FONT
COLOR=#0000FF>Then</FONT>
(* Overflow steht bevor, darf aber eigentl
ich nicht passieren *)<BR>
OVERFLOW:=<FONT COLOR=#0000FF>True</FONT>;<BR>
END_IF;<BR>
<BR>
LIMITS_ACTIVE:=<FONT COLOR=#0000FF>False</FONT>;<BR>
<FONT COLOR=#0000FF>If</FONT> Y_MAX>Y_MIN <FONT
COLOR=#0000FF>And</FONT> Y>Y_MAX <FONT
COLOR=#0000FF>Then</FONT>
(* Stellwert-Obergrenze überschritten *)<BR>
Y:=Y_MAX;<BR>
LIMITS_ACTIVE:=<FONT COLOR=#0000FF>True</FONT>;<BR>
I(<FONT COLOR=#0000FF>In</FONT>:=-<FONT
COLOR=#0000FF>Error</FONT>,TM:=TMDIFF,RESET:=<FONT
COLOR=#0000FF>False</FONT>);
(* Integral korrigieren *)<BR>
END_IF;<BR>
<BR>
<FONT COLOR=#0000FF>If</FONT> Y_MAX>Y_MIN <FONT
COLOR=#0000FF>And</FONT> Y<Y_MIN <FONT
COLOR=#0000FF>Then</FONT>
(* Stellwert-Untergrenze unterschritten *)<BR>
Y:=Y_MIN;<BR>
LIMITS_ACTIVE:=<FONT COLOR=#0000FF>True</FONT>;<BR>
I(<FONT COLOR=#0000FF>In</FONT>:=-<FONT
COLOR=#0000FF>Error</FONT>,TM:=TMDIFF,RESET:=<FONT
COLOR=#0000FF>False</FONT>);
(* Integral korrigieren *)<BR>
END_IF;<BR>
END_IF;<BR>
<FONT COLOR=#0000FF>Else</FONT><BR>
CLOCK(PT:=t#1h,IN:=<FONT COLOR=#0000FF>True</FONT>);<BR>
END_IF;<BR>
<BR>
END_IF;<BR>