Skip to content

[Bug] All down-counters (CTD/CTUD + typed variants) count on FALLING edge of CD, violating IEC 61131-3 #217

Description

@chiouiss

Summary

In the standard function block library (libs/sources/iec-standard-fb/counter.st, current main; also shipped with OpenPLC Editor 4.2.11 under resources/strucpp/libs/sources/), every down-counting input CD is edge-detected with F_TRIG (falling edge), while every up-counting input CU correctly uses R_TRIG (rising edge) — 10 occurrences of CD_T : F_TRIG on main as of 2026-08-23.

IEC 61131-3 defines both CU and CD as rising-edge-sensitive inputs. As implemented, a down-count is registered one pulse later than expected — when the input pulse ends rather than when it begins.

Affected blocks (10 total)

All down-counters in counter.st share the pattern:

  • CTD, CTD_DINT, CTD_LINT, CTD_UDINT, CTD_ULINT
  • CTUD, CTUD_DINT, CTUD_LINT, CTUD_UDINT, CTUD_ULINT

All CTU* blocks are correct (R_TRIG).

Evidence (source excerpts)

CTUD — note the asymmetry between CU and CD:

VAR
    CU_T : R_TRIG;   (* up-count: rising edge - IEC-compliant *)
    CD_T : F_TRIG;   (* down-count: FALLING edge - non-compliant *)
END_VAR
CU_T(CLK := CU);
CD_T(CLK := CD);

CTD — same pattern:

VAR
    CD_T : F_TRIG;
END_VAR
CD_T(CLK := CD);
IF LD THEN
    CV := PV;
ELSIF CD_T.Q AND (CV > 0) THEN
    CV := CV - 1;
END_IF;

Steps to reproduce

Target: OpenPLC Simulator (Editor 4.2.11), cyclic task T#20ms, Structured Text.

PROGRAM repro
  VAR
    cnt : CTUD;
    pulse : BOOL;
  END_VAR
cnt(CU := FALSE, CD := pulse, R := FALSE, LD := FALSE, PV := 10);
END_PROGRAM
  1. Preload CV to a non-zero value (count up twice via CU, or use CTD + LD).
  2. Force pulse from FALSE to TRUE. Expected (IEC): CV decrements on this scan. Actual: CV unchanged.
  3. Force pulse back to FALSE. Actual: CV decrements now — i.e. on the falling edge.

The asymmetry is directly observable with CTUD: wire the same pulse pattern to CU and CD alternately; up-counts land on pulse start, down-counts land on pulse end.

Expected behavior

Per IEC 61131-3 (standard counter FBs), CD shall be sampled on its rising edge, symmetric with CU.

Suggested fix

Replace F_TRIG with R_TRIG for every CD_T declaration in counter.st (10 occurrences). No interface change; only the edge timing of down-counts is corrected.

Note: this changes observable timing for any user program that (knowingly or not) relies on the current falling-edge behavior, so it may warrant a release-note entry.

Environment

  • OpenPLC Editor 4.2.11 (Windows x64, installer OpenPLC.Editor_4.2.11.exe)
  • Library file: libs/sources/iec-standard-fb/counter.st (verified identical behavior in the bundled copy and current main)
  • Reproduced on the built-in OpenPLC Simulator target

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions