Edges and event counting in Structured Text

The Core Idea

Event counting distinguishes an input being on from an input becoming on. Comparing the present signal with its stored earlier state lets a program recognize an arrival rather than count every scan the signal stays true.

What you will learn

  • Understand the difference between a signal staying on and a new event.

  • Use an edge to count an event once, even when a sensor stays on.

  • See how Structured Text can detect an edge with memory or a standard function block.

Why it matters

One part can cover a sensor for many scans. Counting the event instead of its duration keeps the program's count aligned with the physical arrivals.

The problem

A conveyor photo-eye is TRUE while a part covers it. A wide part may hold the sensor TRUE for five scans, but the count must increase once, not five times. Reset must clear the count without turning a part already under the sensor into a new arrival.

SignalMeaning
PART_SENSORTRUE while a part covers the photo-eye.
RESET_PBTRUE while the count-reset button is held.
PART_COUNTParts counted since Reset.
COUNT_PULSETRUE for the single scan in which one part is counted.
SENSOR_WAS_ONThe sensor value saved from the preceding scan.
BATCH_FULLTRUE when the challenge count is three or more.

The lesson simulator scans every 100 ms. The program must count transitions, not milliseconds or scan numbers.

Predict

The first program has a common bug: it adds one on every scan where the sensor is TRUE. Start at zero, turn PART SENSOR on, and step five scans without turning it off. Predict what this program will report before revealing it.

Run the checks after the five steps. The failed held-sensor case describes the difference between what the program did and what the machine requires.

Try it

This version detects a rising edge correctly. Lock in the prediction above, then use PART SENSOR and Step one scan:

  1. Turn the sensor on and step once. COUNT_PULSE is TRUE and the count becomes one.

  2. Keep it on and step four more times. The pulse returns to FALSE and the count stays one.

  3. Turn it off and step once, then on and step once. The count becomes two.

  4. Hold the sensor on, turn RESET COUNT on for one scan, then release Reset and step again. The count stays zero until a fresh off/on event.

The maintained switches let you choose exactly which input level each scan sees. They are teaching controls, not a representation of a particular field device.

Look closer

The detector compares the input now with one bit saved from the previous scan:

COUNT_PULSE := PART_SENSOR AND NOT SENSOR_WAS_ON AND NOT RESET_PB;

PART_SENSOR says the sensor is TRUE now. NOT SENSOR_WAS_ON says it was FALSE one scan ago. Both can be TRUE together for only the first scan of an arrival. The count uses Reset priority, then the final assignment saves the present level for the next scan:

IF RESET_PB THEN
    PART_COUNT := 0;
ELSIF COUNT_PULSE THEN
    PART_COUNT := PART_COUNT + 1;
END_IF;

SENSOR_WAS_ON := PART_SENSOR;

Order matters. Saving SENSOR_WAS_ON before the comparison would erase the difference you are trying to detect. Saving it only when Reset is off would let a held part look new when Reset is released.

Completed scanSensor nowSaved value usedPulseCount
Before a partFALSEFALSEFALSE0
Part arrivesTRUEFALSETRUE1
Part remainsTRUETRUEFALSE1
Part clearsFALSETRUEFALSE1
Next part arrivesTRUEFALSETRUE2

IEC 61131-3 (the international standard for programmable controller languages) also defines the standard rising-edge block R_TRIG. The same idea can be written as:

PartEdge.Q is TRUE for one execution when CLK changes from FALSE to TRUE. Calling the block every scan is important because its instance must keep its own previous CLK state. The explicit-memory form above makes the scan behavior visible; R_TRIG packages that behavior for reuse.

Change it

An exit counter needs the opposite transition. Change the editable program so it counts when a part leaves the photo-eye: PART_SENSOR is FALSE now and SENSOR_WAS_ON was TRUE on the preceding scan.

Before running the checks, try this sequence:

  1. Turn the sensor on and step: the count stays zero.

  2. Keep it on and step again: still zero.

  3. Turn it off and step: the count becomes one for the falling edge.

  4. Repeat the on/off cycle for a second part, then verify Reset clears the count.

The checks judge the scan-by-scan behavior, so equivalent correct code can pass.

Check yourself

Repair the batch counter below. It must count each arrival once, turn BATCH_FULL on at three parts, keep it on for later parts, and let Reset empty the batch without recounting a held part.

Use the human-machine interface (HMI) and single-scan control first. Then run the visible and hidden checks. The hidden cases include Reset during a held third part, Reset in the same scan as an arrival, and a part already present on the first scan.

Passing the challenge records Structured Text completion for the shared edge-detection concept. The lesson's manual completion action remains available if you choose to move on without passing it.

What happened and why

A programmable logic controller (PLC) sees input levels on repeated scans. A physical arrival is an event, so the program needs state from an earlier scan to recognize when the level changed. Explicit memory (SENSOR_WAS_ON) and a standard R_TRIG instance solve the same problem: each retains one bit across scans and produces a one-scan result from a transition.

For a falling edge, reverse the comparison: FALSE now and TRUE before. For counters, alarms, and sequences, decide whether the requirement refers to a continuing condition or to the moment that condition changes. That decision determines whether you use the level directly or an edge pulse.

In an interview, explain the bug with a scan sequence: “The sensor stayed TRUE for five scans, so level logic incremented five times. I compared the current value with the previous scan, updated the saved value after the comparison, and gave Reset priority.” Then mention that production IEC code would commonly use R_TRIG or F_TRIG while preserving the same execution reasoning.

Common mistakes

  • Counting the level: IF PART_SENSOR THEN increments once per scan. Detect the transition instead.

  • Updating memory too early: assigning SENSOR_WAS_ON before comparing makes current and previous values identical.

  • Skipping memory during Reset: a held sensor may be counted when Reset is released. Update edge memory every scan.

  • Calling R_TRIG conditionally: the block misses changes while it is not called. Execute its instance every scan, then decide whether to use Q.

  • Using equality for a full batch: PART_COUNT = 3 turns false at four. Use PART_COUNT >= 3 when “full” should remain true.

Enable JavaScript to run the embedded simulator and complete the interactive exercises.