Siemens S5 Step 5 Subtraction Result Mismatch Troubleshooting

David Krause15 min read
PLC HardwareSiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Statement: Step 5 Subtraction Yields Two Different Values

A standard SUB (subtraction) network in a SIMATIC S5 FB33 produces a value in the programmer's status display that does not match the value seen downstream in PB65:

      L   FW 108        // Load Flag Word 108
      L   DW  35        // Load Data Word 35 from opened DB
      -F               // 16-bit integer subtraction, result in ACCU 1
      T   FW 106        // Transfer ACCU 1 to Flag Word 106
      JU  PB 65         // Unconditional jump to PB 65

While the program is in STOP with the cursor sitting on the T FW 106 line, the STEP 5 online status (PG or PG-Via-LAN) shows:

Operand Display Interpretation
FW 108 KF+20 Source A = +20
DW 35 KF+731 Source B = +731
FW 106 (status) KF+10 Displayed result = +10
FW 106 (in PB 65) KF-1 Observed downstream = -1

Arithmetic on the operands the operator is watching gives 20 − 731 = −711; +10 in the status window is therefore already wrong in absolute terms. The downstream reading of −1 is yet a third, inconsistent value. Both observations come from the same scan, and both can be correct under STEP 5 semantics once you understand what the PLC is actually doing with the operands.

STEP 5 Quick Reference for the Operands in Use

The mistake almost always arises from confusing symbolic names with physical addresses. The mnemonics used in the network above map onto specific memory areas of the S5 CPU:

Mnemonic Area Width Range (S5-115U example) Use
FW Flag / Merker 16 bits FW 0 ... FW 254 Bit-scratch and intermediate results, retained only for the current scan unless declared retentive
DW Data word in currently opened DB 16 bits DW 0 ... DW 255 per DB Process data associated with a DB
MW Not standard S5; some S5-155U H CPUs expose 16 bits CPU-specific Process image / extended flag
PB / FB / OB / SB Program / Function / Organization / Step blocks Code PB 0 ... PB 255, FB 0 ... FB 255, OB 1 ... Logic containers

Every DW operand is a data word inside whatever data block has been opened with A or AX just prior to the access. DW 35 is meaningless without that DB context; DW 35 in DB 4 is a different physical cell from DW 35 in DB 7.

The Arithmetic Operation `-F` in Detail

STEP 5 has three integer subtractions. Make sure you used the one that matches your data type:

Op Operands accepted in ACCU 1 / ACCU 2 Result type Range
-F 16-bit fixed point (KF / DH) 16-bit signed fixed point −32768 ... +32767
-G 32-bit fixed point (KG / DG) 32-bit signed fixed point −2147483648 ... +2147483647
-D BCD coded (real number as BCD) Real (32-bit) ≈ ±3.4·1038

The example uses -F, which on 20 − 731 must yield KF -711 (or overflow behaviour for the 16-bit wraparound). KF +10 in the status display is therefore either a sign/data-type misinterpretation in the display or, far more commonly, a sign that FW 108 or DW 35 you are inspecting is not the same physical cell the CPU actually used to execute the network.

16-bit signed wrap examples

  FW108 = +20, DW35 = +731    ->  20 - 731 = -711     (KF -711)
  FW108 = +20, DW35 = -731    ->  20 - (-731) = 751    (KF +751)
  FW108 = +20, DW35 = 0
  Acc2=+731  Acc1=+20  subtract = Acc2 - Acc1 = +711   (KF +711)

If you change DW 35 between the program doing the subtraction and you reading the status, the displayed operand value can be valid for the display but no longer relevant for the executed operation.

Why the Online Status Window Disagrees with PB 65

Three effects are layered on top of each other; any one of them is enough to produce a non-intuitive mismatch.

1. The STEP 5 status is only coherent at OB 1 boundaries

In cyclic OB 1 processing, the PG or STEP 5 > STATUS BLOCK view is refreshed at the end of the OB 1 pass, not continuously during execution. The values shown in the status variable list are the values present after the most recent OB 1 completion. If your subtraction network is inside FB 33 and FB 33 is called from multiple points in OB 1, the displayed FW 106 reflects the most recent write regardless of which call you are looking at.

