Hallo Marco,
ich habe das von Dir gewünschte Verhalten in den von mir abgeänderten BLIND_*-Bausteinen drin. Ok, nicht ganz - ein kurzer Tastendruck bewirkt nicht immer ein festes Fahren und ein fixes Intervall, sondern bei Tastendrücken < 1 s fährt die Jalousie so lange, wie der Taster gedrückt ist (Tippbetrieb). Sobald er länger als 1 s gedrückt wird, fährt die Jalousie ganz hoch oder runter. Bei einem sehr langen Druck > 5 s gilt wieder der Tippbetrieb; die Jalousie stoppt also, wenn der Taster z. B. nach 10 s losgelassen wird.
Mit den Originalbausteinen hatte ich immer ein Problem, wenn ich die Lamellen nur ein bisschen verstellen wollte. Das wurde dann gerne als kurzer Tastendruck erkannt, und die Jalousie fuhr hoch oder runter. Mit dem jetzigen Verhalten kommen alle bei uns zuhause gut zurecht.
Interessiert? Biddeschön:
Deklaration:
FUNCTION_BLOCK BLIND_INPUT2
VAR_INPUT
POS, ANG : BYTE;
S1, S2 : BOOL;
IN : BOOL;
PI, AI : BYTE;
MAX_RUNTIME : TIME := T#60s;
MANUAL_TIMEOUT: TIME := T#1h;
END_VAR
VAR_INPUT CONSTANT
DEBOUNCE_TIME : TIME := T#20ms;
LONGCLICK_TIME : TIME := t#1s;
LONGERCLICK_TIME : TIME := t#5s;
MASTER_MODE : BOOL;
END_VAR
VAR_OUTPUT
QU : BOOL := TRUE;
QD : BOOL := TRUE;
STATUS : BYTE;
PO : BYTE := 100;
AO : BYTE := 90;
END_VAR
VAR
s1e, s2e : TOF;
s1long, s2long : TON;
s1longer, s2longer : TON;
tonAutoModeActivated : TON;
tx, last : TIME;
test : BOOL := FALSE;
END_VAR
(*
version 1.0 17 feb 2014
programmer MD
*)
Code:
(* read system timer *)
tx := DWORD_TO_TIME(T_PLC_MS());
(* debounce inputs S1 and S2 *)
s1e(in := S1, pt := DEBOUNCE_TIME);
s2e(in := S2, pt := DEBOUNCE_TIME);
(* decode long click for manual fully up/down actions *)
s1long(in := S1e.Q, pt := LONGCLICK_TIME);
s2long(in := S2e.Q, pt := LONGCLICK_TIME);
(* decode longer click for standard manual actions (inching operation) again *)
s1longer(in := S1e.Q, pt := LONGERCLICK_TIME);
s2longer(in := S2e.Q, pt := LONGERCLICK_TIME);
(* detect activation of manual mode *)
tonAutoModeActivated(IN := status=139, PT := t#1s);
(* decode actions *)
IF S1 AND S2 THEN (* activate automatic mode *)
status := 139;
ELSIF (s1e.Q AND NOT s1long.Q OR s1longer.Q) AND NOT (status = 139) THEN (* manual up (inching mode) *)
status := 132;
last := tx;
ELSIF (s2e.Q AND NOT s2long.Q OR s2longer.Q) AND NOT (status = 139) THEN (* manual down (inching mode) *)
status := 133;
last := tx;
ELSIF s1long.Q AND NOT s1longer.Q AND NOT (status = 139) THEN (* manual fully up *)
status := 134;
last := tx;
ELSIF s2long.Q AND NOT s2longer.Q AND NOT (status = 139) THEN (* manual fully down *)
status := 135;
last := tx;
ELSIF in THEN (* force position and angle according to AI/PI *)
status := 136;
last := tx;
END_IF;
(* state machine *)
CASE status OF
0: (* power up operation *)
status := 130;
130: (* automatic operation standby *)
IF NOT master_mode THEN
PO := POS;
AO := ANG;
END_IF;
QU := TRUE;
QD := TRUE;
131: (* manual operation standby *)
QU := FALSE;
QD := FALSE;
PO := POS;
AO := ANG;
(* manual mode will be ended when timeout is reached *)
IF tx - last >= manual_timeout THEN
status := 130;
END_IF;
132: (* manual operation up *)
QU := TRUE;
QD := FALSE;
PO := POS; AO := ANG;
last := tx;
IF NOT s1e.Q THEN status := 131; END_IF;
133: (* manual operation down *)
QU := FALSE;
QD := TRUE;
PO := POS; AO := ANG;
last := tx;
IF NOT s2e.Q THEN status := 131; END_IF;
134: (* manual operation single click up *)
QU := TRUE;
QD := FALSE;
PO := POS; AO := ANG;
IF tx - last >= max_runtime THEN status := 131; END_IF;
135: (* manual operation single click dn *)
QU := FALSE;
QD := TRUE;
PO := POS; AO := ANG;
IF tx - last >= max_runtime THEN status := 131; END_IF;
136: (* forced input in = true *)
QU := TRUE;
QD := TRUE;
PO := PI; AO := AI;
IF tx-last >= max_runtime THEN status := 130; END_IF;
139: (* force automatic operation *)
IF NOT master_mode THEN
PO := POS;
AO := ANG;
END_IF;
QU := TRUE;
QD := TRUE;
IF tonAutoModeActivated.Q THEN status := 130; END_IF;
END_CASE;
(* revision history
MD 17 feb 2014 rev. 1.0
new function block
*)