Modular PID Control ? 5 - .

: 2009-04-03

: komatic

: ModPID



MODPID


1.DEAD_T .
2.NONLIN .
3.PULSEGEN PULSEGEN - .
4.RMP_SOAK

download , .

.

// STL checksum
//
FUNCTION_BLOCK FB104
TITLE =" dead time"
AUTHOR : AUT_1
FAMILY : MODCONT
NAME : DEAD_T
VERSION : " 1.0"
// reverse by komatic
(*
.
.
*)
VAR_INPUT
INV : REAL ; //
DB_NBR : BLOCK_DB ; //
DEAD_TM : TIME := T#10S; //
TRACK : BOOL ; // OUTV=INV
COM_RST : BOOL ; //
CYCLE : TIME := T#1S; //
END_VAR
VAR_OUTPUT
OUTV : REAL ; //
END_VAR
VAR
siPtr : INT := 1;
END_VAR
VAR_TEMP
diMax : INT ; //
diLauf : INT ; //
drOutv : REAL ; // OUTV
// dDummy : DWORD ; //Platzhalter fr L 8.1, LW 10
END_VAR
BEGIN
//
diMax:= REAL_TO_INT(DINT_TO_REAL(TIME_TO_DINT(DEAD_TM)) / DINT_TO_REAL(TIME_TO_DINT(CYCLE)));
IF COM_RST
THEN //
drOutv:=0.0;
siPtr:=1;
FOR diLauf:=1 TO diMax BY 1 DO // 0.0
DB_NBR.DD[(diLauf-1)*4]:=REAL_TO_DWORD(drOutv);
END_FOR;
ELSE //
IF (siPtr > diMax) OR (siPtr < 1) THEN siPtr:=1; END_IF;
drOutv:=DWORD_TO_REAL(DB_NBR.DD[(siPtr-1)*4]);
DB_NBR.DD[(siPtr-1)*4]:=REAL_TO_DWORD(INV);
siPtr:=siPtr+1;
IF TRACK THEN drOutv:=INV; END_IF;
END_IF;
OUTV:=drOutv;
END_FUNCTION_BLOCK

FUNCTION_BLOCK FB115
TITLE =" nonlinear static funktion"
AUTHOR : AUT_1
FAMILY : MODCONT
NAME : NONLIN
VERSION : " 1.0"
// reverse by komatic
(*
NONLIN
, , ,

.
NONLIN
. NONLIN
.
, 0,

, 0 1;
, (NBR_PTS),

, NBR_PTS (NBR_PTS 1).



.



.
- NONLIN
*)
VAR_INPUT
INV : REAL ; //
DF_OUTV : REAL ; //
DB_NBR : BLOCK_DB ; //
DFOUT_ON : BOOL ; //
TRACK : BOOL ; // OUTV=INV
COM_RST : BOOL ; //
END_VAR
VAR_OUTPUT
OUTV : REAL ; //
END_VAR
VAR
n : INT := 1; //
END_VAR
VAR_TEMP
EndPosition : BOOL ; //
Factor : REAL ; // (y2 - y1)/(x2 - x1)
rBegin : REAL ; //
rEnd : REAL ; //
END_VAR
BEGIN
IF COM_RST //
THEN
n:=1;
OUTV:=0.0;
ELSIF TRACK //
THEN
OUTV:=INV;
ELSE
EndPosition:=0; //
//------------------------------------------------------------------
REPEAT
rBegin:=DWORD_TO_REAL(DB_NBR.DD[(n-1)*8+2]); // X1
rEnd:=DWORD_TO_REAL(DB_NBR.DD[n*8+2]); // X2
IF INV>rBegin // X1
THEN
IF INV>rEnd // X2
THEN
IF n < WORD_TO_INT(DB_NBR.DW[0]) //
THEN
rBegin:=rEnd; // X1:=X2
n:=n+1; //
rEnd:=DWORD_TO_REAL(DB_NBR.DD[n*8+2]); // X2:=X2[n]
ELSE
EndPosition:=1; //
END_IF;
ELSE
EndPosition:=1; //
END_IF;
ELSE
IF n > 1 // 1
THEN
n:=n-1; //
rEnd:=rBegin; // X2:=X1
rBegin:=DWORD_TO_REAL(DB_NBR.DD[(n-1)*8+2]); // X1:=X[n-1]
ELSE
EndPosition:=1; //
END_IF;
END_IF;
UNTIL EndPosition //
END_REPEAT;
//------------------------------------------------------------------
//Factor:=(Y2 - Y1)/(X2 - X1)
Factor:=(DWORD_TO_REAL(DB_NBR.DD[n*8+6]) - DWORD_TO_REAL(DB_NBR.DD[(n-1)*8+6]))/(rEnd-rBegin);
// OUTV:=Factor*INV+Y1-(X1*rFactor)
OUTV:=INV*Factor + DWORD_TO_REAL(DB_NBR.DD[(n-1)*8+6]) - rBegin*Factor;
END_IF;
IF DFOUT_ON THEN OUTV:=DF_OUTV; END_IF; //
END_FUNCTION_BLOCK