In S5, the standard OB1 cycle runs in milliseconds. A status snapshot taken with the program in RUN reflects the state at the trailing edge of the previous OB 1 pass, not the current scan position.

2. `FW` is shared scratch memory - any block can write it

Flag words are not local. FW 106 can be written by FB 33, by an FB 12 instance that happens to use the same intermediate, or by a direct T FW 106 elsewhere in OB 1. The most common cause of the exact symptom shown here is that another network overwrites FW 106 after FB 33 writes it but before PB 65 reads it. If the unconditional jump follows that second write, PB 65 sees the second value, not the subtraction result.

3. DB context / opened DB may differ between sites

DW 35 refers to the offset 35 in the currently opened DB. If a block runs AX DB 9 somewhere between the subtraction and PB 65's read, the address DW 35 silently points to offset 35 of DB 9, not of DB 4. The status view (which is anchored in the DB that was active when the debugger opened) and the runtime read in PB 65 are then looking at two different physical cells.

Root Cause in the Original Case

Re-reading the operator's follow-up: "I just figured out that the reason for my problems is DW 109 and everything else is fine — merely I was looking for a value of 10 in PB 65 but realized where the issue is after checking values."

This is the canonical fingerprint of effect (2). A second write to the same flag word was happening, and DW 109 of some DB was being copied into FW 106 by a different network or function block. The status snapshot just before JU PB 65 showed the residual of the subtraction (KF +10 arithmetic noise / last-coincidence value), and at the entry of PB 65 the runtime was already showing the freshly written value the operator had been tracking (here, a flag driven by a different DW 109 source). The arithmetic in the original network was innocent.

Diagnostic Methodology

Follow this ladder; each step is non-destructive.

  1. Capture both windows simultaneously. Place the cursor in FB 33 on the line after T FW 106 and request status, then request status again from inside PB 65. If the values agree, the CPU is consistent and your mental model is wrong. If they disagree, the runtime between the two points of observation modified memory.
  2. Cross-reference writes to the operand. In STEP 5, search the entire project (FB, PB, OB, SB and the called function blocks) for every T FW 106. Use the cross-reference list CTRL+F5 > Cross Refs in classic STEP 5, or IST Editor > References. Any hit after FB 33 is a prime suspect.
  3. Inspect operand DW 35 at the same scan. Read DW 35 in DB 4 explicitly before and after the operation. If the value displayed in the operator's snapshot was being supplied by a different DB, the read in DB 4 will not match.
  4. Watch FW 108 at the entry of FB 33. If FW 108 is the result of a multiplication, a counter or a BCD conversion performed earlier in OB 1, its value at the point of subtraction will differ from its value at any pre-OB 1 snapshot. A stuck KF +20 in the live view is a hint that another path is overriding the counter before this network ever sees it.
  5. Disable subcalls. In RUN, set a single-shot breakpoint at the end of FB 33 by inserting a STP at that location briefly. Read FW 106 directly from PG. Now single-cycle to PB 65's input read. Compare.
  6. Use the runtime test mode. In the S5 tester, set RUN-T mode on PG so you can single-step. This eliminates the OB1-update assumption and any cross-task write.

Status Block vs. Status Variable: Two Different Tools

The STEP 5 programmer exposes two complementary views. Knowing which one to use is critical:

Tool What it shows When to use it
Status Variable (CTRL+F5) Coherent copy of selected operands at OB1 end-of-pass; refreshed cyclically Quick check during RUN; bias: lagged by one full cycle
Status Block (CTRL+F7) Block-internal accumulator, status word and operand values at the program line where the cursor sits Debug a single network live; you see what that specific network just did
Force / Set / Reset Variable Write to operand, never read Drive a value into a suspect input
IST / Cross Reference All references to an operand across the program Detect double-write before runtime ever runs

Use the Status Block, not Status Variable, while you sit on the line under suspicion. Status Variable gives the cycle-end view; Status Block gives the runtime view at your program line.

