PLC Simulator
CODESYS Development System reference

CODESYS and IEC 61131-3 function block reference

IEC 61131-3 is the international standard that defines the programming languages and the standard blocks that most PLC platforms follow. CODESYS is the best-known development system built on it, and its runtime sits inside controllers from many manufacturers. Siemens TIA Portal and Studio 5000 Logix Designer both borrow from the standard too. Learn it once and the timers, counters and edge blocks look familiar on every platform.

This page explains nine IEC pieces in the standard's own terms: the data types, comparisons, the timer, counter and edge function blocks, and the rule that a function block instance keeps its own memory. Each has a short exercise that runs in this editor's IEC dialect.

What the browser editor does and does not simulate

The exercises run in our browser IEC dialect. It supports BOOL, INT, DINT, REAL and TIME declarations, assignments with AND, OR and NOT, the arithmetic and comparison functions as calls such as GT(a, b), and the TON, TOF, TP, CTU, CTD, CTUD, R_TRIG and F_TRIG blocks. It does not support infix arithmetic or comparison operators, and reading a block output such as T_PUMP.Q is written in ladder text, | T_PUMP.Q | := PUMP_RUN ;, not as an assignment.

The IEC task cycle and how CODESYS reports cycle time

An IEC runtime executes programs from tasks. A cyclic task runs on a fixed interval, a freewheeling task restarts as soon as it ends and an event task runs when a trigger occurs. Each cycle the runtime reads the mapped inputs, runs the programs assigned to the task from top to bottom, and writes the mapped outputs.

In CODESYS the task configuration sets the interval and priority of each task, and its monitor view shows the cycle count and the current, average, minimum and maximum cycle time. A cycle that takes longer than its interval is an overrun, and the watchdog on the task can stop the application if it happens too often.

Because the cycle time depends on the controller as well as the program, never assume a figure from another platform. Timer blocks use the real-time clock, so a TON of three seconds waits three seconds regardless of the cycle time, but the instant it expires is only noticed at the next call.

To estimate a scan time from your own program size, use the PLC scan time calculator.

CODESYS and IEC 61131-3 instructions explained

INT / DINT / REAL / TIME · 7 min · Free exercise

IEC data types: BOOL, INT, DINT, REAL and TIME

IEC elementary data types

Every variable has a type that decides what it can hold: a yes-or-no value, a whole number, a number with a fraction, or a length of time. Choosing the right type is the first decision in any IEC program.

What it does exactly

BOOL holds TRUE or FALSE. The whole-number types are SINT, INT, DINT and LINT, which are 8, 16, 32 and 64 bits and signed, with unsigned versions named USINT, UINT, UDINT and ULINT. REAL and LREAL hold floating-point numbers. TIME holds a duration, written with a literal such as T#3s or T#500ms.

Dividing two whole numbers gives a whole number: the fraction is dropped, not rounded. A reading of 253 tenths of a degree divided by 10 gives 25. To keep the fraction, convert to REAL first. Mixing types is normally done with an explicit conversion function, such as INT_TO_REAL.

The IEC and editor equivalent

These are the IEC types themselves. In this editor declare them in a VAR block, such as TEMP_C AT %QW0 : INT;, and use DIV(a, b) for division.

What the scan does with it

A variable keeps its value from one cycle to the next unless the program changes it, so a type that is too small for the value silently wraps or limits. The cycle does not check the range for you.

VAR
  TEMP_DECI AT %IW0 : INT;
  TEMP_C    AT %QW0 : INT;
END_VAR

TEMP_C := DIV(TEMP_DECI, 10);
Tenths of a degree to whole degrees with integer division.

Common mistakes

  • Expecting integer division to round. 9 divided by 10 as INTs is 0.
  • Storing a 32-bit value in a 16-bit variable and losing the high part.

What you can now do: You can pick a data type for a value and predict what integer division does to it.

GT / GE / LE · 7 min · Pro exercise

Comparison: GT, GE, EQ, LE, LT and NE

IEC comparison functions

Comparison functions turn a number into a yes-or-no answer, such as is the pressure at least 20? That answer can then be combined with other conditions.

What it does exactly

