БАЙТ, я не представитель Овен.

В CoDeSys библиотека Util позволяет ознакомиться с PID регулятором на ST
PID из Util:
Код:
(* PD controller *)
FUNCTION_BLOCK PID
VAR_INPUT
	ACTUAL :REAL;		(* actual value, process variable *)
	SET_POINT:REAL;	(* desired value, set point *)
	KP:REAL;				(* proportionality const. (P)*)
	TN:REAL;				(* reset time (I) in sec *)
	TV:REAL;				(* rate time, derivative time (D) in sec*)
	Y_MANUAL:REAL;		(* Y is set to this value as long as MANUAL=TRUE *)
	Y_OFFSET:REAL;		(* offset for manipulated variable *)
	Y_MIN:REAL;			(* minimum value for manipulated variable *)
	Y_MAX:REAL;			(* maximum value for manipulated variable *)
	MANUAL:BOOL;		(* 	TRUE: manual: Y is not influenced by controller,
								FALSE: controller determines Y *)
	RESET:BOOL;			(* reset: set Y output to Y_OFFSET and reset integral part *)
END_VAR
VAR_OUTPUT
	Y:REAL;				(* manipulated variable, set value*)
	LIMITS_ACTIVE:BOOL:=FALSE;	(* true set value would exceed limits Y_MIN, Y_MAX *)
	OVERFLOW:BOOL:=FALSE;		(* overflow in integral part *)
END_VAR
VAR
	CLOCK:TON;
	I: INTEGRAL;
	D: DERIVATIVE;
	TMDIFF: DWORD;
	ERROR: REAL;
	INIT: BOOL:=TRUE;
	Y_ADDOFFSET: REAL;
	KPcopy:REAL;
	TNcopy:REAL;
	TVcopy:REAL;
END_VAR

IF TN>0 AND KP<> 0 AND (NOT OVERFLOW OR RESET OR MANUAL) THEN
	ERROR := SET_POINT-ACTUAL;								(* Regeldifferenz *)

	IF RESET OR MANUAL OR INIT OR (KP<>KPcopy OR TN<>TNcopy OR TV<>TVcopy) THEN							(* Reset oder Handbetrieb *)
		I(RESET:=TRUE);
		D(RESET:=TRUE);
		OVERFLOW:=FALSE;
		LIMITS_ACTIVE:=FALSE;
		IF RESET OR INIT THEN
			Y := Y_OFFSET;
			INIT:=FALSE;
			Y_ADDOFFSET := 0;
		ELSIF MANUAL THEN
			Y := Y_MANUAL;
			Y_ADDOFFSET := Y_MANUAL-(Y_OFFSET+KP*(ERROR+I.OUT/TN+D.OUT*TV));
		ELSE
			Y_ADDOFFSET := Y - Y_OFFSET - KP*ERROR;
		END_IF
		TMDIFF:=0;
		CLOCK(IN:=FALSE);									(* Timer neu starten *)
		CLOCK(PT:=t#1h, IN:=TRUE);

		TNcopy := TN;
		TVcopy := TV;
		KPcopy := KP;
	ELSE
		CLOCK;												(* Timer abfragen *)
		TMDIFF:=TIME_TO_DWORD(CLOCK.ET);					(* Zeitdifferenz seit letztem Aufruf *)
	END_IF;

	IF TMDIFF>0 THEN
		CLOCK(IN:=FALSE);									(* Timer neu starten *)
		CLOCK(PT:=t#1h, IN:=TRUE);

		D(IN:=ERROR, TM:=TMDIFF, RESET:=FALSE);				(* Differential absch&#228;tzen *)
		I(IN:=ERROR, TM:=TMDIFF, RESET:=FALSE);				(* Integral absch&#228;tzen *)

		OVERFLOW := I.OVERFLOW;
		IF NOT OVERFLOW THEN
			Y:=Y_OFFSET+KP*(ERROR+I.OUT/TN+D.OUT*TV) + Y_ADDOFFSET;
			IF Y>1E30 OR Y<-1E30 THEN						(* Overflow steht bevor, darf aber eigentlich nicht passieren *)
				OVERFLOW:=TRUE;
			END_IF;

			LIMITS_ACTIVE:=FALSE;
			IF Y_MAX>Y_MIN AND Y>Y_MAX  THEN				(* Stellwert-Obergrenze &#252;berschritten *)
				LIMITS_ACTIVE:=TRUE;
				IF KP<>0 THEN
					I(IN:=(Y_MAX-Y)*TN/KP,TM:=1000,RESET:=FALSE);		(* Integral korrigieren *)
				END_IF
				Y:=Y_MAX;
			END_IF;
			IF Y_MAX>Y_MIN AND Y<Y_MIN THEN					(* Stellwert-Untergrenze unterschritten *)
				LIMITS_ACTIVE:=TRUE;
				IF KP<>0 THEN
					I(IN:=(Y_MIN-Y)*TN/KP,TM:=1000,RESET:=FALSE);		(* Integral korrigieren *)
				END_IF
				Y:=Y_MIN;
			END_IF;
		END_IF;
	ELSE
		CLOCK(PT:=t#1h,IN:=TRUE);
	END_IF;

END_IF;


Ещё открыт исходник ПИД регулятора из компонентов OwenLogic, хоть и на FBD.