PLC Programming with Structured Text (ST)

Learn how to program PLCs using IEC 61131-3 Structured Text, from core concepts to practical control applications. You will practice building reliable, readable logic with debugging, testing, and basic industrial integration.

1. PLC Fundamentals and Control Hardware Basics

PLC Fundamentals and Control Hardware Basics

Why PLCs exist

A programmable logic controller (PLC) is an industrial computer designed to control machines and processes reliably. PLCs became popular because they:

  • Survive heat, vibration, electrical noise, and continuous operation
  • Provide built-in, predictable connections to sensors and actuators
  • Let you change control behavior by changing the program instead of rewiring relay panels
  • If you are learning Structured Text (ST), you still need hardware basics because your program ultimately reads inputs from the real world and writes outputs that drive equipment.

    > A PLC is “a digital computer used for automation of electromechanical processes.” (Programmable logic controller)

    What a basic control system looks like

    A PLC-based system connects the physical process to software logic.

    !Block diagram of a typical PLC control system: sensors → PLC inputs → CPU/program → PLC outputs → actuators, plus power and networking

    Core PLC hardware components

    CPU (processor)

    The CPU executes your control program and manages communication with I/O and networks. In many PLC families, the CPU may be a separate module or integrated into a compact unit.

    What matters to you as a programmer:

  • The CPU runs your logic repeatedly in a loop (the scan cycle)
  • It stores variable values (your ST variables) in memory
  • It updates outputs based on the logic results
  • Memory (program and data)

    PLCs keep:

  • The program (your ST code compiled into executable form)
  • Data (variable values, timers, counters, setpoints)
  • Some memory is non-volatile (keeps data without power) and some is volatile (lost when power is removed). Whether a value is retained is an important design choice in later lessons.

    Power supply

    Most PLC systems use a dedicated industrial power supply (commonly 24 V DC for control electronics). The power supply choice affects reliability.

    Key ideas:

  • Size the supply for the PLC, I/O modules, and field devices (especially sensors)
  • Use proper grounding and wiring practices to reduce noise issues
  • Rack / backplane or compact housing

    Modular PLCs use a rack/backplane to:

  • Provide mechanical mounting
  • Distribute power and internal communication between modules
  • Compact PLCs integrate CPU and some I/O in one housing and may allow expansion modules.

    Inputs and outputs (I/O): how the PLC touches the real world

    Digital inputs

    A digital input has two logical states: ON/OFF.

    Common examples:

  • Pushbuttons and selector switches
  • Limit switches
  • n- Safety interlocks (wired through safety devices, not directly “trusted” in software)
  • Proximity and photoelectric sensors with discrete output
  • Practical notes:

  • Industrial digital inputs often use 24 V DC signaling
  • A real signal can “bounce” (especially mechanical contacts), which is why PLCs and programs often use filtering or debouncing concepts
  • Digital outputs

    A digital output turns something ON/OFF.

    Typical loads:

  • Relay coils / contactor coils (to switch motors)
  • Solenoid valves
  • Indicator lights (stack lights)
  • Two common output technologies:

  • Relay outputs: flexible for AC/DC and different voltages, but slower and limited by mechanical wear
  • Transistor outputs: fast switching for DC loads, longer life, but usually DC-only
  • Analog inputs

    An analog input measures a continuous value.

    Typical signals:

  • 4–20 mA current loop (common for industrial transmitters)
  • 0–10 V voltage signal
  • Typical devices:

  • Pressure, flow, and level transmitters
  • Temperature transmitters
  • Important programming implication:

  • The PLC converts the physical signal into a number using an analog-to-digital converter (ADC)
  • Your ST program usually works with a raw value (counts) and/or an engineering value (like bar, °C, %)
  • Analog outputs

    An analog output generates a continuous signal to command a device.

    Common uses:

  • Speed reference to a drive (for example, 0–10 V or 4–20 mA)
  • Position command to an actuator
  • Sensors and actuators: translating between physics and logic

    Sensors

    A sensor detects a physical condition and provides an electrical signal.

    Common categories:

  • Discrete sensors (digital): limit switch, inductive proximity, photoelectric
  • Continuous sensors (analog): pressure, temperature, flow, level
  • Two important specs to be aware of (we will use them later when handling signals in software):

  • Range: the minimum and maximum measurable value
  • Resolution: the smallest change that can be represented after conversion to a number
  • Actuators

    An actuator causes physical action.

    Examples:

  • Motors (often controlled through contactors or drives)
  • Pneumatic or hydraulic valves (solenoids)
  • Heaters
  • A PLC output rarely powers large actuators directly. Instead, it usually drives an intermediate device:

  • Contactor, motor starter, or variable frequency drive (VFD)
  • Relay or interposing relay
  • Solid-state relay
  • Signal types, wiring concepts, and why they matter to software

    Even if you are “only programming,” wiring choices affect what your program sees.

    Sourcing vs sinking (DC I/O)

    In 24 V DC systems, digital inputs and outputs are often described as sourcing or sinking.

    High-level meaning:

  • One side provides (+) power (sources current)
  • The other side provides the return path (sinks current)
  • This matters when selecting compatible sensors and I/O modules and when diagnosing why an input never turns ON.

    NPN vs PNP sensors (common DC sensor outputs)

    Many DC sensors come as:

  • PNP (typically “sources” current to the input when active)
  • NPN (typically “sinks” current when active)
  • A mismatch between sensor type and input module wiring is a classic commissioning problem.

    Noise and shielding (practical reliability)

    Industrial environments can introduce electrical noise from motors, contactors, and drives.

    Common mitigation methods:

  • Use shielded cable for analog signals when recommended
  • Separate high-power motor cables from low-level signal cables
  • Proper grounding and cable routing
  • From a software perspective, noise often appears as:

  • Flickering digital inputs
  • Unstable analog readings
  • The PLC scan cycle: the execution model behind your ST code

    Most PLCs operate in a repeating cycle:

  • Read inputs (capture the current state of input channels)
  • Execute the program (your logic runs using those captured values)
  • Update outputs (write results to output channels)
  • Perform communications/diagnostics (varies by PLC)
  • !Diagram of the PLC scan cycle showing how inputs are read, logic is executed, and outputs are updated repeatedly

    Why this matters for ST:

  • Your code is not “event-based” by default; it runs repeatedly
  • An input changing between scans is typically only recognized on the next scan
  • Output changes are typically applied after program execution, not instantly in the middle of a line of code
  • Safety basics: what software can and cannot do

    PLCs are widely used in industrial control, but safety must be designed carefully.

    Key principles:

  • Do not rely on standard PLC logic alone for emergency stop and personnel protection
  • Use appropriate safety components (safety relays or safety PLCs) where required
  • Treat safety signals and circuits as engineered systems, not just “another input”
  • This course focuses on ST programming, but good programmers respect safety boundaries and collaborate with safety engineers.

    PLCs, IEC 61131-3, and where Structured Text fits

    Many PLC environments follow the IEC 61131-3 standard for PLC programming languages. Structured Text is one of the languages defined there.

  • Structured Text is high-level and expressive (good for calculations, state machines, data handling)
  • You will still map variables to real I/O and run them within the PLC scan model
  • Reference:

  • IEC 61131-3
  • What you should be able to do after this article

    You should now be able to:

  • Describe what a PLC is and why it is used
  • Identify the main hardware parts (CPU, power supply, I/O modules)
  • Explain the difference between digital/analog inputs and outputs
  • Explain the scan cycle and why it affects program behavior
  • Recognize how sensors/actuators connect through I/O and intermediate devices
  • In the next article, we will move from hardware concepts to the software environment: projects, tasks/program organization, variable basics, and writing your first small ST logic that matches the scan-cycle model.

    2. IEC 61131-3 and Structured Text Essentials

    IEC 61131-3 and Structured Text Essentials

    In the previous article you learned how PLC hardware reads inputs and drives outputs, and why the scan cycle matters. This article connects that hardware reality to the software standard most PLC environments follow, and gives you the practical Structured Text (ST) basics you need to start writing correct, predictable PLC logic.

    What IEC 61131-3 is

    IEC 61131-3 is an international standard that defines common PLC programming concepts: languages, program structure, and key rules for how PLC software is organized.

    Why it matters for you:

  • It gives shared terminology across many PLC brands and IDEs.
  • It defines Structured Text (ST) and how ST code fits into the PLC execution model.
  • It helps you write portable, maintainable logic (even if details vary by vendor).
  • Reference:

  • IEC 61131-3
  • The IEC 61131-3 software model (how projects are structured)

    Most IEC-based PLC projects can be understood as a hierarchy.

    Key terms:

  • Configuration: the top-level setup that represents the whole control system (often one PLC).
  • Resource: an execution environment inside the PLC (often the CPU runtime).
  • Task: a scheduler that calls code at a defined time or event (for example every 10 ms).
  • POU (Program Organization Unit): the code building blocks you write and reuse.
  • !IEC 61131-3 project hierarchy: configuration, resource, tasks, and POUs

    How this connects to the scan cycle you already learned:

  • A task is what creates the repeating execution (the scan) for the code assigned to it.
  • Different tasks can run at different rates, which affects how fresh your input data is and how fast outputs react.
  • IEC 61131-3 languages and where Structured Text fits

    IEC 61131-3 defines several PLC programming languages. You may see these in the same project.

    | Language | What it looks like | Typical strengths | |---|---|---| | LD (Ladder Diagram) | relay-logic style rungs | discrete logic, troubleshooting on the shop floor | | FBD (Function Block Diagram) | blocks wired together | signal flow, analog processing, PID composition | | ST (Structured Text) | Pascal-like text code | calculations, arrays, state machines, reusable logic | | SFC (Sequential Function Chart) | steps and transitions | sequencing and procedural control |

    ST is especially valuable when your logic becomes more than simple ON/OFF conditions, but it still runs inside the same PLC scan/task model.

    POUs: Program vs Function vs Function Block

    A POU is a standardized unit of code. Understanding the differences is essential in ST.

    Program

    A Program is typically the main unit that a task calls.

  • Usually reads mapped inputs, updates internal logic, and writes outputs.
  • Often coordinates multiple function blocks.
  • Function

    A Function is like a math function in traditional programming.

  • It returns one value.
  • It should be stateless (no memory from one scan to the next).
  • Good for calculations and conversions.
  • Example (a simple clamp):

    Function Block

    A Function Block (FB) is like an object with memory.

  • It can store internal state between scans.
  • You create an instance of the FB, and each instance has its own memory.
  • Great for timers, counters, latches, motor starters, valve controllers, and reusable machine “components”.
  • Example (a simple latch FB):

    Using the FB (instantiation and call):

    What to remember:

  • A function returns one value and should not “remember”.
  • A function block can remember because its instance stores state.
  • Variables and data types you will use constantly

    ST is strongly typed: variables have declared types.

    Common IEC types:

  • BOOL: TRUE or FALSE (digital logic)
  • INT, DINT: signed integers (sizes vary; DINT is typically larger)
  • UINT, UDINT: unsigned integers
  • REAL: floating-point numbers (analog engineering values)
  • TIME: durations (often written like T#250ms, T#2s)
  • STRING: text (length rules vary by environment)
  • Two practical ideas:

  • Use BOOL for discrete I/O and interlocks.
  • Convert raw analog readings to REAL engineering units early, then use REAL in calculations.
  • Variable scope and persistence (why some values survive a power cycle)

    Where and how you declare a variable affects who can see it and whether it keeps its value.

    Typical scopes you will encounter:

  • Local variables: declared inside a POU and used only there.
  • Inputs and outputs of a POU: defined with VAR_INPUT and VAR_OUTPUT to make reusable components.
  • Global variables: shared across POUs (powerful, but easier to misuse).
  • Persistence concepts (names vary by vendor, but the idea is common):

  • Retained: value is kept through a normal power cycle.
  • Non-retained: value resets when power is removed.
  • Why it matters:

  • A production counter might need retention.
  • A momentary “Motor is running” command often should not be retained, to avoid unexpected startup after power returns.
  • Structured Text essentials (syntax you need to read and write real code)

    Assignments and expressions

  • Assignment uses :=.
  • Comparison uses =, <>, <, <=, >, >=.
  • Boolean logic commonly uses AND, OR, NOT.
  • Example:

    IF / ELSIF / ELSE

    Use IF when there are a few clear conditions.

    CASE

    Use CASE when exactly one of many branches should run (often for state machines).

    Loops (use carefully in PLCs)

    ST supports loops such as FOR, WHILE, and REPEAT.

    Important PLC reality:

  • PLC logic must finish within the task cycle time.
  • Long or unbounded loops can cause a watchdog fault or missed deadlines.
  • A safe pattern is a fixed-size loop over an array:

    How ST actually runs: tasks, scan timing, and predictable behavior

    ST code does not run “whenever an input changes”. In most PLCs:

  • Inputs are sampled.
  • Your task calls your program/POUs.
  • Outputs are updated.
  • This creates common timing effects:

  • If a pushbutton changes state just after input sampling, your code sees it on the next scan.
  • A pulse shorter than the task period can be missed.
  • Practical implications:

  • Choose task periods that match the speed of your process and sensors.
  • Use edge-detection or dedicated pulse-handling logic for brief signals.
  • Avoid writing the same output from multiple places; define one “owner” for each actuator command.
  • Coding habits that help from day one

  • Keep I/O mapping and control logic clearly separated (even if it is just different code sections).
  • Prefer small, reusable function blocks for device behavior (motor, valve, alarm).
  • Use clear names that reflect the real-world meaning (for example Conveyor1_RunCmd).
  • Document assumptions that matter to timing (task period, debounce, expected pulse width).
  • What you should be able to do after this article

  • Explain what IEC 61131-3 standardizes and why it matters
  • Name the IEC languages and justify when ST is a good choice
  • Distinguish Program, Function, and Function Block, including FB instance memory
  • Read and write basic ST with IF and CASE
  • Explain how tasks and scan timing affect what your ST code “sees” and when outputs update
  • 3. Data Types, Variables, and Program Organization

    Data Types, Variables, and Program Organization

    In the previous articles you learned how PLC hardware connects to sensors and actuators, and how IEC 61131-3 structures PLC software into tasks and POUs. This article focuses on the day-to-day building blocks of Structured Text (ST): data types, variables, and how to organize code so it stays readable, testable, and safe to change.

    Why types and organization matter in PLCs

    A PLC program is not just “code that works once”. It is logic that:

  • Runs repeatedly in a task (scan-like execution)
  • Interacts with real signals that can bounce, lag, and fail
  • Must be maintained under time pressure (commissioning, troubleshooting)
  • Strong typing and clear program organization help you:

  • Prevent wiring and logic mistakes (for example, mixing raw analog counts with engineering units)
  • Make intent obvious to someone reading the code later
  • Reduce subtle timing and state bugs caused by the cyclic execution model
  • Core IEC 61131-3 data types you will use constantly

    Different PLC vendors may add types, but these are widely supported.

    Boolean and discrete logic

  • BOOL: TRUE / FALSE
  • Use it for:

  • Digital inputs and outputs
  • Interlocks, permissives, alarms
  • State flags (for example IsRunning)
  • Integers (whole numbers)

    Common signed integer types:

  • SINT: small signed integer (typically 8-bit)
  • INT: signed integer (typically 16-bit)
  • DINT: signed integer (typically 32-bit)
  • LINT: signed integer (typically 64-bit)
  • Common unsigned integer types:

  • USINT, UINT, UDINT, ULINT
  • Use integers for:

  • Counts, indexes, IDs
  • Raw values from some I/O modules (vendor-dependent)
  • Practical rule:

  • Use DINT for counters and values that may exceed the range of INT.
  • Real numbers (engineering values)

  • REAL: floating-point (commonly 32-bit)
  • LREAL: higher precision floating-point (commonly 64-bit)
  • Use REAL/LREAL for:

  • Engineering units (bar, °C, %, rpm)
  • Calculations (scaling, control math)
  • Practical rule:

  • Convert to REAL engineering units early, and keep the rest of the control logic in engineering units.
  • Time and date/time

  • TIME: duration values like T#100ms, T#2s, T#5m
  • DATE, TIME_OF_DAY, DATE_AND_TIME: calendar-related types (support varies)
  • Use TIME for:

  • Debounce timers, delays, minimum run times
  • Scheduling logic inside the scan model
  • Strings

  • STRING: text
  • Use strings for:

  • Messages for HMIs (if your environment supports it)
  • Logging, alarm text references (often via IDs instead of full strings)
  • Useful composite types

    Composite types help you avoid dozens of loosely related variables.

  • ARRAY: an indexed collection of same-type elements
  • STRUCT: a “record” of different fields (like a small data object)
  • ENUM (vendor support varies, but common): named states instead of “magic numbers”
  • Example: using an enum for a small state machine makes CASE logic easier to read.

    Declaring variables in Structured Text

    Variables are declared in VAR...END_VAR sections. The section you choose expresses intent.

    The most common declaration blocks

  • VAR: internal variables
  • VAR_INPUT: inputs to a Function Block or Function
  • VAR_OUTPUT: outputs from a Function Block or Function
  • VAR_IN_OUT: passed by reference (use carefully)
  • VAR_TEMP: temporary variables (support and behavior vary by vendor)
  • VAR CONSTANT: constants (support varies)
  • Example: a Function Block skeleton with clear I/O.

    Key idea:

  • The FB instance stores latchedRun between scans, which is why FBs are perfect for “device behavior”.
  • Initialization, retention, and what survives a restart

    PLCs have different kinds of restarts (power cycle, warm restart, cold restart). Your variables can behave differently depending on whether they are configured as retained.

    General concepts you will see:

  • Non-retained: resets to default on restart
  • Retained: keeps its last value through a normal power cycle
  • Persistent: stored more permanently (naming and details vary)
  • What to retain (typical examples):

  • Total production counters
  • Calibration offsets
  • Recipe setpoints
  • What usually should not be retained:

  • Momentary commands (for example StartCmd)
  • Outputs that could cause unexpected motion after power returns
  • Because naming differs by vendor, always confirm retention behavior in your PLC documentation and project settings.

    Type conversions and avoiding “hidden” bugs

    ST is strongly typed, so you often must convert explicitly.

    Common sources of mistakes:

  • Mixing raw analog counts with engineering units
  • Comparing integers to reals without understanding conversion rules
  • Losing decimals by converting REAL to INT too early
  • Typical conversion functions (names can vary):

  • INT_TO_REAL, REAL_TO_INT
  • DINT_TO_REAL, REAL_TO_DINT
  • Example: keep calculations in REAL.

    Practical rule:

  • Convert once at the boundary (I/O layer), then keep the internal logic consistent.
  • Program organization: separating concerns so code stays maintainable

    In real projects, problems often come from where logic is placed and who “owns” an output, not from ST syntax.

    A maintainable structure usually separates:

  • I/O mapping and signal conditioning
  • Device-level control (motors, valves, alarms)
  • Sequence or state logic (machine steps)
  • HMI/SCADA interface (commands, status, setpoints)
  • !Layered program organization: IO mapping, device FBs, sequence logic, and HMI interface.

    A common POU pattern

  • Program (PRG): orchestration, calls FB instances
  • Function Blocks (FBs): reusable components with memory (device logic)
  • Functions (FUN): stateless calculations (scaling, clamps, conversions)
  • This matches what IEC 61131-3 defines for POUs. Reference: IEC 61131-3

    Example: Main program calling multiple components

    Two important organization rules:

  • One clear “owner” writes each physical output (here: DO_Motor is written in one place).
  • Device logic is encapsulated (the FB decides what RunCmd should be).
  • Scope: local vs global, and how to use globals safely

    Local variables

    Local variables live inside a POU instance.

  • They reduce accidental coupling
  • They make testing and reuse easier
  • Global variables

    Global variables are accessible from many POUs (typically declared in a global list).

    Benefits:

  • Good for shared status (for example, one place for all mapped I/O)
  • Useful for HMI tags and system-wide modes
  • Risks:

  • Hidden dependencies (any POU can change a value)
  • Multiple writers to the same signal
  • Practical rules for globals:

  • Use globals mainly for I/O images and high-level commands/modes
  • Avoid writing the same global from multiple POUs
  • Prefer passing values through FB inputs/outputs instead of reading globals everywhere
  • !Variable scope concept: globals for shared signals, locals inside programs/FBs, and per-instance FB memory.

    Naming and grouping: making variables readable under pressure

    A naming convention is not about style, it is about preventing mistakes.

    Good names usually include:

  • Equipment identifier: Conveyor1, Pump2
  • Signal meaning: RunCmd, Running, Fault, Permissive
  • Signal direction when helpful: Cmd vs Status
  • Examples:

  • Pump1_RunCmd (command to run)
  • Pump1_Running (feedback/status)
  • Tank_Level_PV (process value)
  • Tank_Level_SP (setpoint)
  • Grouping options:

  • Group related signals in a STRUCT (for example Pump1 : PumpIO;)
  • Group multiple similar devices in an ARRAY (for example 1..8 motors)
  • Arrays and structs: scaling from one device to many

    Arrays

    Use arrays when you have many similar items.

    PLC-safe loop rule:

  • Prefer fixed bounds (1 TO 8) so execution time is predictable.
  • Structs

    Use structs to keep a device’s signals together.

    This reduces scattered variables and helps code reviews.

    Putting it together: a simple folder and file strategy

    Most IDEs let you organize POUs and types into folders. A practical baseline:

  • Types: enums, structs, shared type definitions
  • Functions: stateless math and helper utilities
  • Function Blocks: device templates (motor, valve, alarm)
  • Programs: main orchestration, sequencing
  • Globals: I/O image, system modes, HMI interface tags
  • The goal is not perfection. The goal is that a new engineer can find:

  • Where an input is mapped
  • Where a device is controlled
  • Where an output is finally written
  • What you should be able to do after this article

  • Choose appropriate IEC data types for typical control problems
  • Declare variables with clear intent using VAR_INPUT, VAR_OUTPUT, and VAR
  • Explain the difference between local variables, global variables, and FB instance memory
  • Organize an ST project so I/O, device logic, and sequencing are clearly separated
  • Use arrays and structs to scale your code without losing readability
  • 4. Timers, Counters, and State-Based Logic in ST

    Timers, Counters, and State-Based Logic in ST

    In the previous articles you learned the PLC scan model, IEC 61131-3 program structure, and how to organize variables and POUs. Now we add the three tools that make most real machines work predictably:

  • Timers to create delays, pulse outputs, and minimum run times
  • Counters to count events like parts, cycles, and rejects
  • State-based logic (state machines) to build clear sequences instead of tangled IF conditions
  • These tools are especially important in Structured Text because ST makes it easy to express sequencing and conditions clearly, but you must always remember: your code runs repeatedly inside a task.

    Time and events in a scan-based PLC

    A PLC does not “wait” on a line of code. Instead, on every scan it:

  • Reads inputs
  • Executes your ST logic
  • Updates outputs
  • So when we say “delay 2 seconds”, what we really mean is:

  • Remember when an enabling condition became TRUE
  • Compare the elapsed time across multiple scans
  • Switch an output after the delay condition becomes satisfied
  • IEC 61131-3 standardizes timer and counter Function Blocks to do this reliably. Reference: IEC 61131-3

    IEC timer function blocks in practice

    Most IEC environments provide these common timer FBs:

    | Timer | Typical name | What it does | Common uses | |---|---|---|---| | On-delay | TON | Output turns ON after input has been ON for a set time | debounce, start delay, permissive delay | | Off-delay | TOF | Output stays ON for a set time after input turns OFF | run-on fan, delayed stop | | Pulse | TP | Output turns ON for a fixed pulse length when triggered | one-shot pulse to a valve or signal |

    The exact implementation details can vary slightly by vendor, but the concepts are stable across IEC systems.

    The key timer signals: IN, PT, Q, ET

    Most IEC timers have:

  • IN as a BOOL input that enables or triggers the timer
  • PT as the preset time (a TIME like T#2s)
  • Q as the timer’s BOOL output
  • ET as the elapsed time (a TIME value)
  • Practical meaning:

  • If IN stays TRUE long enough, the timer reaches PT
  • When it reaches PT, Q typically becomes TRUE
  • ET tells you how far along the timing is
  • !Timing behavior of a TON timer across multiple scans

    TON (On-delay) example

    Goal: start a motor only if a level switch has been TRUE continuously for 3 seconds.

    Important behavior:

  • If LevelOK drops FALSE before 3 seconds, the timer resets (typically ET returns toward T#0s and Q becomes FALSE)
  • The delay is evaluated scan-by-scan, not by blocking the program
  • TOF (Off-delay) example

    Goal: keep a fan running for 10 seconds after a heater turns off.

    Typical interpretation:

  • FanCmd turns ON quickly when HeaterOn is TRUE
  • When HeaterOn turns FALSE, FanCmd stays ON for PT
  • TP (Pulse) example

    Goal: generate a fixed 200 ms pulse when a part is detected.

    Practical warning:

  • Many TP timers expect a trigger edge behavior (often a rising edge). If you hold IN TRUE, the behavior can be vendor-specific. When in doubt, trigger TP with a one-scan pulse (using edge detection).
  • Edge detection: making “one event” from a continuous signal

    Timers and counters often need a one-time trigger, but sensors and buttons might stay TRUE for multiple scans.

    Two common edge types:

  • Rising edge: signal changes from FALSE to TRUE
  • Falling edge: signal changes from TRUE to FALSE
  • Many IEC environments provide standard FBs like R_TRIG and F_TRIG. If they exist, prefer them.

    Rising edge with R_TRIG (common pattern)

    Meaning:

  • StartPulse is TRUE for one scan when the button becomes pressed
  • Manual rising edge detection (when you don’t have R_TRIG)

    Rule:

  • Always update X_last after computing the edge in the same scan
  • IEC counters: counting events safely

    Counters in PLCs are typically Function Blocks that store internal state (the accumulated count) across scans.

    Common IEC counter FBs:

    | Counter | Typical name | What it does | |---|---|---| | Count up | CTU | increments when a count input event occurs | | Count down | CTD | decrements when a count input event occurs | | Up/down | CTUD | increments and decrements with separate events |

    Common counter signals (names may vary by vendor):

  • CU or CD: the count event input
  • RESET: resets count to 0
  • PV: preset value
  • Q: indicates “reached preset”
  • CV: current count value
  • CTU example with a rising edge

    Goal: count parts, one count per sensor detection, and raise BoxFull at 24 parts.

    Why the edge matters:

  • Without edge detection, holding the sensor TRUE for 10 scans could count 10 parts instead of 1
  • Reset strategy (a design choice)

    A counter reset should come from a clearly defined event, for example:

  • Operator acknowledges “new box”
  • Conveyor indexes to the next box position
  • Sequence transitions back to a “ready” state
  • Avoid “hidden” resets scattered across the program, because they make troubleshooting difficult.

    State-based logic: the clean way to build sequences

    A state machine models a sequence as:

  • A finite set of named states
  • Clear transitions between states based on conditions
  • Clear actions associated with each state
  • This is often called a finite-state machine. Reference: Finite-state machine

    Why state machines work well in PLCs:

  • They match the scan cycle (each scan evaluates the current state)
  • They prevent contradictory commands (because one state “owns” the behavior)
  • They are easier to test and extend than deeply nested IF logic
  • !Typical machine state flow and transition conditions

    Representing states: prefer an enum over magic numbers

    Using an enum improves readability and reduces errors.

    A practical state machine pattern in ST

    Key rules:

  • Use CASE on the current state
  • In each state, set outputs and evaluate transitions
  • Decide who “owns” each output (ideally the state machine or a device FB, not both)
  • Example: a simplified motor sequence with start delay and fault handling.

    What this example demonstrates:

  • The timer instance T_Start stores elapsed time across scans because it is an FB instance
  • The state machine ensures MotorCmd is never TRUE in Fault
  • Starting is a dedicated place to handle “start delay” logic cleanly
  • Combining timers, counters, and states without creating conflicts

    A strong, scalable structure is:

  • A device FB owns low-level behavior and interlocks (motor starter, valve control)
  • A sequence/state FB or program owns the high-level steps (Idle, Fill, Mix, Drain)
  • Timers and counters live inside the FB that “owns” the behavior they support
  • Typical ownership rules:

  • A timer that enforces “minimum motor run time” belongs with the motor logic FB
  • A counter that counts “parts in current box” belongs with the packaging sequence FB
  • A timer used only to delay a state transition belongs in the sequence/state machine
  • Common pitfalls and how to avoid them

  • Counting multiple times per event: always use edge detection for counter count inputs.
  • Unexpected timer resets: make sure you understand when IN becomes FALSE and who controls it.
  • Multiple writers to the same output: ensure one POU or one state machine is the final owner.
  • Assuming exact timing: timers are evaluated once per scan, so resolution and jitter are limited by the task period.
  • What you should be able to do after this article

  • Choose the right timer (TON, TOF, TP) for a delay, run-on, or pulse requirement
  • Use rising/falling edge detection so one physical event becomes one logical event
  • Use counters (CTU, CTD, CTUD) without double-counting
  • Build a maintainable state machine using an enum and CASE
  • Place timers and counters in the POU that “owns” the behavior to avoid conflicts
  • 5. Functions, Function Blocks, and Reusable Code Patterns

    Functions, Function Blocks, and Reusable Code Patterns

    Structured Text (ST) becomes truly powerful when you stop writing “one-off” logic in a single program and start building reusable building blocks.

    In previous articles you learned:

  • PLC scan and task execution (cyclic execution)
  • IEC 61131-3 structure (Programs, Functions, Function Blocks)
  • Data types, variables, and organization
  • Timers, counters, edge detection, and state machines
  • This article focuses on writing reusable code with Functions and Function Blocks (FBs), and on patterns that scale from one device to many without creating timing bugs or “multiple writers” conflicts.

    Functions vs Function Blocks in IEC 61131-3

    IEC 61131-3 defines POUs (Program Organization Units). Two POUs matter most for reuse:

  • Function: returns a single value; should be stateless.
  • Function Block: has internal memory; must be instantiated; ideal for behavior over time.
  • Reference: IEC 61131-3

    !Side-by-side concept diagram: stateless Function vs stateful Function Block

    When to choose a Function

    Use a Function when:

  • You want a calculation or conversion.
  • The result depends only on current inputs.
  • You want easy testing (given inputs, expected output).
  • Typical examples:

  • Clamp, scale, unit conversion
  • Selecting min/max
  • Building a derived value like Flow_kgph from Flow_m3ph and density
  • When to choose a Function Block

    Use an FB when:

  • The logic needs memory across scans.
  • You need timers/counters/edge detection inside the component.
  • You model a reusable “device” or “behavior”: motor starter, valve, alarm, debounce, sequencer.
  • Typical examples:

  • Start/stop latch
  • Debounce of a pushbutton
  • Minimum run time enforcement
  • “One command owner” motor or valve controller
  • Writing good interfaces: inputs, outputs, and internal state

    A reusable POU is mostly about its interface.

    Interface rules that keep projects maintainable

  • Make inputs represent commands and conditions (for example CmdStart, PermissiveOK).
  • Make outputs represent results (for example RunCmd, Faulted).
  • Keep internal state inside the FB (VAR), not in global variables.
  • Prefer a single, obvious priority order when commands conflict (for example EStop overrides everything).
  • Pattern: “Reset wins” (conflict resolution)

    For a latch or run request, define a clear priority. A common safe priority is:

  • Fault or emergency stop forces OFF
  • Stop forces OFF
  • Start forces ON
  • This prevents ambiguous behavior during commissioning.

    Practical Functions you will reuse constantly

    Example: clamp a REAL value

    A clamp is a classic Function: no memory, always returns one value.

    Typical uses:

  • Limiting an HMI setpoint to safe bounds
  • Limiting a calculated output before sending it to an analog output
  • Example: scale raw analog counts to engineering units

    This Function turns raw counts into a REAL engineering value. Keeping scaling in a Function helps you standardize behavior.

    Notes:

  • The local variable r exists only to compute the current return value.
  • The Function does not need memory across scans.
  • Function Blocks as “components with behavior”

    Example: debounce FB for a bouncing pushbutton

    A debounced signal is usually “true only if the input stayed true long enough”. That requires time memory, so an FB is appropriate.

    How to use it:

    Key idea:

  • DbStart remembers elapsed time because it contains a timer instance T.
  • Example: reusable Motor Control FB (single writer pattern)

    A common project failure mode is writing the same output (DO_Motor) from different places. A reusable motor FB helps by making a single “owner” of the motor command.

    What this demonstrates:

  • Internal memory (latchedRun) creates stable behavior across scans.
  • Timing behavior (T_MinRun) lives inside the device component, not scattered in a main program.
  • The FB becomes the single owner of the run command decision.
  • Composition: building bigger behavior from small reusable pieces

    A scalable PLC architecture often looks like this:

  • Functions: pure math and conversions
  • Device FBs: motor/valve/alarm components
  • Sequence/state machine: coordinates devices
  • Example: Main program that composes reusable pieces

    This is a concrete “separation of concerns”:

  • Input cleanup in DebounceOn
  • Device decision in MotorControl
  • Output assignment in one clear line
  • Reuse at scale: many instances and arrays

    One reason FBs are so useful is that you can create many instances, each with its own state.

    Pattern: identical devices, separate memory

    Rules to keep this safe in PLCs:

  • Use fixed loop bounds so execution time is predictable.
  • Keep each device decision inside its own FB instance.
  • Reusable code patterns you can apply immediately

    Pattern: edge handling stays near the thing that counts

    If a counter should count “one part per detection”, put edge detection either:

  • Inside the counting FB, or
  • Right next to the CTU call site
  • This avoids accidental double-counting when the same signal is reused.

    Pattern: default assignments, then state-specific overrides

    In scan-based logic, explicitly setting defaults each scan reduces “sticky” bugs.

  • Set safe defaults first (motor off)
  • Override in a CASE state (motor on only in Running)
  • This works especially well when the state machine owns the device command, or when it owns only commands and the device FB owns final interlocks.

    Pattern: keep “policy” separate from “mechanism”

  • Mechanism: a motor FB that enforces permissives, faults, minimum run time
  • Policy: a sequencer that decides when to request start/stop
  • This separation makes changes safer: you can modify the sequence without weakening motor safety behavior.

    Common mistakes and how to avoid them

  • Treating a Function like it has memory: if you need memory, use an FB instance.
  • Hiding state in globals: prefer FB internal variables so each device instance is independent.
  • Writing the same output from multiple POUs: decide who owns each output and keep one writer.
  • Duplicating timing logic everywhere: put timers inside the FB that owns the behavior.
  • What you should be able to do after this article

  • Choose correctly between a Function and an FB based on whether memory is needed
  • Design clean FB interfaces with clear priorities for conflicting commands
  • Compose small reusable units into a maintainable main program
  • Scale logic to many devices by using multiple FB instances (including arrays)
  • Apply “single writer” and “separation of concerns” patterns to avoid common PLC bugs
  • 6. Debugging, Simulation, and Testing PLC Programs

    Debugging, Simulation, and Testing PLC Programs

    Structured Text (ST) lets you express complex logic clearly, but PLC code still runs inside the scan/task model you learned earlier: inputs are sampled, code executes, outputs update. That execution model creates debugging pitfalls that look like “random” behavior if you approach PLCs like event-driven software.

    This article shows practical, IEC 61131-3-aligned techniques for:

  • Debugging ST logic online
  • Simulating I/O and processes safely
  • Testing Functions and Function Blocks (FBs) so changes don’t break machines
  • We will keep the ideas vendor-neutral, because every PLC IDE has different buttons, but the underlying methods are consistent.

    What makes PLC debugging different from typical software debugging

    Cyclic execution changes what “cause and effect” means

    In many PLCs, your code does not react instantly to an input change. Instead:

  • Inputs are sampled at the start of the task cycle
  • Your ST code runs using that sampled image
  • Outputs are updated after logic execution
  • So a signal that changes between scans is only visible on the next scan. This is why issues like missed pulses and double-counting happen.

    State is everywhere (often on purpose)

    PLCs rely heavily on memory across scans:

  • FB instances keep internal variables
  • Timers and counters store elapsed time and counts
  • Latches and state machines intentionally “remember”
  • Debugging often means figuring out who owns the state and when it changes.

    The plant is part of the program

    Your PLC program is connected to:

  • Real sensors that bounce, flicker, or fail
  • Actuators that have delays, inertia, and feedback
  • Safety systems that may remove power regardless of software
  • A correct program can still look wrong if the physical system is not behaving as assumed.

    !A mental model showing where timing and state issues usually originate.

    A practical debugging workflow for ST projects

    When something is wrong, you want a repeatable method that works under commissioning pressure.

    Start with boundaries: I/O mapping and signal conditioning

    Before blaming “logic”, verify what the program is actually seeing.

  • Confirm the raw input tag changes when the device changes
  • Confirm any inversion, scaling, or debouncing is correct
  • Confirm you are not reading the wrong channel or wrong global tag
  • A common organization that helps debugging (from earlier articles):

  • I/O image and conditioning in one place
  • Device FBs as single owners of device behavior
  • Sequence/state logic deciding what to request
  • Then check ownership: who writes the final command

    Many bugs are actually “multiple writers” problems:

  • Two POUs write the same output
  • A state machine sets a command, but a device FB overwrites it
  • A manual/HMI path and an auto path fight each other
  • Rule:

  • Each physical output should have one obvious final writer
  • Finally check time: edges, timers, and scan rate assumptions

    If the behavior is intermittent, suspect timing:

  • A pulse is shorter than the task period
  • A counter counts multiple scans because it lacks edge detection
  • A TON resets because IN drops briefly due to noise
  • Online debugging techniques (and what to be careful about)

    Most PLC IDEs support online monitoring features. Used well, they can shorten troubleshooting dramatically.

    Watch/monitor variables

    Watching variables helps answer:

  • Is the input really TRUE in the PLC?
  • Did the permissive drop for one scan?
  • Is the state machine in the state you think it is?
  • Good things to watch together:

  • Raw input, conditioned input, command, final output
  • State enum value (or state number) and transition conditions
  • Timer IN, Q, and ET
  • Counter CU, CV, and Q
  • Cross-reference and “who writes this?”

    If your IDE supports cross-reference, use it to locate:

  • All reads of a signal (who depends on it)
  • All writes to a signal (who controls it)
  • This is the fastest way to find multi-writer bugs.

    Breakpoints and single-cycle stepping (use carefully)

    Some PLCs allow breakpoints or stepping in ST. If you stop a task, outputs may freeze in an unsafe state.

    Safe guidance:

  • Prefer breakpoints in simulation or with outputs disabled
  • Avoid halting tasks on a running machine unless you have a safe plan
  • Forcing I/O (powerful and risky)

    A force overrides the real input or output value.

    Uses:

  • Simulate a sensor to prove logic
  • Hold an output OFF during commissioning
  • Risks:

  • You can defeat real-world conditions and create unsafe motion
  • You can “prove” logic that only works because the world is being overridden
  • Practical rules:

  • Use forces only with a clear procedure and permission
  • Label and document active forces
  • Remove forces before handing over a system
  • Traces, trends, and sequence-of-events

    When a problem lasts only one scan, watching live is not enough. Many systems provide:

  • Traces or sampled logging of variables
  • Trends for analog values
  • Event logs with timestamps
  • If available, trace these together:

  • State
  • Key permissives
  • Command and output
  • Timer ET or counter CV
  • This often reveals the single scan where a permissive flickered.

    Debugging timers, counters, and edge-related bugs

    Timers: confirm you are driving IN the way you think

    A TON measures continuous TRUE time on IN.

    Common mistakes:

  • IN is not stable because it comes from a bouncing input
  • IN is computed from logic that changes during the start-up sequence
  • A state machine turns IN off when leaving a state, resetting the timer earlier than expected
  • A debugging pattern is to watch IN, Q, and ET at the same time.

    Counters: count events, not levels

    Most counters must be driven by a one-scan pulse (event). Otherwise a single sensor that stays TRUE for 5 scans counts as 5 parts.

    Correct pattern:

  • Use R_TRIG (or equivalent) to generate a one-scan pulse
  • Drive CTU.CU with that pulse
  • Example:

    Debugging tip:

  • If CV increases “too fast”, check if CU is TRUE for multiple scans.
  • State machines: make state visible and transitions explicit

    If you use an enum state (recommended), debugging gets easier:

  • Watch State and the transition conditions
  • Ensure only one state sets the high-level command
  • A useful approach is to provide a status struct from your sequence FB:

  • State
  • LastTransitionReason (string or code)
  • StepTimerET
  • Even if you don’t keep this in final production code, it is valuable during commissioning.

    Simulation strategies: from simple to realistic

    Simulation means running control logic against a model instead of a real machine. In PLC work, simulation can be as simple as toggling bits, or as advanced as a dynamic process model.

    Software-only simulation (logic-level)

    Goal:

  • Prove ST logic, sequencing, and interlocks without hardware
  • Typical methods:

  • Replace mapped I/O with simulated variables
  • Use an HMI screen or test panel to toggle inputs
  • Create a simple process model in ST (for example, tank level increases when a valve is open)
  • A practical pattern is a simulation mode flag:

  • If simulation is enabled, inputs come from simulated variables
  • If not, inputs come from real I/O
  • Caution:

  • Keep simulation code clearly separated so it cannot accidentally be left enabled
  • Hardware-in-the-loop (HIL)

    Goal:

  • Run the real PLC against simulated sensors/actuators to test timing and integration
  • This is common when the real machine is not available or is expensive to risk. Reference: Hardware-in-the-loop simulation

    FAT and SAT mindset

    Two common industrial test stages:

  • Factory Acceptance Test (FAT): test the system before shipment or before installation
  • Site Acceptance Test (SAT): test the system in the real installation
  • Simulation often supports FAT, while SAT validates real-world wiring, noise, and process dynamics.

    Testing ST code: what to test and how to structure it

    Testing is simply making failures visible before production. Reference: Software testing

    What you can unit-test easily: Functions

    Functions are ideal for unit testing because they are stateless and return one value.

    Examples to test:

  • Clamp, scale, conversions
  • Alarm limit calculations
  • Selection logic (min/max)
  • Unit test concept reference: Unit testing

    A basic unit-test idea:

  • Provide known inputs
  • Check the returned value against expected output
  • What you test with sequences of scans: Function Blocks

    FBs have memory, so you test them as a timeline:

  • Apply inputs for N scans
  • Verify outputs and internal state after each phase
  • Typical FB tests:

  • Debounce FB: input flickers should not produce output
  • MotorControl FB: fault forces off; stop priority; minimum run time behavior
  • Counter wrapper FB: counts exactly once per sensor event
  • Test harness pattern (PLC-friendly)

    A test harness is a small program/POU that:

  • Instantiates the FB under test
  • n- Drives its inputs with scripted steps
  • Records results into variables you can watch online
  • Skeleton example:

    Even without a full automated framework, this gives you a controlled way to reproduce a bug.

    Design choices that make debugging and testing easier

    Build observability into your design

    Add variables that explain why something is off, not just that it is off.

    Examples:

  • PermissiveOK as a named BOOL, not an inline expression
  • Faulted and FaultSourceCode
  • AutoRequestRun and ManualRequestRun before they are combined
  • This aligns with the earlier course idea of separating:

  • Commands and permissives
  • Device behavior and sequencing policy
  • Prefer enums for states and codes

    Enums reduce “magic numbers” and make watch windows readable.

    Keep timing and state close to the owner

    From earlier articles:

  • Timers enforcing device behavior belong inside the device FB
  • Timers for sequence transitions belong in the sequence/state logic
  • This reduces hidden interactions and makes test harnesses simpler.

    Make safe defaults explicit every scan

    A reliable scan-based pattern:

  • Set safe defaults (outputs OFF)
  • Override in the correct state or when permissives are satisfied
  • This prevents “sticky” outputs caused by forgotten assignments.

    Common failure patterns and fast diagnostics

    | Symptom | Likely cause | Fastest check | |---|---|---| | Counter jumps by more than 1 per part | No edge detection | Watch CU over several scans | | Timer never finishes | IN not continuously TRUE | Watch IN and ET together | | Output flickers | Two writers or permissive flicker | Cross-reference output writes, trace permissive | | Sequence stuck in a state | Transition condition never TRUE | Watch state, transition BOOLs, and interlocks | | Works in simulation, fails on machine | Noise, wiring, bounce, real delays | Compare raw vs conditioned signals, add debounce, trend inputs |

    What you should be able to do after this article

  • Use online monitoring to trace a signal from raw input to final output
  • Identify and fix multi-writer issues by enforcing single ownership of outputs
  • Debug timer, counter, and edge problems by watching the right internal signals
  • Choose an appropriate simulation approach for your project risk level
  • Create a simple test harness to validate an ST Function or FB across multiple scans
  • 7. Real-World Applications: Interlocks, Alarms, and I/O Mapping

    Real-World Applications: Interlocks, Alarms, and I/O Mapping

    This course has already covered the PLC scan/task model, IEC 61131-3 program structure, core ST syntax, timers/counters, reusable Function Blocks (FBs), and practical debugging. This article ties those fundamentals to real commissioning work: making machines safe and diagnosable by designing clean I/O mapping, robust interlocks, and maintainable alarms.

    Why these three topics belong together

    In real projects, most “PLC problems” are not about syntax. They are about:

  • A wrong signal mapping (the program reads the wrong thing)
  • Missing or inconsistent interlocks (the machine runs when it shouldn’t)
  • Alarms that are noisy, unclear, or impossible to acknowledge
  • A good structure makes troubleshooting faster because you can trace:

  • Field signal (wire)
  • Raw PLC tag (I/O image)
  • Conditioned signal (debounce, scaling, inversion)
  • Control decision (interlocks, sequencing)
  • Command to actuator (single owner)
  • Alarm and diagnostic feedback (what happened and why)
  • !Layered signal flow showing where I/O mapping, interlocks, and alarms live

    I/O mapping in IEC 61131-3 projects

    What “I/O mapping” means

    I/O mapping is the practice of separating:

  • Hardware addresses and modules (vendor-specific)
  • Your project’s internal signal names (vendor-neutral and meaningful)
  • Even if your IDE can map a variable directly to an input address, it is usually cleaner to create a small I/O image layer.

    The three-layer signal model

    A practical, scalable model is:

  • Raw I/O: what the module reads/writes (often BOOL/INT)
  • Conditioned signals: cleaned/scaled/inverted signals used by logic
  • Commands/Outputs: final commands written by one “owner” point
  • #### Example naming pattern

  • Raw: DI_LevelLow_Raw, AI_Pressure_Raw
  • Conditioned: LevelLow, Pressure_bar
  • Command: Pump_RunCmd
  • Physical output: DO_Pump_Raw
  • This matches earlier course rules:

  • One clear writer for each physical output
  • Convert analog raw counts to engineering units early
  • Keep device behavior inside FBs where state/timers belong
  • Using STRUCTs to keep I/O readable

    STRUCTs help you avoid scattered tags and reduce wiring mistakes.

    How to think about these two structs:

  • PumpIO_Raw matches “what the PLC module provides” (often vendor-mapped)
  • PumpIO matches “what the control problem needs” (clean units and intent)
  • Signal conditioning: make inputs trustworthy before logic

    Signal conditioning is any transformation that makes the signal easier and safer to use.

    Common conditioning actions:

  • Debounce a pushbutton (prevents multiple edges)
  • Invert an input if wiring is “active low”
  • Scale analog raw counts into engineering units (REAL)
  • Add simple plausibility checks (for example, detect broken sensor)
  • Example: debouncing start/stop pushbuttons

    From earlier reusable FB patterns, a simple debouncer is typically a TON-based FB.

    Example: scaling an analog input

    If you already have a ScaleLinear function from earlier lessons, apply it in the conditioning layer.

    Interlocks: stopping unsafe or undesired actions

    What an interlock is (in PLC control)

    An interlock is a condition that must be TRUE to allow an action (like starting a motor), or a condition that forces an action OFF when it becomes unsafe.

    Two common categories:

  • Permissives: must be OK before an action is allowed (for example, level is not low)
  • Trips: conditions that force stop when violated (for example, overload fault)
  • Related concept: a fail-safe design prefers a known safe state when signals are missing or power is lost. See Fail-safe.

    Safety boundary reminder

    Emergency stop and personnel protection must be done with appropriate safety hardware (safety relay or safety PLC). Your standard PLC program:

  • Can monitor safety status (like EStopOK feedback)
  • Must not be the only layer preventing dangerous motion
  • This matches the earlier hardware safety guidance.

    Designing interlocks with clear ownership

    A maintainable approach is:

  • A device FB owns final permission checks and fault priority
  • A sequence or main program requests start/stop
  • This prevents “logic fighting logic”.

    Pattern: permissive aggregation with diagnostic bits

    Instead of one long expression like A AND B AND C, name each permissive:

  • Perm_LevelOK
  • Perm_EStopOK
  • Perm_NoHighLevel
  • Perm_AnalogOK
  • Then combine them:

    Benefit:

  • On the HMI or in online watch, you see which permissive blocked the start
  • Pattern: restart inhibit after a trip

    A common real-world requirement:

  • If a trip occurs, do not auto-restart immediately when the trip clears
  • Require an operator reset (or a defined sequence step)
  • This is a “latched trip” behavior, which needs memory, so it belongs in an FB.

    Alarms: making problems visible and actionable

    Alarm vs event vs fault (practical definitions)

    Different sites use different terminology, so define it in your project:

  • Alarm: a condition that requires attention (often shown on HMI)
  • Fault: an alarm that forces equipment off or into a safe state
  • Event: an informational record (start, stop, mode change) that may not require action
  • Related topic: Alarm management.

    Alarm lifecycle (what operators expect)

    A typical HMI alarm behavior includes:

  • Alarm becomes active when a condition is true
  • Alarm may latch so it remains visible until acknowledged
  • Acknowledgement is allowed only when the alarm is no longer active (policy varies)
  • !Alarm lifecycle showing active/acknowledged and latched visibility

    Avoiding “chattering” alarms

    A chattering alarm is one that turns on/off repeatedly due to noise, bounce, or a borderline analog value.

    Common fixes:

  • Debounce (time qualification) using TON (alarm becomes active only if condition stays true for PT)
  • Hysteresis for analog thresholds (requires two thresholds: on and off)
  • Better signal conditioning (filtering/scaling checks)
  • A reusable Alarm FB (latched + acknowledge)

    This FB implements a very common plant policy:

  • Alarm becomes active when Cond is TRUE
  • Alarm latches so it stays visible
  • Operator can clear the latched alarm with Ack only when Cond is FALSE
  • Design note:

  • Ack should usually be a one-scan pulse (from an HMI button edge), otherwise you might clear repeatedly.
  • Adding time qualification to an alarm

    If you want “alarm only if true for 2 seconds”, qualify Cond with a TON before passing it to AlarmLatched.

    Putting it together: a small, realistic pump example

    Requirements

    We will implement a simple pump control with:

  • Start/Stop pushbuttons
  • Low level switch (trip: stop pump)
  • High level switch (permissive: block start)
  • Pressure analog (alarm if pressure too high for more than 1 second)
  • E-stop feedback contact (permissive)
  • Alarm horn output when any alarm is unacknowledged
  • Main program structure

    This example follows the course architecture:

  • I/O conditioning
  • Interlocks/permissives
  • Device behavior (single writer)
  • Alarm generation
  • Final output mapping
  • What to notice:

  • The only writes to IO_Raw.DO_Pump and IO_Raw.DO_AlarmHorn happen at the end
  • Interlocks are separated into named permissives for easy troubleshooting
  • Alarm logic is explicit and reusable (FB-based)
  • Timing behavior (pressure qualification) is visible and testable
  • Commissioning checklist (practical)

    Use this list during simulation or site testing:

  • Verify raw inputs change correctly (IO_Raw.*)
  • Verify conditioning works (debounce and analog scaling)
  • Verify permissive bits reflect reality (watch Perm_*)
  • Verify the pump cannot start when Perm_OK is FALSE
  • Verify low level forces pump OFF immediately
  • Verify pressure alarm activates only after the qualification delay
  • Verify alarms latch and require acknowledgement according to your chosen policy
  • What you should be able to do after this article

  • Build an I/O mapping layer that separates raw I/O from conditioned signals and final commands
  • Implement permissives and trips with clear diagnostic bits
  • Create alarm behavior that is stable (no chatter), informative (latched/visible), and acknowledgeable
  • Preserve the “single writer” pattern so outputs are predictable and debuggable