Initial commit: CODESYS tree, integration docs, Node-RED scripts.
PLC application sources (NVL, rooms, boiler), HA/Node-RED integration guide, and NVL patch utilities. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
(* === DECLARATION === *)
|
||||
TYPE struct_boiler_cmd :
|
||||
STRUCT
|
||||
// Control Commands
|
||||
ha_on: BOOL; // Home Assistant: Turn ON
|
||||
ha_off: BOOL; // Home Assistant: Turn OFF
|
||||
schedule_on: BOOL; // Scheduled ON (from automation)
|
||||
schedule_off: BOOL; // Scheduled OFF (from automation)
|
||||
|
||||
// Safety Input
|
||||
emergency_stop: BOOL; // Emergency stop (physical button or HA)
|
||||
|
||||
// Configuration (can be set via Node-RED)
|
||||
max_on_time_minutes: INT; // Maximum ON time in minutes (default: 480 = 8 hours)
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
@@ -0,0 +1,22 @@
|
||||
(* === DECLARATION === *)
|
||||
TYPE struct_boiler_status :
|
||||
STRUCT
|
||||
// State
|
||||
state: BOOL; // Current boiler state (ON/OFF)
|
||||
relay_output: BOOL; // Actual relay output state
|
||||
|
||||
// Runtime Info
|
||||
on_time_minutes: INT; // Current ON time in minutes
|
||||
remaining_minutes: INT; // Remaining time before auto-shutoff
|
||||
|
||||
// Safety Status
|
||||
emergency_active: BOOL; // Emergency stop is active
|
||||
time_limit_reached: BOOL; // Max time limit was reached
|
||||
|
||||
// Error Handling
|
||||
error_state: BOOL; // Error detected
|
||||
error_code: INT; // Error code (0=none, 1=emergency, 2=time limit)
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
@@ -0,0 +1,13 @@
|
||||
(* === DECLARATION === *)
|
||||
TYPE struct_lights:
|
||||
STRUCT
|
||||
l_1 : BOOL;
|
||||
l_2 : BOOL;
|
||||
l_3 : BOOL;
|
||||
l_4 : BOOL;
|
||||
l_5 : BOOL;
|
||||
l_6 : BOOL;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
@@ -0,0 +1,32 @@
|
||||
(* === DECLARATION === *)
|
||||
TYPE struct_room_cmds :
|
||||
STRUCT
|
||||
// Home Assistant Commands (set/reset)
|
||||
ha_l1_on: BOOL; // HA command: Light 1 ON
|
||||
ha_l1_off: BOOL; // HA command: Light 1 OFF
|
||||
ha_l2_on: BOOL;
|
||||
ha_l2_off: BOOL;
|
||||
ha_l3_on: BOOL;
|
||||
ha_l3_off: BOOL;
|
||||
ha_l4_on: BOOL;
|
||||
ha_l4_off: BOOL;
|
||||
ha_l5_on: BOOL;
|
||||
ha_l5_off: BOOL;
|
||||
ha_l6_on: BOOL;
|
||||
ha_l6_off: BOOL;
|
||||
|
||||
// Zigbee Switch Inputs (edge detection for toggle)
|
||||
zigbee_sw1: BOOL; // Zigbee switch 1 (edge detected)
|
||||
zigbee_sw2: BOOL;
|
||||
zigbee_sw3: BOOL;
|
||||
zigbee_sw4: BOOL;
|
||||
zigbee_sw5: BOOL;
|
||||
zigbee_sw6: BOOL;
|
||||
|
||||
// Global Commands
|
||||
ha_all_on: BOOL; // HA: All lights ON
|
||||
ha_all_off: BOOL; // HA: All lights OFF
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
@@ -0,0 +1,21 @@
|
||||
(* === DECLARATION === *)
|
||||
TYPE struct_room_outs :
|
||||
STRUCT
|
||||
l_1: BOOL; // Light 1 control output
|
||||
l_2: BOOL; // Light 2 control output
|
||||
l_3: BOOL; // Light 3 control output
|
||||
l_4: BOOL; // Light 4 control output
|
||||
l_5: BOOL; // Light 5 control output
|
||||
l_6: BOOL; // Light 6 control output
|
||||
|
||||
// Status feedback (read from actual relay outputs)
|
||||
l_1_status: BOOL; // Actual relay 1 state
|
||||
l_2_status: BOOL; // Actual relay 2 state
|
||||
l_3_status: BOOL; // Actual relay 3 state
|
||||
l_4_status: BOOL; // Actual relay 4 state
|
||||
l_5_status: BOOL; // Actual relay 5 state
|
||||
l_6_status: BOOL; // Actual relay 6 state
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
@@ -0,0 +1,15 @@
|
||||
(* === DECLARATION === *)
|
||||
TYPE struct_switches :
|
||||
STRUCT
|
||||
all_off:BOOL;
|
||||
all_on:BOOL;
|
||||
sw_1:BOOL;
|
||||
sw_2:BOOL;
|
||||
sw_3:BOOL;
|
||||
sw_4:BOOL;
|
||||
sw_5:BOOL;
|
||||
sw_6:BOOL;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
@@ -0,0 +1,23 @@
|
||||
(* === DECLARATION === *)
|
||||
TYPE struct_zones :
|
||||
STRUCT
|
||||
masterBedroom: struct_room_outs;
|
||||
masterBathroom: struct_room_outs;
|
||||
bedroom_1: struct_room_outs;
|
||||
bedroom_2: struct_room_outs;
|
||||
bathroom: struct_room_outs;
|
||||
guest_wc: struct_room_outs;
|
||||
kitchen: struct_room_outs;
|
||||
pantry: struct_room_outs;
|
||||
livingRoom: struct_room_outs;
|
||||
diningRoom: struct_room_outs;
|
||||
entrance: struct_room_outs;
|
||||
hallway: struct_room_outs;
|
||||
veranda: struct_room_outs;
|
||||
front: struct_room_outs;
|
||||
back: struct_room_outs;
|
||||
side: struct_room_outs;
|
||||
END_STRUCT
|
||||
END_TYPE
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
@@ -0,0 +1,8 @@
|
||||
(* === DECLARATION === *)
|
||||
{attribute 'qualified_only'}
|
||||
VAR_GLOBAL
|
||||
// ---------- Option C: relay feedback (copy of output) ----------
|
||||
|
||||
END_VAR
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
@@ -0,0 +1,26 @@
|
||||
(* === DECLARATION === *)
|
||||
//This gobal variable list is received via the network.
|
||||
//Protocol: UDP
|
||||
//Layout matches Node-RED nvl-send (no legacy struct_switches — removed on PLC)
|
||||
|
||||
{attribute 'qualified_only'}
|
||||
VAR_GLOBAL
|
||||
cmd_livingRoom : struct_room_cmds;
|
||||
cmd_dinningRoom : struct_room_cmds;
|
||||
cmd_kitchenArea : struct_room_cmds;
|
||||
cmd_hallway : struct_room_cmds;
|
||||
cmd_office : struct_room_cmds;
|
||||
cmd_bedroom : struct_room_cmds;
|
||||
cmd_masterBedroom : struct_room_cmds;
|
||||
cmd_masterBath : struct_room_cmds;
|
||||
cmd_shower : struct_room_cmds;
|
||||
cmd_guestWc : struct_room_cmds;
|
||||
cmd_outFront : struct_room_cmds;
|
||||
cmd_coveredVeranda : struct_room_cmds;
|
||||
cmd_outYard : struct_room_cmds;
|
||||
cmd_outBack : struct_room_cmds;
|
||||
boiler_cmd : struct_boiler_cmd;
|
||||
|
||||
END_VAR
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
@@ -0,0 +1,23 @@
|
||||
(* === DECLARATION === *)
|
||||
{attribute 'qualified_only'}
|
||||
|
||||
VAR_GLOBAL
|
||||
light_livingRoom : struct_room_outs;
|
||||
light_dinningRoom : struct_room_outs;
|
||||
light_kitchenArea : struct_room_outs;
|
||||
light_hallway : struct_room_outs;
|
||||
light_office : struct_room_outs;
|
||||
light_bedroom : struct_room_outs;
|
||||
light_masterBedroom : struct_room_outs;
|
||||
light_masterBath : struct_room_outs;
|
||||
light_shower : struct_room_outs;
|
||||
light_guestWc : struct_room_outs;
|
||||
light_outFront : struct_room_outs;
|
||||
light_coveredVeranda : struct_room_outs;
|
||||
light_outYard : struct_room_outs;
|
||||
light_outBack : struct_room_outs;
|
||||
boiler_status : struct_boiler_status;
|
||||
|
||||
END_VAR
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
@@ -0,0 +1,151 @@
|
||||
(* === DECLARATION === *)
|
||||
FUNCTION_BLOCK fb_boiler
|
||||
VAR_INPUT
|
||||
// Control Commands
|
||||
ha_on: BOOL; // Home Assistant ON command
|
||||
ha_off: BOOL; // Home Assistant OFF command
|
||||
schedule_on: BOOL; // Scheduled ON
|
||||
schedule_off: BOOL; // Scheduled OFF
|
||||
|
||||
// Safety
|
||||
emergency_stop: BOOL; // Emergency stop input
|
||||
|
||||
// Configuration
|
||||
max_on_time: TIME := T#8H; // Maximum ON time (default 8 hours)
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
// Outputs
|
||||
relay_control: BOOL; // Control output to relay
|
||||
|
||||
// Status
|
||||
state: BOOL; // Current state
|
||||
on_time_seconds: DINT; // Current ON time in seconds
|
||||
remaining_seconds: DINT; // Remaining time in seconds
|
||||
|
||||
// Safety Status
|
||||
emergency_active: BOOL; // Emergency stop active
|
||||
time_limit_reached: BOOL; // Time limit was reached
|
||||
error_state: BOOL; // Error flag
|
||||
error_code: INT; // Error code
|
||||
END_VAR
|
||||
VAR
|
||||
// Internal State
|
||||
internal_state: BOOL := FALSE;
|
||||
last_state: BOOL := FALSE;
|
||||
|
||||
// Edge Detection
|
||||
r_trig_ha_on: R_TRIG;
|
||||
r_trig_ha_off: R_TRIG;
|
||||
r_trig_schedule_on: R_TRIG;
|
||||
r_trig_schedule_off: R_TRIG;
|
||||
r_trig_emergency: R_TRIG;
|
||||
f_trig_emergency: F_TRIG;
|
||||
|
||||
// Timers
|
||||
on_timer: TON; // Counts ON time
|
||||
|
||||
// Time tracking
|
||||
max_on_seconds: DINT;
|
||||
END_VAR
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
// =====================================================
|
||||
// fb_boiler - Implementation
|
||||
// =====================================================
|
||||
// Priority (highest to lowest):
|
||||
// 1. Emergency Stop - Immediate shutdown
|
||||
// 2. Time Limit Exceeded - Auto shutdown
|
||||
// 3. OFF Commands - Turn off
|
||||
// 4. ON Commands - Turn on (if safe)
|
||||
// =====================================================
|
||||
|
||||
// Calculate max time in seconds
|
||||
max_on_seconds := TIME_TO_DINT(max_on_time) / 1000;
|
||||
|
||||
// Edge detection for commands
|
||||
r_trig_ha_on(CLK := ha_on);
|
||||
r_trig_ha_off(CLK := ha_off);
|
||||
r_trig_schedule_on(CLK := schedule_on);
|
||||
r_trig_schedule_off(CLK := schedule_off);
|
||||
r_trig_emergency(CLK := emergency_stop);
|
||||
f_trig_emergency(CLK := emergency_stop);
|
||||
|
||||
// =====================================================
|
||||
// SAFETY CHECKS (highest priority)
|
||||
// =====================================================
|
||||
|
||||
// Priority 1: Emergency Stop
|
||||
IF emergency_stop THEN
|
||||
internal_state := FALSE;
|
||||
emergency_active := TRUE;
|
||||
error_state := TRUE;
|
||||
error_code := 1; // Emergency stop active
|
||||
|
||||
// Priority 2: Time Limit Check
|
||||
ELSIF on_timer.Q THEN
|
||||
internal_state := FALSE;
|
||||
time_limit_reached := TRUE;
|
||||
error_state := TRUE;
|
||||
error_code := 2; // Time limit exceeded
|
||||
|
||||
// =====================================================
|
||||
// CONTROL LOGIC (only when safe)
|
||||
// =====================================================
|
||||
ELSE
|
||||
// Clear safety flags when emergency released
|
||||
IF f_trig_emergency.Q THEN
|
||||
emergency_active := FALSE;
|
||||
error_state := FALSE;
|
||||
error_code := 0;
|
||||
END_IF;
|
||||
|
||||
// Clear time limit flag when boiler turned off
|
||||
IF NOT internal_state THEN
|
||||
time_limit_reached := FALSE;
|
||||
IF error_code = 2 THEN
|
||||
error_state := FALSE;
|
||||
error_code := 0;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
// Priority 3: OFF Commands (HA OFF or Schedule OFF)
|
||||
IF r_trig_ha_off.Q OR r_trig_schedule_off.Q THEN
|
||||
internal_state := FALSE;
|
||||
|
||||
// Priority 4: ON Commands (HA ON or Schedule ON)
|
||||
ELSIF (r_trig_ha_on.Q OR r_trig_schedule_on.Q) AND NOT time_limit_reached THEN
|
||||
internal_state := TRUE;
|
||||
END_IF;
|
||||
END_IF;
|
||||
|
||||
// =====================================================
|
||||
// TIMER MANAGEMENT
|
||||
// =====================================================
|
||||
|
||||
// ON timer - counts total ON time
|
||||
on_timer(
|
||||
IN := internal_state AND NOT emergency_active,
|
||||
PT := max_on_time
|
||||
);
|
||||
|
||||
// Calculate current ON time in seconds
|
||||
IF internal_state THEN
|
||||
on_time_seconds := TIME_TO_DINT(on_timer.ET) / 1000;
|
||||
remaining_seconds := max_on_seconds - on_time_seconds;
|
||||
IF remaining_seconds < 0 THEN
|
||||
remaining_seconds := 0;
|
||||
END_IF;
|
||||
ELSE
|
||||
on_time_seconds := 0;
|
||||
remaining_seconds := max_on_seconds;
|
||||
END_IF;
|
||||
|
||||
// =====================================================
|
||||
// OUTPUT ASSIGNMENT
|
||||
// =====================================================
|
||||
|
||||
// Relay control - only ON when state is ON and no emergency
|
||||
relay_control := internal_state AND NOT emergency_active;
|
||||
|
||||
// State output
|
||||
state := internal_state;
|
||||
@@ -0,0 +1,57 @@
|
||||
(* === DECLARATION === *)
|
||||
FUNCTION_BLOCK fb_light
|
||||
VAR_INPUT
|
||||
// Home Assistant Commands
|
||||
ha_on: BOOL; // HA command: Turn ON
|
||||
ha_off: BOOL; // HA command: Turn OFF
|
||||
|
||||
// Zigbee Switch Input
|
||||
zigbee_sw: BOOL; // Zigbee switch (edge detected)
|
||||
|
||||
// Status Feedback
|
||||
relay_status: BOOL; // Actual relay state (read from EtherCAT)
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
light_output: BOOL; // Control output to relay
|
||||
light_status: BOOL; // Status to send back (actual relay state)
|
||||
END_VAR
|
||||
VAR
|
||||
// Edge triggers
|
||||
r_trig_ha_on: R_TRIG;
|
||||
r_trig_ha_off: R_TRIG;
|
||||
r_trig_zigbee: R_TRIG;
|
||||
|
||||
// Internal state
|
||||
light_state: BOOL := FALSE;
|
||||
END_VAR
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
// =====================================================
|
||||
// fb_light - Implementation (per redesign)
|
||||
// =====================================================
|
||||
// Priority (highest to lowest):
|
||||
// 1. HA OFF command - Always turns light OFF
|
||||
// 2. HA ON command - Always turns light ON
|
||||
// 3. Zigbee toggle - Toggles current state
|
||||
// 4. Maintain current state
|
||||
// =====================================================
|
||||
|
||||
// Edge detection for commands
|
||||
r_trig_ha_on(CLK := ha_on);
|
||||
r_trig_ha_off(CLK := ha_off);
|
||||
r_trig_zigbee(CLK := zigbee_sw);
|
||||
|
||||
// State machine
|
||||
IF r_trig_ha_off.Q THEN
|
||||
light_state := FALSE;
|
||||
ELSIF r_trig_ha_on.Q THEN
|
||||
light_state := TRUE;
|
||||
ELSIF r_trig_zigbee.Q THEN
|
||||
light_state := NOT light_state;
|
||||
END_IF;
|
||||
|
||||
// Output assignment
|
||||
light_output := light_state;
|
||||
|
||||
// Status feedback (read from actual relay)
|
||||
light_status := relay_status;
|
||||
@@ -0,0 +1,58 @@
|
||||
(* === 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;
|
||||
END_VAR
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
// =====================================================
|
||||
// fb_room - Implementation (per redesign)
|
||||
// =====================================================
|
||||
|
||||
// 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;
|
||||
|
||||
// Global Commands (overwrite outputs per redesign)
|
||||
IF switches.ha_all_off THEN
|
||||
lights.l_1 := FALSE;
|
||||
lights.l_2 := FALSE;
|
||||
lights.l_3 := FALSE;
|
||||
lights.l_4 := FALSE;
|
||||
lights.l_5 := FALSE;
|
||||
lights.l_6 := FALSE;
|
||||
ELSIF switches.ha_all_on 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;
|
||||
@@ -0,0 +1,20 @@
|
||||
(* === DECLARATION === *)
|
||||
FUNCTION_BLOCK fb_switch
|
||||
VAR_INPUT
|
||||
switches: struct_switches;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
lights: struct_lights;
|
||||
END_VAR
|
||||
VAR
|
||||
all_off: fb_toogleButton;
|
||||
all_on: fb_toogleButton;
|
||||
sw_1: fb_toogleButton;
|
||||
sw_2: fb_toogleButton;
|
||||
sw_3: fb_toogleButton;
|
||||
sw_4: fb_toogleButton;
|
||||
sw_5: fb_toogleButton;
|
||||
sw_6: fb_toogleButton;
|
||||
END_VAR
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
@@ -0,0 +1,25 @@
|
||||
(* === DECLARATION === *)
|
||||
FUNCTION_BLOCK fb_toogleButton
|
||||
VAR_INPUT
|
||||
|
||||
Input :BOOL;
|
||||
END_VAR
|
||||
VAR_OUTPUT
|
||||
Output :BOOL;
|
||||
|
||||
END_VAR
|
||||
VAR
|
||||
Switch: BOOL;
|
||||
Light: BOOL;
|
||||
Flag1: BOOL;
|
||||
Flag2: BOOL;
|
||||
RT: R_TRIG;
|
||||
Pulse: TP;
|
||||
CTU_0: CTU;
|
||||
CTD_0: CTD;
|
||||
CTU_1: CTU;
|
||||
CTU_2: CTU;
|
||||
TOF_0: TOF;
|
||||
END_VAR
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
@@ -0,0 +1,33 @@
|
||||
(* === DECLARATION === *)
|
||||
(* Water heater — fb_boiler; coil mapped to NVL_Sender.boiler_status.relay_output (%QX5.4). *)
|
||||
PROGRAM Boiler_PRG
|
||||
VAR
|
||||
heater : fb_boiler;
|
||||
max_on_minutes : INT;
|
||||
max_on_time : TIME;
|
||||
END_VAR
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
max_on_minutes := NVL_Receiver.boiler_cmd.max_on_time_minutes;
|
||||
IF max_on_minutes <= 0 THEN
|
||||
max_on_minutes := 480;
|
||||
END_IF;
|
||||
max_on_time := T#1M * max_on_minutes;
|
||||
|
||||
heater(
|
||||
ha_on := NVL_Receiver.boiler_cmd.ha_on,
|
||||
ha_off := NVL_Receiver.boiler_cmd.ha_off,
|
||||
schedule_on := NVL_Receiver.boiler_cmd.schedule_on,
|
||||
schedule_off := NVL_Receiver.boiler_cmd.schedule_off,
|
||||
emergency_stop := NVL_Receiver.boiler_cmd.emergency_stop,
|
||||
max_on_time := max_on_time
|
||||
);
|
||||
|
||||
NVL_Sender.boiler_status.state := heater.state;
|
||||
NVL_Sender.boiler_status.relay_output := heater.relay_control;
|
||||
NVL_Sender.boiler_status.on_time_minutes := DINT_TO_INT(heater.on_time_seconds / 60);
|
||||
NVL_Sender.boiler_status.remaining_minutes := DINT_TO_INT(heater.remaining_seconds / 60);
|
||||
NVL_Sender.boiler_status.emergency_active := heater.emergency_active;
|
||||
NVL_Sender.boiler_status.time_limit_reached := heater.time_limit_reached;
|
||||
NVL_Sender.boiler_status.error_state := heater.error_state;
|
||||
NVL_Sender.boiler_status.error_code := heater.error_code;
|
||||
@@ -0,0 +1,22 @@
|
||||
(* === DECLARATION === *)
|
||||
PROGRAM Lights
|
||||
VAR
|
||||
masterBedroom : fb_switch;
|
||||
masterBathroom: fb_switch;
|
||||
bedroom_1: fb_switch;
|
||||
bedroom_2: fb_switch;
|
||||
bathroom: fb_switch;
|
||||
guest_wc: fb_switch;
|
||||
kitchen: fb_switch;
|
||||
pantry: fb_switch;
|
||||
livingRoom: fb_switch;
|
||||
diningRoom: fb_switch;
|
||||
veranda: fb_switch;
|
||||
entrance: fb_switch;
|
||||
front: fb_switch;
|
||||
back: fb_switch;
|
||||
side: fb_switch;
|
||||
hallway: fb_switch;
|
||||
END_VAR
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
@@ -0,0 +1,116 @@
|
||||
(* === DECLARATION === *)
|
||||
(* Room lighting (redesign). Shower channels l_1..l_5 only — l_6 is water heater (Boiler_PRG). *)
|
||||
PROGRAM Lights_new
|
||||
VAR
|
||||
Living_Room: FB_ROOM;
|
||||
Dininng_Room: fb_room;
|
||||
Kitchen_Area: fb_room;
|
||||
Hallway: fb_room;
|
||||
Office: fb_room;
|
||||
Bedroom: fb_room;
|
||||
Master_Bedroom: fb_room;
|
||||
Master_bath: fb_room;
|
||||
Shower: fb_room;
|
||||
Guest_wc: fb_room;
|
||||
Outside_front: fb_room;
|
||||
Covered_Veranda: fb_room;
|
||||
Yard: fb_room;
|
||||
Outside_back: fb_room;
|
||||
END_VAR
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
Living_Room(
|
||||
switches := NVL_Receiver.cmd_livingRoom,
|
||||
relay_status := NVL_Sender.light_livingRoom
|
||||
);
|
||||
NVL_Sender.light_livingRoom := Living_Room.lights;
|
||||
|
||||
Dininng_Room(
|
||||
switches := NVL_Receiver.cmd_dinningRoom,
|
||||
relay_status := NVL_Sender.light_dinningRoom
|
||||
);
|
||||
NVL_Sender.light_dinningRoom := Dininng_Room.lights;
|
||||
|
||||
Kitchen_Area(
|
||||
switches := NVL_Receiver.cmd_kitchenArea,
|
||||
relay_status := NVL_Sender.light_kitchenArea
|
||||
);
|
||||
NVL_Sender.light_kitchenArea := Kitchen_Area.lights;
|
||||
|
||||
Hallway(
|
||||
switches := NVL_Receiver.cmd_hallway,
|
||||
relay_status := NVL_Sender.light_hallway
|
||||
);
|
||||
NVL_Sender.light_hallway := Hallway.lights;
|
||||
|
||||
Office(
|
||||
switches := NVL_Receiver.cmd_office,
|
||||
relay_status := NVL_Sender.light_office
|
||||
);
|
||||
NVL_Sender.light_office := Office.lights;
|
||||
|
||||
Bedroom(
|
||||
switches := NVL_Receiver.cmd_bedroom,
|
||||
relay_status := NVL_Sender.light_bedroom
|
||||
);
|
||||
NVL_Sender.light_bedroom := Bedroom.lights;
|
||||
|
||||
Master_Bedroom(
|
||||
switches := NVL_Receiver.cmd_masterBedroom,
|
||||
relay_status := NVL_Sender.light_masterBedroom
|
||||
);
|
||||
NVL_Sender.light_masterBedroom := Master_Bedroom.lights;
|
||||
|
||||
Master_bath(
|
||||
switches := NVL_Receiver.cmd_masterBath,
|
||||
relay_status := NVL_Sender.light_masterBath
|
||||
);
|
||||
NVL_Sender.light_masterBath := Master_bath.lights;
|
||||
|
||||
Shower(
|
||||
switches := NVL_Receiver.cmd_shower,
|
||||
relay_status := NVL_Sender.light_shower
|
||||
);
|
||||
// l_6 not used for shower — water heater uses boiler_status.relay_output (%QX5.4)
|
||||
NVL_Sender.light_shower.l_6 := FALSE;
|
||||
NVL_Sender.light_shower.l_6_status := FALSE;
|
||||
NVL_Sender.light_shower.l_1 := Shower.lights.l_1;
|
||||
NVL_Sender.light_shower.l_2 := Shower.lights.l_2;
|
||||
NVL_Sender.light_shower.l_3 := Shower.lights.l_3;
|
||||
NVL_Sender.light_shower.l_4 := Shower.lights.l_4;
|
||||
NVL_Sender.light_shower.l_5 := Shower.lights.l_5;
|
||||
NVL_Sender.light_shower.l_1_status := Shower.lights.l_1;
|
||||
NVL_Sender.light_shower.l_2_status := Shower.lights.l_2;
|
||||
NVL_Sender.light_shower.l_3_status := Shower.lights.l_3;
|
||||
NVL_Sender.light_shower.l_4_status := Shower.lights.l_4;
|
||||
NVL_Sender.light_shower.l_5_status := Shower.lights.l_5;
|
||||
|
||||
Guest_wc(
|
||||
switches := NVL_Receiver.cmd_guestWc,
|
||||
relay_status := NVL_Sender.light_guestWc
|
||||
);
|
||||
NVL_Sender.light_guestWc := Guest_wc.lights;
|
||||
|
||||
Outside_front(
|
||||
switches := NVL_Receiver.cmd_outFront,
|
||||
relay_status := NVL_Sender.light_outFront
|
||||
);
|
||||
NVL_Sender.light_outFront := Outside_front.lights;
|
||||
|
||||
Covered_Veranda(
|
||||
switches := NVL_Receiver.cmd_coveredVeranda,
|
||||
relay_status := NVL_Sender.light_coveredVeranda
|
||||
);
|
||||
NVL_Sender.light_coveredVeranda := Covered_Veranda.lights;
|
||||
|
||||
Yard(
|
||||
switches := NVL_Receiver.cmd_outYard,
|
||||
relay_status := NVL_Sender.light_outYard
|
||||
);
|
||||
NVL_Sender.light_outYard := Yard.lights;
|
||||
|
||||
Outside_back(
|
||||
switches := NVL_Receiver.cmd_outBack,
|
||||
relay_status := NVL_Sender.light_outBack
|
||||
);
|
||||
NVL_Sender.light_outBack := Outside_back.lights;
|
||||
10
codesys-tree/Device/Plc Logic/Application/PLC_PRG.st
Normal file
10
codesys-tree/Device/Plc Logic/Application/PLC_PRG.st
Normal file
@@ -0,0 +1,10 @@
|
||||
(* === DECLARATION === *)
|
||||
PROGRAM PLC_PRG
|
||||
VAR
|
||||
masterBedroom: fb_switch;
|
||||
END_VAR
|
||||
|
||||
(* === IMPLEMENTATION === *)
|
||||
// Room lights first; Boiler_PRG last (dedicated boiler_status.relay_output, not shower l_6).
|
||||
Lights_new();
|
||||
Boiler_PRG();
|
||||
Reference in New Issue
Block a user