Step-by-Step Reproduction & Verification Procedure

  1. Open STEP 5 in offline or online mode targeting the CPU (e.g., S5-115U, AG 115, AG 135, AG 150).
  2. Load project and bring FB 33 plus PB 65 into working windows.
  3. Open DB 4 explicitly with A DB 4 in OB 1 prior to FB 33 if not already done.
  4. Set a breakpoint or cursor on the T FW 106 line in FB 33; press CTRL+F7 to enter Status Block.
  5. Trigger a single scan. From the PG, force RUN-T or set Status / Single Cycle; observe ACCU 2, ACCU 1, status word CC 1/CC 0/OV/OS.
  6. Verify CC bits: after -F the CC 1 / CC 0 pair must encode the signed comparison of the result. CC 1 = 1, CC 0 = 1 means result < 0.
  7. Single-cycle into PB 65 and read FW 106 again from the Status Variable list immediately afterward.
  8. Compare: if the Status Block and PB 65 entry agree, the subtraction is correct. The discrepancy then is purely a result of an intervening write to FW 106, a DB swap, or a conversion that PB 65 performs immediately on its input.

Common Pitfalls Specific to S5

Operand aliasing by symbolic names

STEP 5 supports symbolic names (Symbol Table, SYMBOL EDITOR). Two different symbols can resolve to the same absolute operand FW 106. Cross-references computed on a single symbol will not list the alias writes.

Indirect addressing and the offset confusion

L DW [FW200] reads DW where the index is in FW 200. If a probe sets FW 200 to a different value while you are looking at the screen, the runtime references jump to a different cell than your display does. Always check whether the operands in your suspicious network are absolute or indexed.

DB rights and the wrong DB

DW 35 in DB 4 may be read-only in that DB (e.g., a parameter DB). If you alter it from PG, the read-back shows new value but the runtime still sees the snapshot loaded for that OB pass.

Counter / timer PV versus CV

If FW 108 is the PV of a counter block and DW 35 is the CV, then reading either at the wrong instant of the count cycle will not give the post-subtraction number. JU PB 65 may then operate on values that are mid-update.

Process image vs extended I/O

The PII / PIQ tables are not interchangeable with flag memory. Treat anything wired through I, IB, QW, QD differently from FW when timing is in question.

Service / startup OBs

OB 21 / OB 22 (warm / cold restart) and OB 100 (in newer S5-155U H versions) can execute initialization code that touches flag memory and data blocks. A subtraction network that runs in the first cycle after STOP > RUN transition can produce a transient value that the steady-state OB 1 cycle never reproduces.

Verification Checklist After the Fix

Verification Tool Acceptance
FW 106 = expected subtraction result at the entry of PB 65 Status Block in PB 65 first network Value matches arithmetic on FW 108 - DW 35
No cross-write between FB 33 and PB 65 Cross Reference list on FW 106 Single write in FB 33 / absent elsewhere
Stable across 50 consecutive OB 1 cycles Status Variable, single-cycle to 50 No drift, no overflow, CC consistent
DB pointer unchanged Status word ANZ1 / ANZ0 in OB1 / FB 33 DB register matches between sites
Watchdog / SF LED CPU front panel No SF, no OB 26 stop fault during test

Field-Engineering Recommendations

  • Reserve flag ranges per scope. Adopt the convention FW 200 ... FW 254 for inter-block scratch, and never write to those flags inside application blocks. This makes any cross-write visible at commissioning time.
  • Pass intermediate results through their own DB. When an intermediate value must travel across an unconditional jump, store it in a dedicated DW in a private DB rather than into a flag. DW values then cannot be clobbered by FB instance code.
  • Avoid unconditional JU PB x chains in OB 1; prefer one SPB / SPA table per cycle. This forces a visible call order in the cross-reference and stops silent jumps to PB 65 from hiding writes.
  • Label subtraction operands on both sides. Use symbols on every operand so that double-name issues surface during symbol table cross-checks.
  • Run a self-test sequence in OB 100 / restart code that writes known constants to all flag and data areas the program uses, then asserts the expected subtraction results; an alarm on mismatch is a fast alarm on future regressions.
  • Where STEP 5 substitutes for STEP 7: remember that FC in STEP 7 retains a similar scratch-merker behaviour with the multi-instance DB, so the diagnostic philosophy carries forward, even though the syntax changes.

