A production-grade, multi-tank industrial process control system implemented in CODESYS using IEC 61131-3 Structured Text (ST), encapsulated Function Block architecture, prioritized alarm management, cumulative runtime tracking, and a fully integrated HMI visualization layer
This project implements a fully automated water reclamation and staged transfer control system modeled on real industrial process requirements. The system coordinates fluid flow across three distinct process stages:
Automated transfer between stages is managed by three independently controlled pumps,
each governed by a reusable FB_Pump Function Block that encapsulates
command logic, feedback verification, fault detection, and accumulated runtime tracking.
The control system enforces safe operating envelopes through overflow prevention,
dry-run protection, and hardwired emergency stop handling at the scan-cycle level.
A full operator-facing HMI was implemented using CODESYS Visualization (Visu), providing real-time process status, active alarm display with priority classification, pump runtime indicators, and operator reset controls — all variable-linked directly to the running PLC program.
The control system was required to autonomously manage a staged fluid transfer process while enforcing safe operational limits across all process conditions. Specific functional requirements included:
TIME-typed accumulators per pump instance, incremented on a per-scan basis while feedback is activeSTRING-typed status variable reflecting current operational state for HMI displayIEC 61131-3 Structured Text was selected as the implementation language due to the multi-instance Function Block architecture, conditional alarm prioritization logic, and runtime accumulation requirements — all of which are significantly more maintainable, testable, and scalable in ST than equivalent Ladder Logic implementations. The modular FB design ensures that any of the three pump instances can be independently diagnosed, modified, or extended without impacting the broader program structure.
PROGRAM PLC_PRG
VAR
Auto_Mode : BOOL := TRUE;
Manual_Mode : BOOL := FALSE;
System_Reset : BOOL := FALSE;
Emergency_Stop : BOOL := FALSE;
Source_High : BOOL;
Source_Low : BOOL;
Process_High : BOOL;
Process_Low : BOOL;
Storage_High : BOOL;
Storage_Low : BOOL;
Cmd_Pump1_Start : BOOL;
Cmd_Pump2_Start : BOOL;
Cmd_Pump3_Start : BOOL;
Fb_Pump1_Running : BOOL;
Fb_Pump2_Running : BOOL;
Fb_Pump3_Running : BOOL;
Alarm_Overflow : BOOL;
Alarm_DryRun : BOOL;
Alarm_PumpFault : BOOL;
Alarm_HighPriority : BOOL;
Pump1_Runtime : TIME;
Pump2_Runtime : TIME;
Pump3_Runtime : TIME;
System_Status : STRING(50);
Current_Active_Alarm : STRING(100);
END_VAR
(* Fill Process Tank *)
IF Process_Low AND NOT Process_High THEN
Cmd_Pump1_Start := TRUE;
ELSE
Cmd_Pump1_Stop := TRUE;
END_IF;
(* Transfer Process → Storage *)
IF Process_High AND NOT Storage_High THEN
Cmd_Pump2_Start := TRUE;
ELSE
Cmd_Pump2_Stop := TRUE;
END_IF;
(* Supply Load from Storage *)
IF Storage_High AND Load_Demand THEN
Cmd_Pump3_Start := TRUE;
ELSE
Cmd_Pump3_Stop := TRUE;
END_IF;
(* Emergency Stop Override *)
IF Emergency_Stop THEN
Cmd_Pump1_Start := FALSE;
Cmd_Pump2_Start := FALSE;
Cmd_Pump3_Start := FALSE;
END_IF;
System verification was conducted entirely within the CODESYS online simulation environment using live variable forcing to inject controlled input states and validate deterministic output behavior across all defined operating scenarios and fault conditions.
Process_Low correctly triggered Pump 1 auto-start with confirmed feedback acknowledgmentStorage_High and Load_Demand asserted to verify Pump 3 supply mode activation and interlock sequencingEmergency_Stop forced TRUE mid-cycle to validate immediate, unconditional de-energization of all pump command outputs within the same scanSystem_Reset assertion
The primary engineering challenge was designing a reusable FB_Pump
Function Block architecture that could be instantiated across three independent
pump contexts while maintaining predictable, non-interfering alarm and fault behavior.
Ensuring that latched alarm states in one instance did not propagate incorrectly
through shared status variables required careful scoping of internal FB state and
explicit output mapping at the program level.
Debugging multi-stage conditional logic required tracing the full signal chain — from raw sensor input through command evaluation, feedback comparison, timer expiry, and alarm latch — rather than relying on final output observation alone. This reinforced disciplined use of intermediate status variables and structured test case design to isolate individual logic branches during verification.
Implementing the HMI required precise variable binding between Visu elements and PLC program variables, with particular attention to ensuring that pump run/fault/alarm state indicators accurately reflected the underlying Boolean logic states rather than command outputs alone — distinguishing between commanded and confirmed running states was essential for correct operator feedback.