An industrial-grade production counting and alarm system developed in OpenPLC Editor using IEC 61131-3 Structured Text (ST)
This project implements a discrete event-driven production counting system representative of real-world manufacturing line control. The system monitors a digital photo-eye sensor input, accumulates part detections using rising-edge logic, and compares the running count against a configurable production target. Upon reaching that threshold, a discrete alarm output is asserted automatically — enabling downstream process control, operator notification, or conveyor interlock integration. The entire solution was developed in IEC 61131-3 compliant Structured Text within OpenPLC Editor and validated through live simulation.
In high-throughput industrial production environments, accurate part counting is critical for batch management, quality assurance, and overproduction prevention. Without reliable automated detection and alerting, operators must manually track output quantities — a process prone to human error, inconsistency, and delayed response. The requirement was to engineer a deterministic control solution capable of detecting individual product passage events at conveyor speed, maintaining an accurate running total, and issuing a real-time alarm signal the moment a configurable production target was met — all without operator intervention.
PartCount >= TargetCount; suitable for driving indicator lights, relay coils, or SCADA system inputsStructured Text was selected over Ladder Logic as the implementation language due to its superior handling of stateful conditional logic and scan-cycle-accurate edge detection. Ladder Logic's CTU (Count Up) function block introduced simulation instability in OpenPLC's runtime environment — specifically, inconsistent coil behavior across forced-input cycles. Migrating the logic to Structured Text resolved these runtime anomalies, eliminated dependency on standard function block libraries, and produced cleaner, more auditable control code aligned with modern IEC 61131-3 programming practices.
VAR_INPUT
PhotoEyeSensor : BOOL;
ResetButton : BOOL;
TargetCount : INT;
END_VAR
VAR_OUTPUT
AlarmOutput : BOOL;
END_VAR
VAR
PartCount : INT;
LastSensorState : BOOL;
END_VAR
IF ResetButton THEN
PartCount := 0;
END_IF;
IF PhotoEyeSensor AND NOT LastSensorState THEN
PartCount := PartCount + 1;
END_IF;
LastSensorState := PhotoEyeSensor;
IF PartCount >= TargetCount THEN
AlarmOutput := TRUE;
ELSE
AlarmOutput := FALSE;
END_IF;
System validation was performed entirely within the OpenPLC software runtime using the integrated simulator and real-time variable debugger. All inputs were exercised via forced variable injection to replicate physical field conditions without requiring external hardware. The following test scenarios were executed and verified:
TargetCount was forced to 10 at runtime to establish a known batch threshold for controlled testingPhotoEyeSensor was toggled manually across multiple scan cycles to simulate discrete product passage events at varied intervalsPartCount was confirmed to increment exactly once per rising-edge transition — sustained HIGH signals across multiple scans produced no additional counts, validating edge detection correctnessAlarmOutput asserted deterministically upon PartCount reaching 10, with no false positives observed during testingResetButton synchronously zeroed the accumulator and de-asserted AlarmOutput within the same scan cycle, confirming correct priority and execution order within the ST programThe primary technical obstacle encountered was instability in OpenPLC's handling of standard CTU (Count Up) function blocks within Ladder Logic networks. During forced-input simulation, the CTU block exhibited non-deterministic coil behavior — the counter value failed to update consistently across scan cycles when inputs were toggled via the debugger, likely due to internal state management conflicts between the function block instance and the simulator's forced-variable override mechanism.
The solution was to deprecate the CTU block entirely and re-implement the counting logic natively in Structured Text using an explicit LastSensorState latch variable for edge detection and a direct integer accumulator for the count register. This approach removed the dependency on library function blocks, gave full visibility and control over state transitions within each scan cycle, and proved significantly more stable under simulation. The experience reinforced the importance of understanding the underlying execution model of a PLC runtime — not just the syntax of the programming language — when diagnosing simulation-specific anomalies.