The IEC comparison functions are GT (greater than), GE (greater than or equal), EQ (equal), NE (not equal), LE (less than or equal) and LT (less than). Each takes two values of the same type and returns a BOOL. GT and LT are strict, while GE and LE are true at the limit itself.

A range check combines two comparisons with AND. For pressure between 20 and 80 inclusive that is GE(P, 20) AND LE(P, 80). Compare values of the same type, and avoid exact equality on REAL values because of rounding.

The IEC and editor equivalent

Real CODESYS code writes these as operators, such as P >= 20 AND P <= 80. This editor accepts the function form, ABOVE_MIN := GE(PRESSURE, 20);, and then combines the flags with AND.

What the scan does with it

The comparison is evaluated each cycle that the code runs, so the flag follows the value with at most a cycle of lag. Store the flag in a BOOL if more than one place needs the same answer in the same cycle.

ABOVE_MIN := GE(PRESSURE, 20);
BELOW_MAX := LE(PRESSURE, 80);

PRESSURE_OK := ABOVE_MIN AND BELOW_MAX;
Pressure in range using one flag per limit.

Common mistakes

  • Using GT at the limit and missing the exact limit value.
  • Chaining a comparison inside another comparison. Make one flag per comparison, then combine the flags.

What you can now do: You can write a range check from two comparisons and choose strict or inclusive limits.

TON · 8 min · Pro exercise

TON in CODESYS: IN, PT, Q and ET

On-delay timer

The on-delay timer makes an output wait. The input has to stay on for the whole preset time before the output switches on, and any drop in the input makes it start again.

What it does exactly

TON has the inputs IN (BOOL) and PT (TIME) and the outputs Q (BOOL) and ET (TIME). When IN goes true, ET starts counting up from zero. When ET reaches PT, Q turns on, and it stays on while IN stays true. If IN goes false at any time, ET goes back to zero and Q turns off.

A TON is a function block, so you declare an instance, such as T_PUMP : TON;, and call it with named inputs. The call stores ET and the previous state in that instance. The pump should be driven by T_PUMP.Q, not by the request bit.

The IEC and editor equivalent