Edge Cases That Look Like a Subtraction Bug but Are Not

Conversion rounding

If FW 106 is a fixed-point result displayed as KF+10 while downstream is a counter that interprets it as BCD, that single bit difference 10010BCD vs 10hex is the entire apparent mismatch. Validate the downstream block's input declaration, not the subtraction.

Negative vs. sign-extension

FW 106 = KF -1 as a 16-bit signed word is hex 0xFFFF. If PB 65's input is a 32-bit accumulator and the load does sign-extension, you may be re-interpreting 0xFFFFFFFF as -1, where another site might mask to 0x00FF for BCD purposes.

Forced variable from PG

Forcing FW 106 from Force Variable overrides every program write of that cell. If an operator is forcing FW 106, the subtraction result will appear correct briefly after the T, then the forced value reasserts before PB 65 sees it. PG-side forced values are persistent across STOP > RUN until cleared.

Compatibility Notes (S5 family)

CPU family Typical use today Flag range DB range Notes
S5-90U / 95U Compact, OEM FW 0..127 typical, expand to 255 DB 1..31 (small) Limited DW per DB; double-check
S5-115U Plant floor, very common FW 0..254 (CPU-specific) DB 1..255, 256 DW per DB Most common platform for legacy STEP 5
S5-135U / 155U Process control FW 0..2047+ in 155U H DB 1..255 / 1..4095 Increased memory, more useful for indirect operands

Operator advice originally given was targeting a CPU compatible with DB 4 and flag memory in the FW 0..254 range, which fits comfortably in any of the above. If you are running S5-155U H with multi-instance flag extensions or with the CFs (communications processors), the cross-reference tool should be invoked with extra care; instance FBs reuse the same flag area by configuration.

Related Resources

  • Siemens SIMATIC S5 ST programmable controller catalog (system overview)
  • STEP 5 Basic Programming Manual (operations: L, T, A, AX, JU, JC, -F, -G, -D)
  • STEP 5 Reference Manual - Integer and floating-point arithmetic
  • S5-115U / 135U / 155U System Manual - CPU flags, DB layout, restart OB

Why does the status variable show KF+10 while the arithmetic 20 - 731 should yield -711?

The status variable view is a coherent snapshot taken at the end of OB 1, not at the moment of the subtraction. If any code path between the subtraction network and the next cycle termination has touched the accumulator or the carry bits, or has signed-extended from an earlier operation, the displayed KF value can lag or reflect a co-incidental value rather than the actual -F result. Always read the Status Block on the exact line of T FW 106 for the in-cycle truth.

How do I detect a double-write to FW 106 in STEP 5?

Use the cross-reference table (IST Editor > Cross References) on the absolute operand FW 106. The table will enumerate every T FW 106, every L FW 106, and every indirect reference. Any T to FW 106 outside the network you suspect is the culprit.

Is DW 35 always the same cell across the program?

Only within the data block that is currently open (A DB n or AX DB n). DW 35 in DB 4 and DW 35 in DB 7 are different cells. Before DW 35 is referenced, ensure the matching DB is opened, and check that no AX call swaps the DB register between the writer and the reader.

Should I prefer JU PB 65 over calling FB 65?

Unconditional jumps to PB blocks are legal but they bypass the parameter-passing interface and the local-merker scoping that FBs provide. They are usually a debugging convenience, not a production pattern. Convert PB callouts into JU FB 65 with parameter passing into a private DB once the logic stabilizes, and the double-write class of bug becomes much rarer.

What CC bits should I expect after -F with positive result, negative result, and zero?

Status bits CC 1 and CC 0 reflect the signed comparison of the result. For positive result (KF > 0): CC 1=0, CC 0=1. For negative result (KF < 0): CC 1=1, CC 0=0. For zero (KF = 0): CC 1=0, CC 0=0. For overflow on signed 16-bit (result outside -32768..+32767): CC 1=1, CC 0=1 and OV is set. If your observed status-word bits disagree with the math, you are looking at the wrong cycle end.

Back to blog