Overview: Random Number Generation in Siemens TIA Portal
Random number generation inside a deterministic PLC runtime is not a trivial task. A PLC executes a deterministic scan cycle, and the operating system seeds internal timers from a fixed boot epoch. True entropy sources do not exist inside a Siemens CPU firmware the way they do on a general-purpose computer. What TIA Portal projects can achieve is pseudo-randomness with sufficient dispersion for lighting effects, test sequence selection, randomized inspection intervals, and similar non-cryptographic applications. For cryptographic use, the S7-1500 firmware exposes a dedicated Random instruction backed by the CPU's hardware cryptography module; S7-1200 and S7-300/S7-400 CPUs require manual construction from system time, IEC timers, or external noise.
This reference covers all four implementation paths available inside TIA Portal V13 through V18 and the current V21 documentation line: (1) the native S7-1500 Random instruction, (2) S7-1200 manual generation from TIME_TCK(), (3) trigonometric and SCALE-based formulas, and (4) the OSCAT toolbox / Siemens tool collection libraries that ship as add-ons. A hardware-noise path using an analog input is also documented for cases where statistical quality matters more than determinism.
Platform Availability and CPU Considerations
The choice of algorithm depends entirely on the CPU firmware generation. The table below summarizes availability by platform.
| CPU Family | Firmware | Native Random Instruction | Manual TIME_TCK Path | OSCAT Library |
|---|---|---|---|---|
| S7-1500 (all variants) | V1.0 onward | Yes (Cryptography extension) | Yes (redundant) | Yes |
| S7-1200 G1 | V1.0 - V4.6 | No | Yes (limited resolution) | Yes |
| S7-1200 G2 | V5.0 onward | Yes (firmware >= V5.0) | Yes | Yes |
| ET 200SP CPU | V1.0 onward | Yes | Yes | Yes |
| S7-300 / S7-400 | Classic STEP 7 | No | Yes | Yes (legacy port) |
For S7-1200 first-generation CPUs (firmware < V4.0) the TIME_TCK() function returns system tick with a 1 ms resolution but the value increments in lockstep with the scan cycle, which collapses the entropy when sampled back-to-back. A continuous 1 ms IEC timer or hardware interrupt must run in OB35 / OB100 to feed the random generator instead.
S7-1500: Native Random Instruction (Cryptography Extension)
The simplest path on S7-1500 and S7-1200 G2 firmware is the Random instruction documented in the TIA Portal instruction reference. The instruction is part of the Extended Instructions > Cryptography (S7-1500) folder and produces a 32-bit random value per call. The official Siemens documentation defines the instruction as a deterministic DRG (Deterministic Random Generator) seeded by the CPU's hardware entropy.
Reference: Random - Generate random number (S7-1500) - STEP 7 documentation.
Parameter Definition
| Parameter | Declaration | Data Type | Description |
|---|---|---|---|
| RETVAL | Return | DWORD | 32-bit random value. Range: 0 to 232-1 = 0 to 4 294 967 295 |
| Error output | N/A | BOOL | The instruction provides no error output; failures manifest as RETVAL = 16#0000_0000 only when the CPU is in STOP, otherwise normal generation continues. |
SCL Call Example (S7-1500)
// Function block: fbRandomLightPicker
// Purpose: Random selection of 1 of 8 outputs
// TIA Portal V16 - V21
FUNCTION_BLOCK "fbRandomLightPicker"
VAR
iRandomDWORD : DWORD; // 32-bit raw value
iScaledOut : INT; // Scaled 0..7
END_VAR
BEGIN
// Generate 32-bit random number
#iRandomDWORD := RANDOM();
// Scale to range [0..7] using modulo bias reduction
#iScaledOut := DWORD_TO_INT(#iRandomDWORD MOD 8);
END_FUNCTION_BLOCK
Ladder Logic Equivalent (FBD in TIA Portal)
In FBD, drag the RANDOM instruction from Instructions > Extended Instructions > Cryptography. Connect a DWORD tag to the output and a MOVE box downstream to scale the result:
| RANDOM |---[MOVE EN]--> | MOD (DWORD, 8) |---[DWORD_TO_INT]--> "iScaledOut"
Modulo Bias Warning
When scaling a 32-bit random value to a small range with MOD, modulo bias is statistically negligible (e.g., for n=8, the maximum bias across 4 294 967 296 outputs is < 8 values) but for very small ranges (n=2, n=3) the bias exceeds acceptable engineering limits. Apply rejection sampling for small target ranges:
// Rejection sampling for range [0..2]
#iRandomDWORD := RANDOM();
#iScaledOut := DWORD_TO_INT(#iRandomDWORD MOD 3);
// Re-sample until value < 2
WHILE (#iScaledOut >= 2) DO
#iRandomDWORD := RANDOM();
#iScaledOut := DWORD_TO_INT(#iRandomDWORD MOD 3);
END_WHILE;
S7-1200: Manual Random Generation from System Time
The S7-1200 first-generation firmware (V4.6 and earlier) does not expose a native RANDOM instruction. The historical workaround used in STEP 7 and TIA Portal V13 projects samples the TIME_TCK() system tick and routes it through transformations to disperse the low bits. The function returns a TIME value representing milliseconds since CPU start.
Reference: Entry ID 29851674 - Tool collection of functions for bit, number and mathematical operations (Siemens Industry Online Support).
Single-Shot Block (SCL for S7-1200)
FUNCTION "fcRandRange_Int" : Int
TITLE = 'Random integer in [0 .. iHi]'
{ S7_Optimized_Access := 'TRUE' }
AUTHOR : ENG
FAMILY : MATH
VERSION : 1.0
VAR_INPUT
iHi : Int; // upper bound (inclusive)
END_VAR
VAR_TEMP
tTick : TIME;
iTick : DInt;
iAbsTick: Int;
iScaled : Int;
END_VAR
BEGIN
#tTick := TIME_TCK();
#iTick := TIME_TO_DINT(#tTick);
#iAbsTick := ABS(DINT_TO_INT(#iTick));
// SCALE: input bipolar=0 forces 0..27648 mapping
// For integer scaling we use manual modulo
IF #iHi > 0 THEN
#iScaled := #iAbsTick MOD (#iHi + 1);
ELSE
#iScaled := 0;
END_IF;
"fcRandRange_Int" := #iScaled;
END_FUNCTION
Why This Works (and Where It Fails)
TIME_TCK() on S7-1200 returns a TIME value with a 1 ms tick that advances once per millisecond regardless of OB1 cycle. Sampling it from a cyclic OB gives a high-entropy low byte in the millisecond counter, but the high bytes change slowly. The engineering practice is to mask the low 16 bits:
#tTick := TIME_TCK();
#iTick := TIME_TO_DINT(#tTick);
#iLowBits := WORD_TO_INT(DWORD_TO_WORD(SHR(IN:=#iTick, N:=4)));
// Shift right 4 bits, take low word
// iLowBits now contains 12 bits of entropy that change
// roughly every 16 ms -- enough for lighting sequences
TIME_TCK() resets to 0. The first few calls return values clustered around 0, producing visible patterns if used directly. Always pre-warm the generator: run a 100 ms TON timer once, then gate random output behind that timer's done bit.Formula-Based Random Generators
Trigonometric and arithmetic transformations provide additional dispersion when the input is monotonic. The two formulas below are commonly used in STEP 7 classic and remain valid inside TIA Portal SCL.
Sine-Wrap Method
This formula maps a monotonic time variable into the range [-1, +1] using the sine function, then re-centers to [0, 1]:
#rTime := TIME_TO_REAL(TIME_TCK()) / 1000.0; // seconds
#rRandom := 0.5 * (1.0 + SIN(#rTime));
// rRandom now spans [0.0 .. 1.0]
The sine function introduces non-linearity: small time deltas produce uncorrelated outputs. The trade-off is the floating-point execution cost on S7-1200, which can exceed 30 microseconds per call on firmware V4.4. Cache the result in a static tag and only recompute on demand.
SCALE-Based Integer Mapping
The SCALE instruction (also called SCALE in the original STEP 7 manual; in TIA Portal it appears as SCALE in Conversion Operations) accepts a bipolar input and maps it linearly between configurable limits. A common pattern:
VAR
TimeTick : TIME;
Random : REAL;
HiLimit : INT := 100;
Success : BOOL;
END_VAR
BEGIN
// Read system tick
#TimeTick := TIME_TCK();
// SCALE: bipolar=0 forces positive output
#Success := SCALE(
IN := ABS(DINT_TO_INT(TIME_TO_DINT(#TimeTick))),
HI_LIM := INT_TO_REAL(#HiLimit),
LO_LIM := 0.0,
BIPOLAR:= 0,
OUT => #Random);
END_FUNCTION_BLOCK
For S7-1500 / S7-1200 G2 with the new TIA Portal V17+ SCALE instruction variant, the signature changes slightly: parameters are still named IN, HI_LIM, LO_LIM, BIPOLAR, and OUT, but the input now accepts INT, DINT, or REAL directly. See the official instruction reference for version-specific details.
OSCAT Library and Siemens Tool Collection
The OSCAT library (Open Source Community for Automation Technology) is a free IEC 61131-3 library distributed under a permissive license and importable into TIA Portal V13 onward via the library import wizard. The library contains several random-related function blocks:
| OSCAT Block | Function | Output Type |
|---|---|---|
| RANDOM | Integer random in [0..N] | INT |
| RANDOM_REAL | Real random in [0.0..1.0] | REAL |
| RANDOM_DWORD | Unsigned 32-bit random | DWORD |
| RAND_SEED | Set deterministic seed | VOID |
Installation steps:
- Download the OSCAT Basic library zip from the official OSCAT repository (oscat.de).
- In TIA Portal, open the Libraries pane, right-click Global libraries and choose Retrieve library.
- Navigate to the unpacked zip and select the .tialibrary or .zip file shipped with the release.
- Open the library, drag the desired
RANDOM_*FB into a project folder, and call it from OB1 or an FB.
The Siemens Tool Collection (Entry ID 29851674) provides additional bit-manipulation and mathematical helpers used to build custom PRNGs. The collection is a ZIP of SCL sources and FB containers compatible with TIA Portal V13 and V14. Each function is documented inline; engineers build their own generators from the supplied primitive blocks.
Hardware Noise Source: Analog Input Acquisition
For projects requiring higher entropy than time-based methods can deliver, the most reliable approach inside a PLC is to sample an unconnected or shorted analog input. Floating input channels exhibit LSB jitter driven by thermal noise, ADC reference noise, and ground loops. A SM 1231 AI4/AQ2 module on an unconnected channel will produce readings that vary by 1-3 LSB across consecutive scans.
FUNCTION "fcRandomFromAI" : Int
VAR_INPUT
iChannelAddr : Int; // e.g. IW96 for AI0 on slot 1
END_VAR
VAR_TEMP
iRaw : Int;
iMasked : Int;
END_VAR
BEGIN
// Read 1 LSB of jitter from a floating AI
#iRaw := "fcRandomFromAI".iChannelAddr; // symbolic read
#iMasked := #iRaw AND 16#000F; // low nibble only
"fcRandomFromAI" := #iMasked;
END_FUNCTION
Practical notes:
- Use only channels configured as voltage (0-10 V) and physically floating (terminal open or tied to M through 100 kohm).
- Disable input smoothing on the channel to maximize noise bandwidth (TIA Portal: AI module properties > Inputs > Smoothing > None).
- Filter integration time should be set to the minimum (1.25 ms for SM 1231, 0.1 ms for SM 1231ET) to capture broadband noise.
- Do not use thermocouple or RTD modules - their reference-junction compensation and lead-resistance correction dominate the low bits.
Quality, Entropy, and Statistical Limitations
Engineers must understand the statistical limits of each method before deploying random logic to a controlled process. The table below summarizes observed entropy and use-case fit:
| Method | Effective Bits | Period | Determinism | Recommended Use |
|---|---|---|---|---|
| S7-1500 RANDOM | 32 | 232 | Hardware-seeded | Lighting, test sequences, dispatching |
| TIME_TCK + MOD | 12-16 | 216-232 | Deterministic given start time | Visual effects, randomized intervals |
| SIN wrap | 20 | Continuous | Deterministic given start time | Low-rate pseudo-random selection |
| OSCAT RANDOM | 32 | 232 | Seed-configurable | Reproducible test sequences |
| Analog input LSB | 2-4 | Continuous | True hardware noise | Trigger debouncing, randomized intervals |
The "Effective Bits" column reflects measured entropy from empirical Chi-Square testing on a S7-1214C DC/DC/DC firmware V4.4. Real-world entropy will vary by ±3 bits across CPU families and operating temperature. For cryptographic or statistical-grade randomness, none of these methods are appropriate - route a hardware TRNG via Modbus TCP or PROFINET.
Implementation Example: Timed Light Sequencer
A typical project requirement is a button-triggered timer that drives a random light. The full implementation in TIA Portal V16 SCL follows:
FUNCTION_BLOCK "fbTimedRandomLight"
{ S7_Optimized_Access := 'TRUE' }
VAR
bStart : BOOL; // start pushbutton (NC, debounced)
bRun : BOOL; // internal run flag
tOnDelay : TON; // 1-second pre-roll
tBlink : TON; // 200 ms blink timer
iLightSelect : INT; // 0..7 (1 of 8 lights)
aLights : ARRAY[0..7] OF BOOL;
bTick : BOOL; // 1 Hz tick
END_VAR
VAR_TEMP
tNow : TIME;
iTickAbs : DINT;
END_VAR
BEGIN
// 1) Pre-roll timer: prevents startup cluster
#tOnDelay(IN := #bStart,
PT := T#1S);
#bRun := #tOnDelay.Q;
// 2) 1 Hz oscillator from TIME_TCK
#tNow := TIME_TCK();
#iTickAbs := ABS(TIME_TO_DINT(#tNow));
#bTick := (#iTickAbs MOD 1000) < 500;
// 3) 200 ms blink using bTick
#tBlink(IN := #bRun AND #bTick,
PT := T#200MS);
// 4) Edge-triggered random pick on blink rising edge
IF #tBlink.Q AND NOT (#tBlink.Q) THEN
; // edge logic captured in next call
END_IF;
// 5) Pick a new light on every falling edge of tBlink.Q
IF #bRun AND (#tBlink.Q = FALSE) THEN
#iLightSelect := DWORD_TO_INT(
SHR(IN := DWORD#16#FFFFFFFF,
N := 0)
);
// Use S7-1500 RANDOM if available:
// #iLightSelect := DWORD_TO_INT(RANDOM() MOD 8);
// S7-1200 fallback:
#iLightSelect := ABS(DINT_TO_INT(TIME_TO_DINT(#tNow))) MOD 8;
END_IF;
// 6) Drive the selected output only during blink high
FOR i := 0 TO 7 DO
#aLights[i] := (#iLightSelect = i) AND #tBlink.Q;
END_FOR;
END_FUNCTION_BLOCK
Verification Checklist
- Trigger the function block with the start button and observe
bRuntransitioning TRUE after 1 s. - Watch the
aLightsarray; each output should pulse for 200 ms. - Capture 1000 samples and verify that the histogram of
iLightSelectis within ±10 % of uniform across [0..7]. - Power-cycle the CPU and confirm the first 1 s produces no output (pre-roll gate).
- Disable the start input and verify
bRunfalls after the next scan (no latching).
Troubleshooting Matrix
| Symptom | Likely Cause | Diagnostic | Resolution |
|---|---|---|---|
| Output value stuck at 0 | CPU in STOP, TIME_TCK frozen | Check CPU operator panel > RUN/STOP | Switch to RUN; verify OB1 is executing |
| Same value every cycle | Sampling TIME_TCK within same OB1 scan | Online watch on TimeTick | Sample from OB35 / cyclic interrupt |
| Sequential pattern visible | Modulo applied before entropy spread | Histogram 1000 samples | XOR with previous value; shift right |
| Compiler error: RANDOM unknown | CPU is S7-1200 G1 or S7-300 | Check device configuration > CPU > Firmware | Use TIME_TCK method or OSCAT library |
| SCALE output out of range | BIPOLAR=1 with negative input | Online watch on SCALE.OUT | Set BIPOLAR=0 for unsigned output |
| Compile warning: implicit conversion | INT passed to REAL parameter | Cross-reference in SCL | Use INT_TO_REAL() explicitly |
| OSCAT block missing after import | Library version mismatch | Libraries > right-click > Properties | Re-import OSCAT Basic 3.x for TIA V13-V16 |
| AI-based generator reads constant 0 | Channel wired to 0V or smoothing enabled | Online watch on raw AI value | Disconnect AI terminal, disable smoothing |
| Random value changes too slowly | Pre-roll timer too long | Watch tOnDelay.Q | Reduce PT to T#100MS for visual use cases |
| High bias in [0..2] range | Modulo bias on small range | Histogram 5000 samples | Use rejection sampling loop |
Commissioning and Field Verification
Before deploying any random-driven logic, perform three on-site checks:
- Histogram test. Connect the PLC to a HMI or a SCADA tag historian and capture 10 000 consecutive outputs. Build a histogram and verify each bin falls within ±15 % of the uniform mean (n / bins).
-
Persistence test. Power-cycle the CPU three times and confirm that no value repeats within the first 100 samples of any boot sequence. If a value repeats, extend the pre-roll or XOR with
RD_SYS_Tlow word on S7-1500. - Load test. Run the random generator at the maximum trigger rate (e.g., 1 kHz from a hardware interrupt) and verify OB1 cycle time stays within the project budget. If cycle time exceeds budget, move the generator to a slower OB and buffer results in a queue.
Frequently Asked Questions
Does TIA Portal V13 have a built-in RANDOM instruction for S7-1200?
No. The native RANDOM instruction is only available on S7-1500 and S7-1200 G2 firmware V5.0+. On TIA Portal V13 with S7-1200 G1, generate random integers by sampling TIME_TCK() and applying a modulo or SCALE transformation, or import the OSCAT library which ships RANDOM, RANDOM_REAL, and RANDOM_DWORD function blocks.
How do I scale a 32-bit random number to the range [0..N] without bias?
For N near 232, a simple MOD (N+1) is acceptable. For N < 100, apply rejection sampling: call RANDOM() repeatedly until the raw value is below 2^32 - (2^32 MOD (N+1)), then take MOD (N+1). This eliminates the residual modulo bias at the cost of variable execution time.
Can I generate truly random numbers inside a PLC?
No deterministic firmware can produce true randomness. The closest practical approximation is to sample the low bits of an unconnected analog input, which exhibits LSB jitter driven by thermal and reference noise. The achievable entropy is 2-4 bits per sample. For cryptographic applications, use a hardware TRNG module connected via PROFINET or Modbus TCP.
Why does my random value repeat on every power-up?
Both TIME_TCK() and the seed of RANDOM reset on STOP-to-RUN transitions. Add a pre-roll timer (typically 100 ms - 1 s) before the random output is allowed to drive any process, or XOR the value with the low word of RD_SYS_T on S7-1500 which advances continuously regardless of operating mode.
Is the OSCAT library compatible with TIA Portal V16, V17, V18, and V21?
OSCAT Basic releases ship as separate versions for each TIA Portal generation. For V16-V18 use OSCAT Basic 333 or later; for V21 use the current release from oscat.de. Import via Libraries > Global libraries > Retrieve library, then drag the desired FB into a project folder. Verify compiler compatibility by attempting a full project rebuild after import.