Standard Function Blocks

IEC 61131-3 defines a comprehensive set of standard function blocks that provide essential timing, counting, and logic functions for industrial automation applications.

🚀 Enhance Your Development Experience

Get syntax highlighting, IntelliSense, and debugging support for Structured Text:

Install VS Code Extension →

Timer Function Blocks

Timer Function Blocks (TON, TOF, TP)

VAR
    OnDelayTimer : TON;     // Timer On Delay
    OffDelayTimer : TOF;    // Timer Off Delay  
    PulseTimer : TP;        // Timer Pulse
    
    StartSignal : BOOL := FALSE;
    StopSignal : BOOL := FALSE;
    TriggerPulse : BOOL := FALSE;
    
    MotorRunning : BOOL;
    AlarmActive : BOOL;
    PulseOutput : BOOL;
END_VAR

// TON - Timer On Delay
// Output goes TRUE after input has been TRUE for preset time
OnDelayTimer(
    IN := StartSignal,
    PT := T#5s
);
MotorRunning := OnDelayTimer.Q;

// TOF - Timer Off Delay  
// Output goes FALSE after input has been FALSE for preset time
OffDelayTimer(
    IN := NOT StopSignal,
    PT := T#3s
);
AlarmActive := OffDelayTimer.Q;

// TP - Timer Pulse
// Output pulse for preset duration when input goes TRUE
PulseTimer(
    IN := TriggerPulse,
    PT := T#500ms
);
PulseOutput := PulseTimer.Q;

TON - Timer On Delay

Members:

  • IN: Start input (BOOL)
  • PT: Preset time (TIME)
  • Q: Timer output (BOOL)
  • ET: Elapsed time (TIME)

Delays the TRUE signal by the preset time.

TOF - Timer Off Delay

Members:

  • IN: Input signal (BOOL)
  • PT: Preset time (TIME)
  • Q: Timer output (BOOL)
  • ET: Elapsed time (TIME)

Delays the FALSE signal by the preset time.

TP - Timer Pulse

Members:

  • IN: Trigger input (BOOL)
  • PT: Pulse duration (TIME)
  • Q: Pulse output (BOOL)
  • ET: Elapsed time (TIME)

Generates a pulse of fixed duration.

Counter Function Blocks

Counter Function Blocks (CTU, CTD, CTUD)

VAR
    UpCounter : CTU;        // Count Up
    DownCounter : CTD;      // Count Down
    UpDownCounter : CTUD;   // Count Up/Down
    
    CountPulse : BOOL := FALSE;
    ResetCounter : BOOL := FALSE;
    LoadCounter : BOOL := FALSE;
    CountDownPulse : BOOL := FALSE;
    
    PartCount : INT;
    RemainingParts : INT;
    TotalParts : INT;
    BatchComplete : BOOL;
    BatchEmpty : BOOL;
END_VAR

// CTU - Counter Up
UpCounter(
    CU := CountPulse,       // Count up on rising edge
    R := ResetCounter,      // Reset to 0
    PV := 100              // Preset value (limit)
);
PartCount := UpCounter.CV;        // Current value
BatchComplete := UpCounter.Q;     // TRUE when CV >= PV

// CTD - Counter Down  
DownCounter(
    CD := CountDownPulse,   // Count down on rising edge
    LD := LoadCounter,      // Load preset value
    PV := 50               // Preset value (start value)
);
RemainingParts := DownCounter.CV; // Current value
BatchEmpty := DownCounter.Q;      // TRUE when CV <= 0

// CTUD - Counter Up/Down
UpDownCounter(
    CU := CountPulse,       // Count up input
    CD := CountDownPulse,   // Count down input
    R := ResetCounter,      // Reset to 0
    LD := LoadCounter,      // Load preset value
    PV := 200              // Preset value
);
TotalParts := UpDownCounter.CV;   // Current value
// QU = TRUE when CV >= PV, QD = TRUE when CV <= 0

CTU - Count Up

Members:

  • CU: Count up input (BOOL)
  • R: Reset input (BOOL)
  • PV: Preset value (INT)
  • Q: Output (CV ≥ PV)
  • CV: Current value (INT)

CTD - Count Down

Members:

  • CD: Count down input (BOOL)
  • LD: Load input (BOOL)
  • PV: Preset value (INT)
  • Q: Output (CV ≤ 0)
  • CV: Current value (INT)

CTUD - Count Up/Down

Members:

  • CU: Count up input (BOOL)
  • CD: Count down input (BOOL)
  • R: Reset input (BOOL)
  • LD: Load input (BOOL)
  • PV: Preset value (INT)
  • QU: Up output (CV ≥ PV)
  • QD: Down output (CV ≤ 0)
  • CV: Current value (INT)

Edge Detection Function Blocks

Edge Detection Function Blocks (R_TRIG, F_TRIG)

VAR
    RisingEdge : R_TRIG;    // Rising edge detection
    FallingEdge : F_TRIG;   // Falling edge detection
    
    StartButton : BOOL := FALSE;
    StopButton : BOOL := FALSE;
    EmergencyStop : BOOL := TRUE;
    
    StartPulse : BOOL;
    StopPulse : BOOL;
    EmergencyPulse : BOOL;
    MotorRunning : BOOL := FALSE;
    
    // Edge trigger counters for diagnostics
    StartButtonPresses : INT := 0;
    EmergencyActivations : INT := 0;
END_VAR