This is the standard block itself: T_PUMP(IN := PUMP_REQ, PT := T#3s); then | T_PUMP.Q | := PUMP_RUN ;. The same call works in Siemens SCL and in this editor.

What the scan does with it

The timer must be called every cycle to track IN. The elapsed time comes from the system clock, so the delay is independent of the cycle time, though the output only changes when the call next runs.

T_PUMP(IN := PUMP_REQ, PT := T#3s);
| T_PUMP.Q | := PUMP_RUN ;
The pump starts three seconds after the request.

Common mistakes

  • Calling the timer inside an IF that is not true every cycle, which freezes it.
  • Using one TON instance for two separate delays.

What you can now do: You can delay an output with TON and name its inputs and outputs.

TOF · 8 min · Pro exercise

TOF in CODESYS: Q holds after IN falls

Off-delay timer

The off-delay timer keeps an output on for a while after its input has gone, so a fan or a lamp does not cut off the instant the motor stops.

What it does exactly

TOF has the same pins as TON. Q follows IN on the way up: when IN becomes true, Q becomes true immediately and ET is zero. When IN falls, ET starts counting, and Q stays true until ET reaches PT, when Q turns false. If IN goes true again during the count, ET resets and Q stays on.

The total time Q stays on after the input drops is PT, measured by the real-time clock. Use TOF when the thing to be delayed is the turn-off.

The IEC and editor equivalent

The call is T_FAN(IN := MOTOR, PT := T#4s); then | T_FAN.Q | := FAN ;. Siemens and Rockwell have the same behaviour under the same name.

What the scan does with it

On the cycle IN falls, Q is still true. It becomes false on the first call after the elapsed time reaches PT, so the run-on is PT plus up to one cycle.

T_FAN(IN := MOTOR, PT := T#4s);
| T_FAN.Q | := FAN ;
The fan runs on for four seconds after the motor stops.

Common mistakes

  • Expecting Q to go true late on the way up. A TOF reacts immediately on the way up.
  • Never calling the block while IN is false, so the delay never counts down.

What you can now do: You can build a run-on with TOF and say what Q does at each edge of IN.

TP · 8 min · Pro exercise

TP in CODESYS: a fixed-length pulse

Pulse timer

The pulse timer gives you a fixed-length pulse, no matter how short or long the trigger is. Press a button for a flicker or for a minute and the horn sounds for exactly the same time.

What it does exactly

TP has IN, PT, Q and ET. A rising edge on IN starts the pulse: Q goes true and ET counts up to PT. When ET reaches PT, Q goes false. While the pulse is running, further changes on IN are ignored, and a new pulse can only start after the previous one has ended and IN has fallen and risen again.

So the pulse length is set by PT alone. If IN is still high when the pulse ends, Q goes false and stays false until IN falls and rises again.

The IEC and editor equivalent

The call is T_HORN(IN := TRIGGER, PT := T#2s); then | T_HORN.Q | := HORN ;. TP is part of the standard block set on CODESYS, Siemens and others.

What the scan does with it

The pulse is measured by the real-time clock, so its length does not depend on the cycle time. The block must run every cycle to see the edge on IN.

T_HORN(IN := TRIGGER, PT := T#2s);
| T_HORN.Q | := HORN ;
A two-second horn pulse from any press.

Common mistakes

  • Using a TON when a fixed-length pulse is needed. The TON output only follows the input and does not stretch a short press.
  • Expecting a retrigger while the pulse is running. TP ignores IN until it ends.

What you can now do: You can produce a fixed-length pulse with TP and explain why it ignores IN while running.

R_TRIG / F_TRIG · 9 min · Pro exercise

R_TRIG and F_TRIG: edges, not levels

Edge detection blocks

An edge is the moment a signal changes. IEC gives you two small blocks that report it: one for a signal turning on and one for a signal turning off.

What it does exactly

R_TRIG has an input CLK and an output Q. Q is true for exactly one call when CLK goes from false to true, and false at all other times. F_TRIG is its mirror: Q is true for one call when CLK goes from true to false.

Each instance remembers the previous CLK value, so each edge you want to detect needs its own instance. Use F_TRIG to catch a machine stopping and R_TRIG to catch a button press, then latch or count the pulse.

The IEC and editor equivalent

These are the standard blocks: RUN_DROP(CLK := RUNNING); and the pulse is RUN_DROP.Q. They exist under the same names in Siemens SCL and in this editor.

What the scan does with it

The pulse lasts one cycle and is visible only to code that runs after the block call within that cycle. Place the call before the logic that uses its Q.

RUN_DROP(CLK := RUNNING);
| (RUN_DROP.Q OR STOPPED) AND NOT ACK | := STOPPED ;
Latch a stop event on the falling edge of RUNNING.

Common mistakes

  • Latching on the level NOT RUNNING, which is true at power-up before the machine ever ran.
  • Reusing one instance for two signals, so the stored previous value is wrong for both.

What you can now do: You can detect rising and falling edges with R_TRIG and F_TRIG and use the one-cycle pulse.

CTU · 8 min · Pro exercise

CTU in CODESYS: CU, RESET, PV, Q and CV

Count-up counter

A counter remembers how many times something has happened. The count-up counter adds one each time its input switches on and tells you when it reaches the target.

What it does exactly

CTU has the inputs CU, a reset input and PV, and the outputs Q and CV. Each rising edge on CU adds 1 to CV. Q is true while CV is greater than or equal to PV. The reset input sets CV back to zero. The standard text names the reset R, the CODESYS Standard library names it RESET, and this editor uses R.

CV keeps counting past PV unless you reset, and the counter is an instance with its own stored count. A held input adds only one, because the counter reacts to the edge rather than the level.

The IEC and editor equivalent

The call is PART_COUNT(CU := PART_SENSOR, R := RESET_PB, PV := 5); then | PART_COUNT.Q | := BATCH_FULL ;. CTD counts down and CTUD does both.

What the scan does with it

The block must be called every cycle, because it compares CU with the value it stored last call. Two pulses between two calls count as one.

PART_COUNT(CU := PART_SENSOR, R := RESET_PB, PV := 5);
| PART_COUNT.Q | := BATCH_FULL ;
Five parts fill the box.

Common mistakes

  • Never resetting the counter between batches.
  • Expecting CV to hold at PV. It keeps counting.

What you can now do: You can count edges to a preset with CTU and reset it between batches.

CTUD · 9 min · Pro exercise

CTUD: count up, count down, QU and QD

Up-down counter

Some things go up and down: cars into and out of a car park, items onto and off a conveyor. The up-down counter adds on one input and subtracts on another.

What it does exactly

CTUD has the inputs CU (count up), CD (count down), a reset, a load and PV, and the outputs QU, QD and CV. A rising edge on CU adds 1 to CV, and a rising edge on CD subtracts 1. QU is true while CV is greater than or equal to PV, and QD is true while CV is less than or equal to zero.

For a three-space car park with PV set to 3, QU is the full sign: it turns on at the third car and off again when one leaves. A reset sets CV to zero and a load sets CV to PV.

The IEC and editor equivalent

The call is SPACES(CU := CAR_IN, CD := CAR_OUT, PV := 3); then | SPACES.QU | := FULL ;. Siemens, Rockwell and CODESYS all have an up-down counter with the same idea.

What the scan does with it

An entry and an exit seen in the same cycle can cancel each other, depending on the implementation. Detect each on its own edge and call the block every cycle.

SPACES(CU := CAR_IN, CD := CAR_OUT, PV := 3);
| SPACES.QU | := FULL ;
A three-space car park.

Common mistakes

  • Using QD for the full sign. QD means empty.
  • Letting the count go below zero by missing an entry, which makes every later reading wrong.

What you can now do: You can track a quantity that rises and falls with CTUD and read its two outputs.

FUNCTION_BLOCK · 10 min · Pro exercise

Function block instances keep their own memory

Function blocks and instances

A function block is a small program with a memory. If two machines need the same behaviour, you do not copy the code. You make two instances, and each instance remembers its own state.

What it does exactly

IEC defines three kinds of program organisation unit. A PROGRAM runs from a task. A FUNCTION has inputs and one result and no memory, so calling it twice with the same inputs always gives the same result. A FUNCTION_BLOCK has stored variables, and each declared instance has its own copy of them.

The standard timers and counters are function blocks. An instance such as PARTS_A : CTU; has its own count, and PARTS_B : CTU; has a separate one. Calling one instance for two lines makes the lines share a single count, and each call disturbs the other.

The IEC and editor equivalent

This is the IEC rule itself. In this editor declare PARTS_A : CTU; and PARTS_B : CTU;, call each once with its own sensor, and read each one's Q.

What the scan does with it

An instance keeps its values from one cycle to the next, which is what lets a counter hold a count. A second call to the same instance in one cycle runs against the same stored values and overwrites them.

PARTS_A(CU := PART_A, PV := 3);
| PARTS_A.Q | := FULL_A ;

PARTS_B(CU := PART_B, PV := 3);
| PARTS_B.Q | := FULL_B ;
Each line counts its own parts.

Common mistakes

  • Sharing one instance between two machines to save declarations.
  • Putting stored state in a FUNCTION, whose locals do not survive the call.

What you can now do: You can tell a function from a function block and give each use of a block its own instance.

Frequently asked questions

Is CODESYS the same thing as IEC 61131-3?

No. IEC 61131-3 is the international standard that defines the languages and standard blocks. CODESYS is a development system and runtime that implements it, and many controller makers build on it. Siemens and Rockwell tools also follow the standard in places.

Why does a TON need an instance?

Because a timer has to remember how long it has been timing between calls. Each declared instance owns its own stored time and previous input state, so two delays need two instances. Calling one instance for two jobs makes them share one memory.

What are the pins of the standard counters?

CTU has CU, a reset, PV, Q and CV. CTD has CD, a load, PV, Q and CV. CTUD has CU, CD, a reset, a load and PV, with outputs QU, QD and CV. The reset input is named R in the standard text and RESET in the CODESYS Standard library.

Which IEC features does the browser editor support?

BOOL, INT, DINT, REAL and TIME variables, assignments with AND, OR and NOT, comparison and arithmetic written as calls such as GT(a, b), and the TON, TOF, TP, CTU, CTD, CTUD, R_TRIG and F_TRIG blocks. It does not support infix arithmetic or comparison operators.

Training material. Follow your site procedures, local electrical code and the manufacturer's instructions. Lockout/tagout and a qualified person are required for real equipment.