Też walczyłem z tymi wbudowanymi funkcjami z bibliotek. Niestety żadna nie działała tak jakbym chciał... w końcu napisałem swoją funkcję.
Nacisnę dłużej = zamyka lub otwiera do końca.
Nacisnę dwa razy = pozycja uchylona
Zatrzymanie = krótkie naciśnięcie
FUNCTION_BLOCK BLIND
VAR_INPUT
key_up,key_down : BOOL;
END_VAR
VAR_IN_OUT
param : type_param_blinds;
END_VAR
VAR_OUTPUT
engine_up, engine_down : BOOL;
END_VAR
VAR
_click_up , _click_down :CLICK_MODE;
k_long_up , k_single_up , k_double_up : BOOL;
k_long_down , k_single_down , k_double_down : BOOL;
shadow :BOOL := FALSE;
start_pulse_up,start_pulse_down, start_pulse_shadow : BOOL;
pulse_up, pulse_down,pulse_shadow :BOOL;
g_puls_up, g_puls_down,g_puls_shadow : GEN_PULSE;
r_puls_up, r_puls_down, r_puls_shadow : R_TRIG;
END_VAR
_click_up(
IN:= key_up ,
T_LONG:= _T_LONG ,
SINGLE=> k_single_up,
DOUBLE=> k_double_up,
LONG=> k_long_up ,
TP_LONG=> );
_click_down(
IN:= key_down ,
T_LONG:= _T_LONG ,
SINGLE=> k_single_down,
DOUBLE=> k_double_down,
LONG=> k_long_down ,
TP_LONG=> );
(*generatory impulsow do licznika CV*)
g_puls_up (ENQ := engine_up, PTH := DWORD_TO_TIME(param.time_up*5 ) , PTL := DWORD_TO_TIME(param.time_up*5 ) , Q => pulse_up);
g_puls_down (ENQ := engine_down, PTH := DWORD_TO_TIME(param.time_down*5), PTL := DWORD_TO_TIME(param.time_down*5) , Q => pulse_down);
g_puls_shadow (ENQ := engine_up OR engine_down, PTH := DWORD_TO_TIME(param.time_slot*5), PTL :=DWORD_TO_TIME(param.time_slot*5) , Q => pulse_shadow);
(*wykrywanie impulsow *)
r_puls_up(CLK := pulse_up);
r_puls_down(CLK := pulse_down);
r_puls_shadow (CLK := pulse_shadow);
(*modyfikacja CV zgodnie z wykrytymi impulsami*)
IF(r_puls_up.Q AND param.CV_S =100 AND param.CV < 100 ) THEN param.CV := param.CV + 1;END_IF;
IF(r_puls_down.Q AND param.CV > 0 ) THEN param.CV := param.CV - 1;END_IF;
IF(r_puls_shadow.Q) THEN
IF(engine_up AND param.CV_S < 100 ) THEN param.CV_S := param.CV_S + 1;
ELSIF(engine_down AND param.CV =0 AND param.CV_S > 0) THEN param.CV_S := param.CV_S -1;
END_IF;
END_IF;
(*ZATRZYMANIE SILNIKÓW*)
IF(engine_down OR engine_up) THEN
IF(k_single_down OR k_single_up OR param.open_close > 0) THEN
param.POS :=0; param.open_close:=0; engine_up := FALSE; engine_down := FALSE; shadow := FALSE;
END_IF;
END_IF;
(*jezeli pozycja auto nie ustalona*)
IF (param.POS = 0) THEN
(*jezeli roleta jest na dole*)
IF(param.CV = 0 ) THEN
IF(shadow AND param.CV_S = 100) THEN shadow := FALSE; engine_up := FALSE; engine_down := FALSE;
ELSIF(engine_down AND param.CV_S = 0) THEN engine_up := FALSE; engine_down := FALSE;
END_IF;
(*jezeli jest juz na gorze*)
ELSIF (param.CV = 100 AND engine_up) THEN engine_up := FALSE; engine_down := FALSE;
END_IF;
(*jezeli osiagniela zadana pozycje*)
ELSE IF(param.POS = param.CV) THEN param.POS := 0; engine_up := FALSE; engine_down := FALSE; END_IF;
END_IF;
(*URUCHOMIENIE SILNIKOW*)
IF(key_up OR key_down) THEN param.POS := 0 ; END_IF;
IF((k_long_up OR k_double_up) AND engine_down = FALSE) THEN
IF(k_double_up AND param.CV = 0) THEN shadow:= TRUE; END_IF;
engine_up := TRUE;
END_IF;
IF((k_long_down OR k_double_down) AND engine_up = FALSE) THEN
IF(k_double_down AND param.CV > 0) THEN shadow:= TRUE; END_IF;
engine_down := TRUE;
END_IF;
IF(param.open_close > 0) THEN
IF (param.open_close = 1) THEN engine_up := TRUE;
ELSIF (param.open_close = 2) THEN engine_down := TRUE;
END_IF;
param.open_close := 0;
END_IF;
IF(param.POS > 0) THEN
IF(param.POS > param.CV) THEN engine_up := TRUE;
ELSIF (param.POS < param.CV) THEN engine_down := TRUE;
ELSE param.POS := 0;
END_IF;
END_IF;
{attribute 'pack_mode' := '2'}
TYPE type_param_blinds :
STRUCT
time_up : BYTE ; res1: BYTE ;
time_down :BYTE ; res2:BYTE;
time_slot :BYTE; res3 :BYTE ;
res4 :BYTE ; res5:BYTE;
POS :BYTE := 0; res6:BYTE;
open_close :BYTE := 0; res7:BYTE;
CV : BYTE := 0; res8:BYTE;
CV_S :BYTE; res9:BYTE;
END_STRUCT
END_TYPE
K_BLIND (
key_up := K_K_ROL_UP,
key_down := K_K_ROL_DOWN,
engine_down => K_ROL_ENGINE_DOWN,
engine_up => K_ROL_ENGINE_UP,
param := _RETAIN.param_blinds[ K ],
);