This is particularly useful for initializing complex data structures, allocating memory with __NEW , or passing parameters to function blocks before they are used in the program.
If you are coming from the Allen-Bradley world, you are likely very comfortable with the (First Scan) bit. It’s a staple for initializing logic, resetting counters, or clearing buffers on startup.
| Platform | System Variable Availability | Behavior Notes | |---|---|---| | | SystemTaskInfoArr[1].firstCycle via TcBaseBCxx50.lbx | Requires library linking | | BX Series | SystemTaskInfoArr via TcBaseBX.lbx | Full structure support | | TwinCAT 2 (PC) | SystemTaskInfoArr via TcSystem.lib | Standard implementation | | TwinCAT 3 (PC) | SystemTaskInfoArr via TcSystem.lib | Same as TwinCAT 2, fully compatible | | CX Series | Same as PC platforms | Consistent behavior across all PC-based controllers |
Proper utilization of the first scan bit is a hallmark of clean, structured Beckhoff programming. Common use cases include:
A common point of confusion during commissioning revolves around what actually triggers a "first scan" in TwinCAT. _TaskInfo[x].FirstCycle Behavior Custom Software Flag Behavior (Switching Config -> Run) Triggers TRUE Triggers TRUE Cold Reset / PLC Download Triggers TRUE Triggers TRUE Stop & Start PLC Code (Red Square / Green Triangle in VS) Remains FALSE Triggers TRUE (Variables re-initialize) Online Change (Modifying code on the fly) Remains FALSE Remains FALSE (Memory is preserved) The Stop/Start Runtime Trap
| TwinCAT Version | Variable Name | Scope | |----------------|---------------|-------| | TwinCAT 2 | bInit | Global (in Standard.lib ) | | TwinCAT 3 | FirstScan | Per-POU (automatic) |
Commonly used to load recipes, initialize communication drivers, or reset state machines to their starting position upon a PLC cold or warm start. If you'd like, I can show you:
Without FirstScan , you face several classic initialization hazards:
This relies on the fact that standard, non-retained PLC variables always initialize to FALSE (or 0 ) upon a cold reset. Code Implementation (Structured Text)
// This runs once when the FB is created (first scan of the FB) METHOD FB_Init : BOOL VAR_INPUT bInitRetains : BOOL; // TRUE if retain variables are restored bInCopyCode : BOOL; // TRUE if FB is copied END_VAR fSpeed := 0.0; // Initialize internal variable bReady := FALSE; END_METHOD
Purging old data arrays, resetting FIFO (First-In, First-Out) pointers, and sending initial handshakes to Modbus, EtherCAT, or EtherNet/IP slaves.
To use it, you must retrieve the current task index and access the system info array: Function Block GETCURTASKINDEX to find which task is currently running. System Variable : Access the global array using that index. Example Implementation (Structured Text):
When you transition to Beckhoff TwinCAT, you won’t find a system bit named exactly "First Scan" in the global variable list. This often leads to the question: How do I run logic exactly once when the PLC starts?
While the core concept is universal, the naming and implementation of the first scan differ across platforms.
: This function block grabs the internal index of the task currently running the MAIN program.