Files
codesys-home-automation/codesys-tree/Device/Plc Logic/Application/3.Function Blocks/fb_room.st
root 4010649388 fix(fb_room): latch ha_all_on/off on rising edge, not level
Node-RED sends ha_all_on and ha_all_off as short NVL pulses (same as
zigbee_swN). Level-sensitive IF switches.ha_all_on caused all outputs to
drop when the pulse cleared (~1s flash then off).

Use R_TRIG plus all_on_latch: ALL ON edge latches room on until ALL OFF
edge. Document behaviour and Node-RED sparse merge in integration guide.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-26 18:30:06 +00:00

69 lines
2.5 KiB
Smalltalk

(* === DECLARATION === *)
FUNCTION_BLOCK fb_room
VAR_INPUT
switches: struct_room_cmds;
relay_status: struct_room_outs; // Read from EtherCAT outputs (actual relay states)
END_VAR
VAR_OUTPUT
lights: struct_room_outs;
END_VAR
VAR
l1: fb_light;
l2: fb_light;
l3: fb_light;
l4: fb_light;
l5: fb_light;
l6: fb_light;
r_trig_all_on: R_TRIG;
r_trig_all_off: R_TRIG;
all_on_latch: BOOL := FALSE; // Latched room-wide ON until ha_all_off rising edge
END_VAR
(* === IMPLEMENTATION === *)
// =====================================================
// fb_room - Implementation (per redesign)
// =====================================================
// Per-light: ha_lN_on/off and zigbee_swN use R_TRIG in fb_light (NVL pulses).
// Room-wide: ha_all_on / ha_all_off are also rising-edge pulses from Node-RED;
// latch all_on_latch so outputs stay on after the pulse ends (do not use level
// on switches.ha_all_on a FALSE NVL bit would drop back to per-light state).
// =====================================================
// Light 1..6 (relay_status = previous cycle output for Option C)
l1(ha_on := switches.ha_l1_on, ha_off := switches.ha_l1_off, zigbee_sw := switches.zigbee_sw1, relay_status := relay_status.l_1);
lights.l_1 := l1.light_output;
l2(ha_on := switches.ha_l2_on, ha_off := switches.ha_l2_off, zigbee_sw := switches.zigbee_sw2, relay_status := relay_status.l_2);
lights.l_2 := l2.light_output;
l3(ha_on := switches.ha_l3_on, ha_off := switches.ha_l3_off, zigbee_sw := switches.zigbee_sw3, relay_status := relay_status.l_3);
lights.l_3 := l3.light_output;
l4(ha_on := switches.ha_l4_on, ha_off := switches.ha_l4_off, zigbee_sw := switches.zigbee_sw4, relay_status := relay_status.l_4);
lights.l_4 := l4.light_output;
l5(ha_on := switches.ha_l5_on, ha_off := switches.ha_l5_off, zigbee_sw := switches.zigbee_sw5, relay_status := relay_status.l_5);
lights.l_5 := l5.light_output;
l6(ha_on := switches.ha_l6_on, ha_off := switches.ha_l6_off, zigbee_sw := switches.zigbee_sw6, relay_status := relay_status.l_6);
lights.l_6 := l6.light_output;
// Room-wide commands (rising edge + latch)
r_trig_all_on(CLK := switches.ha_all_on);
r_trig_all_off(CLK := switches.ha_all_off);
IF r_trig_all_on.Q THEN
all_on_latch := TRUE;
ELSIF r_trig_all_off.Q THEN
all_on_latch := FALSE;
END_IF;
IF all_on_latch THEN
lights.l_1 := TRUE;
lights.l_2 := TRUE;
lights.l_3 := TRUE;
lights.l_4 := TRUE;
lights.l_5 := TRUE;
lights.l_6 := TRUE;
END_IF;