PULSEGEN - .

FUNCTION_BLOCK FB120
TITLE =" pulse generator"
AUTHOR : AUT_1
FAMILY : MODCONT
NAME : PULSEGEN
VERSION : " 1.1"
// reverse by komatic
(*
PULSEGEN -
.
PULSEGEN
-.
-, PULSEGEN
INV (
INV LMN
PID-) ,
PER_TM.
, .
*)
VAR_INPUT
INV : REAL ; //
PER_TM : TIME := T#1S; //
P_B_TM : TIME := T#50MS; // /
RATIOFAC : REAL := 1.000000e+000; //
STEP3_ON : BOOL := TRUE; //
ST2BI_ON : BOOL ; //
MAN_ON : BOOL ; //
POS_P_ON : BOOL ; //
NEG_P_ON : BOOL ; //
SYN_ON : BOOL := TRUE; //
COM_RST : BOOL ; //
CYCLE : TIME := T#10MS; //
END_VAR
VAR_OUTPUT
QPOS_P : BOOL ; //
QNEG_P : BOOL ; //
END_VAR
VAR
sInvAlt : REAL ;
siZaehlPer : INT ;
siZaehlPTm : INT ;
sbPosP : BOOL := TRUE;
END_VAR
VAR_TEMP
rCycle : REAL ; //Abtastzeit in real
rPerTm : REAL ; //Periodendauer in real
rMinPTm : REAL ; //Mindestimpulsdauer in real
rRatioFac : REAL ; //Verhltnisfaktor
Offset : REAL ; //Offset
PTm : REAL ; //Impulsdauer
PTmHlm : REAL ; //Obere Begrenzung der Impulsdauer
PTmLlm : REAL ; //Untere Begrenzung der Impulsdauer
END_VAR
BEGIN
IF COM_RST
THEN
QPOS_P:=0;
QNEG_P:=0;
siZaehlPer:=0;
siZaehlPTm:=0;
sbPosP:=1;
ELSE
IF MAN_ON
THEN
IF STEP3_ON
THEN
IF POS_P_ON XOR NEG_P_ON
THEN
IF POS_P_ON
THEN
QPOS_P:=1;
QNEG_P:=0;
ELSE
QPOS_P:=0;
QNEG_P:=1;
END_IF;
ELSE
QPOS_P:=0;
QNEG_P:=0;
END_IF;
ELSE
IF POS_P_ON
THEN
QPOS_P:=1;
QNEG_P:=0;
ELSE
QPOS_P:=0;
QNEG_P:=1;
END_IF;
END_IF;
siZaehlPer:=0;
siZaehlPTm:=0;
sbPosP:=1;
ELSE
IF siZaehlPer <= 0
THEN
rCycle:=DINT_TO_REAL(TIME_TO_DINT(CYCLE));
rPerTm:=DINT_TO_REAL(TIME_TO_DINT(PER_TM));
rMinPTm:=DINT_TO_REAL(TIME_TO_DINT(P_B_TM));
siZaehlPer:=DINT_TO_INT(REAL_TO_DINT(rPerTm/rCycle));
IF siZaehlPer < 0
THEN
siZaehlPer:=0;
END_IF;
IF STEP3_ON
THEN
IF INV > 0.0
THEN
IF RATIOFAC > 1.0
THEN
rRatioFac:=1.0/RATIOFAC;
ELSE
rRatioFac:=1.0;
END_IF;
sbPosP:=1;
ELSE
IF RATIOFAC > 1.0
THEN
rRatioFac:=1.0;
ELSE
rRatioFac:=RATIOFAC;
END_IF;
sbPosP:=0;
END_IF;
Offset:=0.0;
ELSE
IF ST2BI_ON
THEN
IF INV<-100.0
THEN
Offset:=0.0;
rRatioFac:=0.0;
ELSE
Offset:=0.5*rPerTm;
rRatioFac:=0.5;
END_IF;
ELSE
Offset:=0.0;
IF INV < 0.0
THEN
rRatioFac:=0.0;
ELSE
rRatioFac:=1.0;
END_IF;
END_IF;
sbPosP:=1;
END_IF;
PTm:=ABS(INV*rRatioFac*rPerTm*0.01+Offset);
IF (NOT STEP3_ON) AND ST2BI_ON
THEN
rRatioFac:=1.0;
END_IF;
PTmHlm:=(rPerTm-rMinPTm)*rRatioFac;
PTmLlm:=rMinPTm*rRatioFac;
IF PTm > PTmHlm
THEN
PTm:=rPerTm*rRatioFac;
END_IF;
siZaehlPTm:=DINT_TO_INT(REAL_TO_DINT(PTm/rCycle));
IF PTm < PTmLlm
THEN
siZaehlPTm:=0;
END_IF;
END_IF;
IF ((INV <> sInvAlt) AND SYN_ON) AND (siZaehlPer > 2)
THEN
siZaehlPer:=1;
siZaehlPTm:=0;
END_IF;
IF STEP3_ON
THEN
IF siZaehlPTm = 0
THEN
QPOS_P:=0;
QNEG_P:=0;
ELSE
IF sbPosP
THEN
QPOS_P:=1;
QNEG_P:=0;
ELSE
QPOS_P:=0;
QNEG_P:=1;
END_IF;
END_IF;
ELSE
IF siZaehlPTm = 0
THEN
QPOS_P:=0;
ELSE
QPOS_P:=1;
END_IF;
QNEG_P:= NOT QPOS_P;
END_IF;
siZaehlPer:=siZaehlPer-1;
IF siZaehlPTm>0
THEN
siZaehlPTm:=siZaehlPTm-1;
ELSE
siZaehlPTm:=0;
END_IF;
END_IF;
END_IF;
sInvAlt:=INV;
END_FUNCTION_BLOCK