// R_TRIG - Rising Edge Trigger
// Output pulse on FALSE to TRUE transition
RisingEdge(CLK := StartButton);
StartPulse := RisingEdge.Q;

// F_TRIG - Falling Edge Trigger  
// Output pulse on TRUE to FALSE transition
FallingEdge(CLK := EmergencyStop);
EmergencyPulse := FallingEdge.Q;

// Application logic using edge detection
IF StartPulse THEN
    MotorRunning := TRUE;
    StartButtonPresses := StartButtonPresses + 1;
END_IF;

IF StopButton OR EmergencyPulse THEN
    MotorRunning := FALSE;
    IF EmergencyPulse THEN
        EmergencyActivations := EmergencyActivations + 1;
    END_IF;
END_IF;

R_TRIG - Rising Edge

Members:

  • CLK: Input signal (BOOL)
  • Q: Edge output (BOOL)

Q is TRUE for one scan when CLK changes from FALSE to TRUE.

F_TRIG - Falling Edge

Members:

  • CLK: Input signal (BOOL)
  • Q: Edge output (BOOL)

Q is TRUE for one scan when CLK changes from TRUE to FALSE.

Bistable Function Blocks

Bistable Function Blocks (RS, SR)

VAR
    SetResetLatch : RS;     // Set dominant bistable
    ResetSetLatch : SR;     // Reset dominant bistable
    
    SetSignal : BOOL := FALSE;
    ResetSignal : BOOL := FALSE;
    
    MotorEnabled : BOOL;
    AlarmLatch : BOOL;
    SystemReady : BOOL;
    MaintenanceMode : BOOL;
END_VAR

// RS - Set Reset Bistable (Set dominant)
// If both S and R1 are TRUE, Q1 = TRUE (Set wins)
SetResetLatch(
    S := SetSignal,         // Set input
    R1 := ResetSignal      // Reset input
);
MotorEnabled := SetResetLatch.Q1;

// SR - Set Reset Bistable (Reset dominant)  
// If both S1 and R are TRUE, Q1 = FALSE (Reset wins)
ResetSetLatch(
    S1 := SetSignal,       // Set input
    R := ResetSignal       // Reset input
);
SystemReady := ResetSetLatch.Q1;

// Practical alarm latch example
VAR
    AlarmRS : RS;
    OverTemperature : BOOL;
    AckButton : BOOL;
    AlarmAcknowledged : BOOL;
END_VAR

AlarmRS(
    S := OverTemperature,   // Set on alarm condition
    R1 := AckButton        // Reset when acknowledged
);
AlarmLatch := AlarmRS.Q1;

// Combined logic
AlarmAcknowledged := AckButton AND AlarmLatch;

RS - Set Dominant

Members:

  • S: Set input (BOOL)
  • R1: Reset input (BOOL)
  • Q1: Output (BOOL)

When both S and R1 are TRUE, Q1 = TRUE (Set wins).

SR - Reset Dominant

Members:

  • S1: Set input (BOOL)
  • R: Reset input (BOOL)
  • Q1: Output (BOOL)

When both S1 and R are TRUE, Q1 = FALSE (Reset wins).

Practical Application Example

Complete Conveyor Control Example

PROGRAM ConveyorControl
VAR
    // Inputs
    StartButton : BOOL;
    StopButton : BOOL;
    EmergencyStop : BOOL;
    PartSensor : BOOL;
    PhotoEye : BOOL;
    
    // Standard function blocks
    StartButtonEdge : R_TRIG;
    StopButtonEdge : R_TRIG;
    EStopEdge : F_TRIG;
    PartCounterEdge : R_TRIG;
    
    StartupTimer : TON;
    RunTimer : TON;
    PartCounter : CTU;
    SystemLatch : SR;
    
    // Outputs
    ConveyorMotor : BOOL;
    StatusLight : BOOL;
    AlarmBuzzer : BOOL;
    
    // Variables
    SystemRunning : BOOL;
    PartCount : INT;
    OperationTime : TIME;
END_VAR

// Edge detection for buttons
StartButtonEdge(CLK := StartButton);
StopButtonEdge(CLK := StopButton);
EStopEdge(CLK := EmergencyStop);
PartCounterEdge(CLK := PartSensor);

// System control latch (Reset dominant for safety)
SystemLatch(
    S1 := StartButtonEdge.Q,
    R := StopButtonEdge.Q OR EStopEdge.Q
);
SystemRunning := SystemLatch.Q1;

// Startup delay
StartupTimer(
    IN := SystemRunning,
    PT := T#3s
);

// Run timer for operation tracking
RunTimer(
    IN := StartupTimer.Q,
    PT := T#999h  // Long time for continuous operation
);
OperationTime := RunTimer.ET;

// Part counting
PartCounter(
    CU := PartCounterEdge.Q,
    R := NOT SystemRunning,
    PV := 1000
);
PartCount := PartCounter.CV;

// Output control
ConveyorMotor := StartupTimer.Q AND NOT EmergencyStop;
StatusLight := SystemRunning;
AlarmBuzzer := EStopEdge.Q OR PartCounter.Q;

END_PROGRAM

🚀 Key Benefits of Standard Function Blocks

  • Standardization: Consistent behavior across different PLC platforms
  • Reliability: Well-tested implementations with predictable timing
  • Efficiency: Optimized performance for real-time control systems
  • Maintainability: Familiar interfaces for all automation engineers
  • Safety: Proven components for safety-critical applications

© 2025 ControlForge Systems