(* @NESTEDCOMMENTS := 'Yes' *) (* @PATH := '\/FB\/Unity' *) (* @OBJECTFLAGS := '0, 8' *) (* @SYMFILEFLAGS := '2048' *) FUNCTION_BLOCK RAMP VAR_INPUT PV:REAL:=0.0;(*Переменная процесса*) SP:REAL:=0.0; (*Уставка, к которой стремимся*) RAMP_TIME:TIME; INDIRECT:BOOL; PLC_TIME:TIME; START:BOOL; STOP:BOOL; END_VAR VAR_OUTPUT OUT:REAL:=0.0;(*Выход с блока*) END_VAR VAR Selection:INT; FSP_SP:BOOL; FSP_PV:BOOL; R_TRIG:R_TRIG; AM:REAL; OS:REAL; Err:REAL; PT:TIME; Second:BOOL; tx:TIME; txr_diff:REAL; tx1:TIME; fr:REAL; fr1:REAL; END_VAR (* @END_DECLARATION := '0' *) CASE Selection OF 0: Selection:=1; (*Инициализация процесса*) 1: AM:=SP - PV; OS:=PV; PT:=RAMP_TIME; Second:=FALSE; Err:=0.0; R_TRIG (CLK:=FALSE); IF START THEN Selection:=2; END_IF; (*Если сетпоинт больше измеренной, то начинаем рост рамп, если меньше, то приравниваем плавающую к уставке*) 2: IF SP < PV AND NOT INDIRECT THEN Selection:=3; ELSIF SP > PV AND INDIRECT THEN Selection:=3; ELSIF SP > PV AND NOT INDIRECT THEN Selection:=4; ELSIF SP < PV AND INDIRECT THEN Selection:=4; END_IF; IF STOP THEN Selection:=11; END_IF; (* Присваиваем плавающей значение уставки*) 3: OUT:=SP; FSP_SP:=TRUE; FSP_PV:=FALSE; IF SP < PV AND NOT INDIRECT THEN Selection:=1; ELSIF SP > PV AND INDIRECT THEN Selection:=1; END_IF; IF STOP THEN Selection:=11; END_IF; (* Подготавливаем внутренние переменные к подсчету рамп*) 4: tx:=T#0s; tx:=T#0s; Err:=4.0; AM:=SP - PV; OS:=PV; IF NOT Second THEN Selection:=5; ELSIF Second THEN Selection:=6; END_IF; IF STOP THEN Selection:=11; END_IF; (* Двигаем рамп за заданный период времени*) 5: R_TRIG (CLK:=TRUE); FSP_SP:=FALSE; FSP_PV:=FALSE; IF R_TRIG.Q THEN tx1:=PLC_TIME; END_IF; tx:=PLC_TIME; txr_diff:=DINT_TO_REAL(TIME_TO_DINT(tx)) - DINT_TO_REAL(TIME_TO_DINT(tx1)); fr:=txr_diff/DINT_TO_REAL(TIME_TO_DINT(PT)); fr1:=fr - INT_TO_REAL(TRUNC(fr)); (*возвращает целочисленную часть числа с плавающей запятой.*) OUT:=AM * fr1 + OS; IF NOT INDIRECT THEN Err:=SP - OUT; ELSIF INDIRECT THEN Err:=OUT - SP; END_IF; IF Err <= ABS(AM/100.0)+ 0.3 OR (PV>SP AND NOT INDIRECT) OR (PVSP AND NOT INDIRECT) OR (PVOUT AND NOT INDIRECT THEN Selection:=10; ELSIF SPOUT AND INDIRECT THEN Selection:=9; END_IF; IF STOP THEN Selection:=11; END_IF; (* Уставка(SP)ушла в обратную сторону от роста переменной, значит устанавливаем выход равным уставке *) 9: OUT:=SP; FSP_SP:=TRUE; FSP_PV:=FALSE; IF SP>OUT AND NOT INDIRECT THEN Selection:=10; END_IF; IF SPSP THEN OUT:=SP; FSP_SP:=TRUE; FSP_PV:=FALSE; Selection:=1; ELSIF INDIRECT AND PV