RMP_SOAK , , ()

// checksum
//
FUNCTION_BLOCK FB121
TITLE =" ramp soak"
AUTHOR : AUT_1
FAMILY : MODCONT
NAME : RMP_SOAK
VERSION : " 1.1"
// reverse by komatic
(*
RMP_SOAK , ,
() ,
,
.
RMP_SOAK
,
.
.

:
RMP_SOAK;
;
"" ;
;
;

.
*)
VAR_INPUT
DF_OUTV : REAL ; //
DB_NBR : BLOCK_DB ; //
TM_SNBR : INT ; // (CONT_ON)
TM_CONT : TIME ; // (CONT_ON)
DFOUT_ON : BOOL ; //
RMPSK_ON : BOOL ; //
HOLD : BOOL ; //
CONT_ON : BOOL ; //
CYC_ON : BOOL ; //
TUPDT_ON : BOOL ; //
COM_RST : BOOL ; //
CYCLE : TIME := T#1S; //
END_VAR
VAR_OUTPUT
OUTV : REAL ; //
QR_S_ACT : BOOL ; // -
NBR_ATMS : INT ; //
RS_TM : TIME ; //
T_TM : TIME ; //
RT_TM : TIME ; //
END_VAR
VAR
sOutEnd : REAL ;
sOutOld : REAL ;
siNbratms : INT ;
stRstm : TIME ;
stTtm : TIME ;
stRttm : TIME ;
sbStart : BOOL ; //
sbQrsact : BOOL ; //
END_VAR
VAR_TEMP
Sollwert : REAL ;
dOutNeu : REAL ; //
dJ : INT ; //
END_VAR
BEGIN
Sollwert:=DF_OUTV; //
IF COM_RST //
THEN
stTtm:=T#0MS; //
FOR dJ:=0 TO WORD_TO_INT(DB_NBR.DW0) - 1 BY 1 DO
stTtm:=DINT_TO_TIME(DWORD_TO_DINT(DB_NBR.DD[dJ*8+6]))+stTtm;
//
END_FOR;
dOutNeu:=0.0; //
stRttm:=stTtm;
sOutEnd:=0.0;
siNbratms:=0;
stRstm:=T#0MS;
sbStart:=1;
sbQrsact:=0;
ELSE
IF RMPSK_ON
THEN
IF sbStart
THEN
dOutNeu:=DWORD_TO_REAL(DB_NBR.DD2);
//
sOutEnd:=DWORD_TO_REAL(DB_NBR.DD10);
//
stRstm:=DINT_TO_TIME(DWORD_TO_DINT(DB_NBR.DD6));
//
stRttm:=stTtm;
siNbratms:=1;
sbStart:=0;
sbQrsact:=1;
ELSE
IF HOLD
THEN
sbQrsact:=0;
dOutNeu:=sOutOld;
IF CONT_ON
THEN
sOutEnd:=DWORD_TO_REAL(DB_NBR.DD[TM_SNBR*8+2]);
stRttm:=TM_CONT;
stRstm:=TM_CONT;
siNbratms:=TM_SNBR;
FOR dJ:=siNbratms TO WORD_TO_INT(DB_NBR.DW0) - 1 BY 1 DO
stRttm:=DINT_TO_TIME(DWORD_TO_DINT(DB_NBR.DD[dJ*8+6]))+stRttm;
END_FOR;
END_IF;
ELSE
IF stRstm > CYCLE
THEN
dOutNeu:=(sOutEnd-sOutOld) / DINT_TO_REAL(TIME_TO_DINT(stRstm))
* DINT_TO_REAL(TIME_TO_DINT(CYCLE)) + sOutOld;
stRstm:=stRstm-CYCLE;
stRttm:=stRttm-CYCLE;
ELSE
IF siNbratms < WORD_TO_INT(DB_NBR.DW0)
THEN
sOutEnd:=DWORD_TO_REAL(DB_NBR.DD[(siNbratms+1)*8+2]);
dOutNeu:=DWORD_TO_REAL(DB_NBR.DD[siNbratms*8+2]);
stRstm:=DINT_TO_TIME(DWORD_TO_DINT(DB_NBR.DD[siNbratms*8+6]));
siNbratms:=siNbratms+1;
sbQrsact:=1;
stRttm:=stRttm-CYCLE;
ELSE
IF CYC_ON
THEN
sbStart:=1;
ELSE
sbQrsact:=0;
END_IF;
dOutNeu:=DWORD_TO_REAL(DB_NBR.DD[siNbratms*8+2]);
END_IF;
END_IF;
END_IF;
END_IF;
ELSE
sbStart:=1;
dOutNeu:=0.0;
QR_S_ACT:=0;
END_IF;
IF TUPDT_ON //
THEN
stTtm:=T#0MS;
stRttm:=stRstm;
FOR dJ:=0 TO WORD_TO_INT(DB_NBR.DW0)-1 BY 1 DO
stTtm:=DINT_TO_TIME(DWORD_TO_DINT(DB_NBR.DD[dJ*8+6]))+stTtm;
END_FOR;
FOR dJ:=siNbratms TO WORD_TO_INT(DB_NBR.DW0)-1 BY 1 DO
stRttm:=DINT_TO_TIME(DWORD_TO_DINT(DB_NBR.DD[dJ*8+6]))+stRttm;
END_FOR;
END_IF;
END_IF;
IF DFOUT_ON
THEN
dOutNeu:=Sollwert;
sbQrsact:=0;
END_IF;
OUTV:=dOutNeu;
sOutOld:=dOutNeu;
QR_S_ACT:=sbQrsact;
NBR_ATMS:=siNbratms;
RS_TM:=stRstm;
T_TM:=stTtm;
RT_TM:=stRttm;
END_FUNCTION_BLOCK





: 14871

: Pie-Man    : 2011-04-21

Modular Pid Control http://plcforum.uz.ua/viewtopic.php?f=9&t=15245

:     : 2013-06-18

. TIA ... TIA...

: liping wei    : 2017-04-29

Very good

:

(4000 max):

: