Problem Statement: HMI-Driven Parameter Recalculation
On a Siemens S7-1200 PLC, an application reads machine parameters from an HMI tag (recipe setpoint, tolerance band, scaling factor). These parameters are static until the operator edits them. A derived result (converted engineering units, flow correction, position offset) is computed from the parameters and used downstream in the same OB1 cycle.
Two implementation strategies are common:
- Strategy A - Recalculate every cycle: Run the formula unconditionally in OB1, regardless of whether the input has changed.
- Strategy B - Compare-and-recalculate: Compare the current parameter value against a stored "last applied" value. Recalculate only when a mismatch is detected.
Intuition suggests Strategy B is faster because it skips the formula on cycles where the input is unchanged. Empirical measurement on a CPU 1214C FW 4.2 shows the opposite. This article documents the benchmark, explains the underlying cost, and gives a recommended implementation pattern.
Test Platform: S7-1200 CPU 1214C FW 4.2
Test hardware and firmware:
| Parameter | Value |
|---|---|
| CPU | 6ES7214-1AG40-0XB0 (CPU 1214C DC/DC/DC) |
| Firmware | V4.2 |
| Work memory | 100 KB load / 75 KB work |
| Bit memory / timers / counters | 8192 B / 512 / 512 |
| OB1 cycle, no test | 1 ms typical |
| Watchdog | Default raised to allow long test loops |
| Engineering | TIA Portal V15 or later |
| Online connection | Disconnected for tests 2 and 3 to isolate communication cost |
For a full hardware reference see the SIMATIC S7-1200 Programmable Controller System Manual and the S7-1200 Easy Book.
Measurement Procedure
The test FB runs both strategies inside a FOR loop that executes 100,000 iterations in a single OB1 scan. The shortest PLC cycle time over the loop is captured with the RUNTIME instruction. The watchdog was raised to avoid a STOP transition during the 100k iteration burst.
Three test cases were executed:
- Strategy A: Formula executed on every iteration.
- Strategy B, no change: Comparison path returns "equal" on every iteration; formula is skipped.
- Strategy B, with change: The stored "last value" is forced to a different value on every iteration so the comparison path returns "not equal" and the formula is executed.
Test Results
| Test # | Method | Min Cycle Time (ms) for 100k Iterations |
|---|---|---|
| 1 | Strategy A (recalculate every cycle) | 120 |
| 2 | Strategy B, no parameter change | 192 |
| 3 | Strategy B, parameter change forced | 212 |
Strategy A finished the 100,000-iteration loop in 120 ms. Strategy B without a change required 192 ms - 60% longer than Strategy A. Strategy B with a forced change required 212 ms - 77% longer than Strategy A.
Secondary Benchmarks (FOR loop baseline and additional test cases)
| Benchmark | Time (ms) | Notes |
|---|---|---|
| FOR loop only (no formula, no compare) | 588 | Baseline cost of the loop construct itself |
| Test 1 | 20,914 | First-run anomaly - one-time setup cost, excluded from comparison |
| Test 2 | 212 | Repeat of Strategy B, no change |
| Test 3 | 321 | Compare + formula + write back |
| Test 4 | 312 | Compare + formula + write back, alternate order |
| Test 5 | 521 | Two-variable compare + formula + write back |
Test 5 confirms the field caveat: comparing two inputs and then writing back is the most expensive variant at 521 ms, or roughly 4.3x the cost of Strategy A.
Analysis: Why Comparison Costs More Than Calculation
The result is counter-intuitive only until the instruction set is examined. On a S7-1200, the comparison path is not a single cheap instruction - it is a sequence of memory loads, equality tests, conditional jumps, and a write-back. Specifically:
- Load current tag value from the process image (or directly from the HMI-consumed tag).
- Load stored "last value" from a static / instance DB.
-
Equality test with
EQ_DIntorEQ_Realdepending on data type. - Conditional jump over the formula block (ladder: open contact, comparator, branch).
- On change: Run the formula and write the result and the new "last value" back to the DB.
By contrast, Strategy A is a straight-line sequence of arithmetic instructions with no branch, no extra load, and no write-back of state. The S7-1200 instruction list for y := a * b + c using MUL / ADD with implicit accumulator use is shorter than if last<>a then y := a*b+c; last := a; end_if.
Three concrete cost drivers:
-
Branch overhead: every
JNB/JCin STL, or every parallel branch in LAD/FBD, costs at least one or two extra micro-operations per scan relative to straight-line code. - DB read/write traffic: Strategy B reads two tags and writes one. Strategy A writes one result and reads one tag - the formula is inlined.
- Pipeline linearity: the S7-1200 user-code path is short and deterministic; introducing conditional execution breaks the linear instruction stream and forces the runtime to evaluate the branch predicate before the next block.
Communication Overhead
The S7-1200 online connection is asynchronous. HMI tag updates arrive in the OB1 cycle through the communication portion of the scan. The RUNTIME measurement was repeated with the engineering station disconnected to isolate the user-code cost from the comms cost. The relative ordering of the three strategies did not change, but the absolute times were lower without the online connection.
Recommended Pattern: Event-Driven HMI Update
Because Strategy A is the most efficient in user code, the cleanest pattern is to let the HMI explicitly signal a "save / apply" event. This shifts the conditional logic out of the PLC scan and into the HMI request, giving both readability and speed.
HMI side: expose three tags.
| HMI Tag | Direction | Purpose |
|---|---|---|
param_new |
HMI -> PLC | Staging area for the new value (only committed on Save) |
param_current |
PLC -> HMI | Echo of the currently applied value |
param_save_cmd |
HMI -> PLC | Boolean pulse set true on the operator's Save press |
PLC side: implement the commit in a single conditional block, with a one-shot edge detection to consume the pulse.
Structured Text (SCL) Implementation
// FB_ApplyParam
VAR
bSaveEdge : BOOL; // one-shot memory
bSavePrev : BOOL; // previous save state
rCurrent : REAL; // applied value
END_VAR
BEGIN
// Edge detect on the HMI save command
bSaveEdge := param_save_cmd AND NOT bSavePrev;
bSavePrev := param_save_cmd;
// Commit only on rising edge of the save pulse
IF bSaveEdge THEN
rCurrent := param_new;
END_IF;
// Recompute every cycle - Strategy A is faster than compare-and-skip
rResult := rCurrent * rScale + rOffset;
END_CODE
This pattern is the documented "save on event" approach for recipe and parameter handling on the S7-1200. See the recipe example in the S7-1200 System Manual, section on recipe and data record handling.
Ladder (LAD) Implementation
The same logic in ladder uses a positive edge contact (P) on the save tag and a single move (MOVE) into the applied value, followed by a math block computing the result.
| param_save_cmd P| --( MOVE )-- rCurrent <= param_new
| rCurrent | --[ MUL ]-- temp <= rCurrent * rScale
| rOffset | --[ ADD ]-- rResult <= temp + rOffset
Alternative: In-Cycle Recalculation with Math Instructions
If the HMI does not need an explicit "save" step, accept Strategy A unconditionally. The CPU cost is the lowest of the three options, and the code is also the simplest to read.
// OB1 or FC_Update - Strategy A
rResult := rParam * rScale + rOffset;
bLimitOK := (rResult >= rMin) AND (rResult <= rMax);
For multi-input formulas, the same principle holds: a straight-line expression is cheaper than a "did any of N inputs change" guard. If guard logic is required for auditability (a "stale" status bit, for example), build it as a side-effect of Strategy A, not as a gate that blocks Strategy A.
When to Choose a Compare-Based Approach
Despite the benchmark, there are valid cases for Strategy B:
- Audit and traceability: a regulated application may require a "parameter X changed at time T" log entry, in which case the change detector is a feature, not overhead.
- State-machine transitions: recalculate only when the machine enters a new state. Inside a state, the formula is evaluated at most once per transition, so the per-cycle cost is essentially zero. This is the event-driven-in-state-machines pattern.
- Heavyweight formulas: a single-cycle formula that takes >200 µs to execute (matrix math, polynomial fit, table lookup with interpolation) may justify a compare. Benchmark first; the threshold is platform-specific.
- Time-deterministic batching: when a downstream consumer needs the result to be stable across multiple OB1 cycles (a recipe read by a slow field device, for instance), a one-shot apply on change is the correct behavior.
Verification Procedure
To confirm the result on your own CPU and firmware, follow this sequence:
- Create an FB with three networks: Network 1 is the FOR loop counter, Network 2 is Strategy A, Network 3 is Strategy B (with a configurable "force change" boolean).
- Wrap the FOR loop in
RUNTIMEand store the result in a staticLREALarray indexed by the test number. - Raise the OB1 watchdog under PLC properties -> Cycle to avoid a STOP transition during the 100k-iteration burst.
- Download the project, put the CPU in RUN with no online connection from TIA Portal, and read the captured times from a watch table.
- Repeat the test with the engineering station online to see the comms delta.
Field-Proven Caveats
- Real-time priority: the S7-1200 runs OB1 to completion. Long FOR loops inside OB1 starve the communication slice. Never use a 100k-iteration benchmark loop in production code; it is for measurement only.
-
Data type width: mixing
REALandLREALin the same formula can introduce conversion overhead. UseLREALconsistently for engineering calculations to avoid the implicit conversion step. - HMI tag buffering: most HMI drivers on the S7-1200 update the process image at the configured acquisition rate, not on every OB1. A parameter change may not be visible in the very next cycle. Strategy A masks this issue; Strategy B exposes it as a "missed change" on a fast cyclic event.
- Multi-instance DBs: if the formula is inside an FB with multi-instance data, the read/write of "last value" is local to the instance. This is faster than a global DB but still slower than a straight-line formula.
- Compiler optimization: the SCL compiler folds constant sub-expressions. If the formula has any constant term, expect Strategy A to be even cheaper than a literal instruction count suggests.
Summary Matrix
| Strategy | Min Cycle (ms / 100k iter) | Relative Cost | Readability | Best Use |
|---|---|---|---|---|
| A: Recalculate every cycle | 120 | 1.0x | Highest | Default for derived values |
| B: Compare, no change | 192 | 1.6x | Medium | Audit / change log |
| B: Compare, change every iter | 212 | 1.77x | Medium | One-shot apply on save |
| B: Two-input compare + apply | 521 | 4.34x | Lowest | Avoid unless required |
FAQ
Is it always faster to recalculate every cycle on the S7-1200?
For simple arithmetic (one or two multiplies, one add), yes - the CPU 1214C FW 4.2 benchmark shows Strategy A at 120 ms vs. Strategy B at 192-212 ms for 100,000 iterations. For heavyweight math (table lookup, matrix, polynomial), benchmark both; the crossover depends on the cost of the formula relative to the compare-and-skip guard.
Why does a single comparison cost more than the formula it would skip?
Each comparison is a load + load + equality test + conditional jump + a possible write-back, while the formula is a straight-line sequence of arithmetic operations. The branch and the extra memory traffic dominate the cost of a small formula on the S7-1200.
Does the online TIA Portal connection change the result?
It raises absolute cycle time because the communication portion of the OB1 scan must service the engineering connection, but the relative ordering of the three strategies is unchanged. Measure both with and without the online connection to get a realistic range.
How should I handle recipe setpoints from the HMI?
Use the three-tag pattern: a staging tag, a current tag, and a save-command pulse. Edge-detect the save command in the PLC and apply the new value in a single conditional block. Run the derived formula in straight-line code every cycle.
Do I need to disable the PLC watchdog to run this benchmark?
Yes, raise the OB1 cycle watchdog in the CPU properties before running a 100,000-iteration test, otherwise the CPU will STOP on a timeout. Restore the application value before commissioning.