Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Functions

A FUNCTION is a stateless POU that accepts inputs, performs a computation, and returns a single value. Functions have no persistent state – local variables are initialized fresh on every call. This makes functions ideal for pure computations: conversions, math helpers, validation, and formatting.

Declaration

A function declaration specifies the function name and its return type after the colon:

FUNCTION FunctionName : ReturnType
  VAR_INPUT
    // input parameters
  END_VAR
  VAR
    // local variables
  END_VAR

  // body
END_FUNCTION

Return Value

The return value is assigned by writing to the function name itself:

FUNCTION CelsiusToFahrenheit : REAL
  VAR_INPUT
    celsius : REAL;
  END_VAR

  CelsiusToFahrenheit := celsius * 9.0 / 5.0 + 32.0;
END_FUNCTION

You may assign to the function name multiple times. The last assigned value before the function returns is the result:

FUNCTION Classify : INT
  VAR_INPUT
    value : REAL;
  END_VAR

  Classify := 0;  // default: nominal

  IF value > 100.0 THEN
    Classify := 2;  // high
  ELSIF value > 80.0 THEN
    Classify := 1;  // warning
  ELSIF value < 0.0 THEN
    Classify := -1; // underrange
  END_IF;
END_FUNCTION

Use RETURN to exit early after assigning the return value:

FUNCTION SafeSqrt : REAL
  VAR_INPUT
    x : REAL;
  END_VAR

  IF x < 0.0 THEN
    SafeSqrt := -1.0;
    RETURN;
  END_IF;

  SafeSqrt := SQRT(x);
END_FUNCTION

Calling with Named Arguments

Named (formal) argument syntax passes each parameter by name using :=:

PROGRAM Main
  VAR
    temp_f : REAL;
  END_VAR

  temp_f := CelsiusToFahrenheit(celsius := 100.0);
  // temp_f = 212.0
END_PROGRAM

Named arguments can appear in any order:

FUNCTION Clamp : REAL
  VAR_INPUT
    value : REAL;
    low   : REAL;
    high  : REAL;
  END_VAR

  IF value < low THEN
    Clamp := low;
  ELSIF value > high THEN
    Clamp := high;
  ELSE
    Clamp := value;
  END_IF;
END_FUNCTION

PROGRAM Main
  VAR
    result : REAL;
  END_VAR

  // Order does not matter with named arguments
  result := Clamp(high := 100.0, value := 150.0, low := 0.0);
  // result = 100.0
END_PROGRAM

Calling with Positional Arguments

Arguments can also be passed positionally, matching the declaration order of VAR_INPUT:

result := Clamp(150.0, 0.0, 100.0);
// value=150.0, low=0.0, high=100.0

Do not mix positional and named arguments in the same call. Use one style consistently.

Local Variables

Functions can declare local variables in a VAR block. These are initialized on every call and do not persist:

FUNCTION Average : REAL
  VAR_INPUT
    a, b, c : REAL;
  END_VAR
  VAR
    sum : REAL;
  END_VAR

  sum := a + b + c;
  Average := sum / 3.0;
END_FUNCTION

Functions Without Inputs

A function may have no inputs, though this is uncommon:

FUNCTION GetTimestamp : LINT
  GetTimestamp := ReadSystemClock();
END_FUNCTION

Recursive Functions

Functions may call themselves recursively, but be cautious of stack depth in resource-constrained PLC environments:

FUNCTION Factorial : LINT
  VAR_INPUT
    n : LINT;
  END_VAR

  IF n <= 1 THEN
    Factorial := 1;
  ELSE
    Factorial := n * Factorial(n := n - 1);
  END_IF;
END_FUNCTION

Practical Examples

Linear Interpolation

FUNCTION Lerp : REAL
  VAR_INPUT
    a : REAL;  // start value
    b : REAL;  // end value
    t : REAL;  // 0.0 to 1.0
  END_VAR

  Lerp := a + (b - a) * t;
END_FUNCTION

Scaling an Analog Input

A common PLC task is converting a raw ADC count to engineering units:

FUNCTION ScaleAnalog : REAL
  VAR_INPUT
    raw      : INT;    // 0..32767
    eng_low  : REAL;   // engineering low  (e.g., 0.0 PSI)
    eng_high : REAL;   // engineering high (e.g., 100.0 PSI)
  END_VAR
  VAR
    fraction : REAL;
  END_VAR

  fraction := INT_TO_REAL(raw) / 32767.0;
  ScaleAnalog := eng_low + fraction * (eng_high - eng_low);
END_FUNCTION

PROGRAM Main
  VAR
    raw_pressure : INT := 16384;
    pressure_psi : REAL;
  END_VAR

  pressure_psi := ScaleAnalog(
    raw := raw_pressure,
    eng_low := 0.0,
    eng_high := 100.0
  );
  // pressure_psi ~ 50.0
END_PROGRAM

Bitfield Check

FUNCTION IsBitSet : BOOL
  VAR_INPUT
    value : DWORD;
    bit   : INT;
  END_VAR

  IsBitSet := (value AND SHL(DWORD#1, bit)) <> 0;
END_FUNCTION

Restrictions

Standard IEC 61131-3 places the following restrictions on functions:

  • Functions must not instantiate function blocks.
  • Functions must not write to global variables.
  • Functions must not have side effects.

These restrictions ensure that a function’s output depends only on its inputs, making programs easier to reason about. This compiler may relax some of these constraints, but adhering to them is strongly recommended for portable, maintainable code.