1. Problem Summary
A field-proven fault on the Siemens S7-1200 CPU 1214C (DC/DC/DC and AC/DC/RLY variants both affected): a coil-flag in the Merker (M) area drives a physical output, but the flag refuses to return to logic 0 even when the visible rung logic clearly resets it. The engineer inspects the single network where the bit is set (--[ ]--( S )) and sees the SET input is FALSE, then inspects the RESET network and sees the --[ ]--( R ) input is TRUE. The bit should be low. It is not. The output it drives latches ON, often causing a machine stop, a valve held energized, or a permissive that prevents the line from re-starting.
Classic symptom pattern:
- Bit is set in one and only one network (cross-search confirms this).
- Bit is reset in one and only one network.
- Bit is also used as a coil in one and only one additional network.
- SET condition is FALSE, RESET condition is TRUE at the moment of observation, yet the bit reads
1in the standard tag table or in a watch table. - Forcing the bit off in the watch table works, but the next scan it returns to
1.
The user-visible workaround — relocating the flag to an adjacent bit (for example, moving from M69.2 to M69.3) — restores correct behavior, which is the most important diagnostic clue. The bit itself is healthy; something else is writing the word that contains the bit.
2. Affected Hardware, Firmware, and Software
| Component | Detail |
|---|---|
| CPU | SIMATIC S7-1200 CPU 1214C, all order numbers (6ES7214-1AG40-0XB0, 6ES7214-1BG40-0XB0, 6ES7214-1HG40-0XB0, 6ES7214-1AE30-0XB0, etc.) |
| Firmware | Observed on V4.2 through V4.6; behavior is independent of firmware revision because the cause is logical, not firmware-bug |
| Engineering | STEP 7 Basic (TIA Portal) V13 SP1 through V18 |
| Memory area | Bit memory (M) — %M0.0 through %M1023.7 on 1214C |
| Triggers | Any Mx.y bit that shares a byte with a word, double-word, or symbol-named block used elsewhere in the program, DB, or HMI tag list |
Reference: SIMATIC S7-1200 Programmable Controller System Manual (entry ID 109814663).
3. Root Cause — M-Area Memory Overlap
The S7-1200 M-area is a flat byte array. The CPU does not enforce a "type" on an M-address; the same byte can be addressed as a boolean (%M69.2), a byte (%MB69), a word (%MW69), or a double word (%MD69). Any write to the wider type overwrites every bit in the same physical byte, word, or double word — including the bit you believe is independent.
For a bit at M69.2, the overlapping references are:
| Address | Symbolic name example | Data type | Bytes touched | Contains M69.2? |
|---|---|---|---|---|
| %M69.2 | Flag_Bit | BOOL | 1 bit of byte 69 | Yes |
| %MB69 | Byte_69 | BYTE / SINT / USINT / CHAR | 1 byte | Yes (all 8 bits) |
| %MW68 | Word_68 | WORD / INT / UINT | 2 bytes (68–69) | Yes (upper byte of the word) |
| %MW69 | Word_69 | WORD / INT / UINT | 2 bytes (69–70) | Yes (lower byte of the word) |
| %MD66 | DWord_66 | DWORD / DINT / UDINT / REAL | 4 bytes (66–69) | Yes (MSB byte) |
| %MD67 | DWord_67 | DWORD / DINT / UDINT / REAL | 4 bytes (67–70) | Yes |
| %MD68 | DWord_68 | DWORD / DINT / UDINT / REAL | 4 bytes (68–71) | Yes |
| %MD69 | DWord_69 | DWORD / DINT / UDINT / REAL | 4 bytes (69–72) | Yes |
| %MD70 | DWord_70 | DWORD / DINT / UDINT / REAL | 4 bytes (70–73) | No |
| Sliced access | %MW68.%X2 | BOOL on a word-tag | Same as %M69.2 | Yes |
If any one of these overlapping symbols is written by an FB, FC, OB, HMI tag, motion control technology object, recipe function, or PID compact block, it can flip the bit back to 1 in the same scan cycle that your reset logic ran.
4. Secondary Cause — System Memory and Clock Memory Bits
The S7-1200 exposes two system-controlled bit ranges that are enabled in the CPU device configuration and that re-write on every scan:
-
System memory bytes (configurable start):
%MB0–%MBnby default contains first-cycle, diagnostic, and run-state flags. If you setSystem Memory Byteto100in the device properties, bytes%MB100–%MB105are reserved. A bit inside that range will be driven by the firmware. -
Clock memory byte (configurable): a single byte at a user-chosen address whose bits toggle at fixed frequencies (10 Hz, 5 Hz, 2.5 Hz, 2 Hz, 1 Hz, 0.5 Hz, 0.625 Hz, 0.5 Hz). If the clock byte is configured at
MB69, thenM69.0–M69.7are NOT free bits — they are the eight clock pulses.
Check both in Device configuration → Properties → System and clock memory. See the S7-1200 System Manual, section on system and clock memory bits.
M69.2 is not merely "a bit that toggles". It is a bit that the firmware will write to 0 or 1 every 200 ms (5 Hz) — at the same priority class as your OB1 logic. A user-reset followed by a 5 Hz clock-set in the next scan creates the exact symptom described in this article.5. Third Cause — Set/Reset "Last Call Wins" Scan Order
SR and RS flip-flops, like the ladder --[ ]--( S ) and --[ ]--( R ) coils, are not edge-triggered in STEP 7. They are evaluated every scan, and the order in which they are encountered inside OB1 (or inside the FBs/FCs that the cyclic OB calls) decides the result:
- If network 7 sets
M69.2and network 23 resetsM69.2, network 23 wins (last write wins, and OB1 ends with the value just written). - If a higher-priority OB (e.g. OB35 cyclic interrupt at 100 ms) also touches
M69.2via a word or DWord move, the OB1 reset can be overwritten on the next interrupt boundary. - If an FB's
STATorTEMPvariable is inadvertently pointing to%MW68or%MD69(a common mistake when symbol-table defaults are not pruned), that FB's:=assignment clobbers the bit at the end of the FB's execution.
This is the most common cause of "the bit goes high after a reset, and the same bit goes low after a set" — the order of the SET and RESET in OB1 was wrong, or an interrupting OB is writing the same memory.
6. Diagnostic Procedure (Field-Proven)
Run the following seven steps before declaring a CPU replacement.
Step 1 — Online cross-reference, then binary search
In TIA Portal: right-click the tag → Go to → Cross-references. Confirm only three references (set, reset, coil). If you see more than three, the overlap is local — jump to Step 4.
Step 2 — Watch the word and the byte, not the bit
Open a Watch table with the following four rows and force cyclic monitoring at 500 ms:
WatchRow | Address | Display format
1 | %M69.2 | BOOL
2 | %MB69 | BIN+ (B#16#)
3 | %MW68 | BIN+ (W#16#)
4 | %MD66 | BIN+ (DW#16#)
Watch what else changes in MB69/MW68/MD66 at the exact moment M69.2 flips back to 1. The non-M69.2 bits that change are the smoking gun: they reveal which code path is writing the wider reference.
Step 3 — Disable user code in half-blocks
Use the Call environment view (TIA Portal → Project tree → PLC → Call environment). Starting with the largest FB (often a machine sequencer), temporarily skip the call by routing it through a --[ FALSE ]-- CALCULATE gate. Re-test the bit. If M69.2 now resets correctly, the disabled block contains the offending write.
Step 4 — Search the entire project for byte/word/dword collisions
Use Search in project → "68" "69"* and filter to M-area addresses. The collision often hides behind a symbolic name. Example: a programmer's DB has "MachineState" : WORD; at offset that maps to %MW68 because the DB was assigned to the M-area for a technology object.
Step 5 — Check HMI tag list
WinCC Comfort/Advanced on a 1214C often polls the M-area cyclically. An HMI tag with Acquisition mode = Cyclic continuous at %MW68 will NOT write the bit, but a tag at %MD66 with Update value on operator input will. Inspect HMI tags → Connection → Address.
Step 6 — Check PID_Compact, Motion Control, and recipe blocks
Each of the following technology objects reserves a block of M-area for instance DB by default. If the start address was left at 0, they can land anywhere.
-
PID_Compactbackground DB -
TO_Axis_PTO/TO_PositioningAxistechnology DBs -
RecipeGet / RecipePuttemporary buffers
Step 7 — Use a diagnostic helper bit
Add a single dedicated diagnostic tag in a reserved, un-overlapped region (recommend %M2000.0 as a project convention). Copy the SET/RESET logic to the new bit in parallel. If the new bit also fails, the problem is in the driving logic. If the new bit works and the old bit fails, the problem is M-area overlap at the original address.
| a_flag_old a_flag_new
|------|------(S) ------(S)
| |
| b_reset b_reset
|------|------(R) ------(R)
Wire the diagnostic bit to a non-essential lamp on the HMI. Several plants keep a small "diagnostic mirror" panel reserved for these probes; the cost is two M-bits and one HMI tag, the benefit is minutes-versus-hours fault-finding.
7. Resolution and Workarounds
| Root cause confirmed | Permanent fix | Quick mitigation |
|---|---|---|
| Word/DWord overlap from a sequencer FB | Rename the FB's STAT variable to a private DB; remove the M-area alias | Move the bit to M69.3 (current article's reported fix); re-test before commit |
| System memory byte reservation overlaps the user bit | Change System memory byte in CPU properties to a non-conflicting address (e.g. 1000) | Move the user bit out of MB0–MB105 |
| Clock memory byte overlaps the user bit | Change Clock memory byte to a non-conflicting address (e.g. MB2000) and document | Move the user bit out of the clock byte's range |
| Last-call-wins in OB1 ordering | Reorder the SET and RESET networks so RESET is encountered last in the scan | Wrap both into a single SR flip-flop block in an FB called from a single location |
| Higher-priority OB clobbering the bit | Move the bit into a DB static variable; never let cyclic OBs write to the M-area | Disable the interrupting OB temporarily with --[ g_bypass_ob35 ]-- SRT_DINT on the OB call |
| Symbolic tag in HMI is a wide type pointing at the M-byte | Switch the HMI tag to a BOOL and use the bit address directly | Change HMI tag update mode to "On demand" |
Reference: SIMATIC S7-1200 Automation System Function Manual (entry ID 109751799), section "Bit memory (M) area" and "System memory and clock memory bits".
8. Verification Procedure
After the fix, prove the change with all of the following:
-
Watch-table trace: monitor
%M69.2,%MB69,%MW68,%MD66for 10 minutes of normal operation. All four must remain at zero where expected. -
Cross-reference sweep: with the project offline, search the entire TIA Portal project for the literal text
M69.2and the symbolic tag name. The result count must equal 3 (set, reset, coil) — never more, never less, unless the addition is a documented diagnostic mirror. - Force / release test: from the watch table, force the bit ON, then release. It must return to OFF on the next scan and remain OFF.
- Cold restart: power cycle the CPU. The bit must come up in its initialized state (BOOL default = 0 unless the tag's Retain is set and the prior value was 1). If retain is enabled, perform an MRES and confirm.
- HMI round-trip: trigger the SET condition from a button on the HMI, then trigger the RESET. Confirm via the HMI indicator that the bit transitions 0→1→0 cleanly.
- Cycle-time sanity: open Online & diagnostics → Cycle time. The OB1 cycle time must not have changed by more than 1 ms; an FB inadvertently moved into the M-area will sometimes drag in a large block.
9. Preventive Coding Practices
Adopt the following four rules in every S7-1200 project to make the M69.2 class of fault structurally impossible:
-
Reserve the M-area by band. Use the high band (
%M2000.0–%M2047.7) for "free user bits". Reserve%M0–%M199for clock/system. Reserve%M200–%M1999for HMI polling only. Document the band map in the project header. -
Never alias a multi-byte variable onto the M-area. Use a global DB with a typed UDT. If a sequencer requires a 32-bit state word, declare
StateWord : DWORD;in DB_State, not in the M-area. - Use SR/RS flip-flop blocks for any bit that is both set and reset in different networks. The block evaluates once per scan and guarantees a deterministic result. See the SR and RS instructions in the S7-1200 function manual.
- Add a startup OB (OB100) reset sweep for any non-retain bit you depend on. This guarantees a defined power-up state and makes cold-restart faults easier to isolate.
10. Troubleshooting Matrix
| Symptom observed in watch table | Likely cause | First test | Time to fix |
|---|---|---|---|
| M69.2 stays ON even after forcing OFF in watch table, returns ON within 1 scan | Word/DWord overlap from an FB or DB | Watch MW68 and MD66 simultaneously; look for the bits that change with M69.2 | 5–30 min |
| M69.2 toggles at 200 ms cadence (5 Hz square wave) | Clock memory byte placed at MB69 | Device config → System and clock memory → move clock byte to MB2000 | 2 min |
| M69.2 is forced OFF, stays OFF until next OB35 cycle, then returns ON | Cyclic interrupt OB writing the byte | Search project for OB35; check every MOVE/DWord-to-MW in the OB | 10–45 min |
| Only one of M69.0..M69.7 misbehaves; rest are clean | Sliced access of a wider variable (e.g. WordVar.%X2) |
Search for "%X2" and the parent tag name | 10 min |
| Bit works on the offline laptop, fails on the online CPU only | Online program differs from offline (TIA Portal "Load to device" was never run after the last edit) | Compare offline/online; perform full download | 5 min |
| Bit resets correctly until the operator presses a specific HMI button | HMI tag is a wide type whose write clobbers the bit | Inspect HMI tag address; switch to a BOOL or change update mode to On demand | 10 min |
| Bit fails on 1214C firmware V4.0 and earlier, works on V4.4 | External — system memory layout changed (rare; verify release notes) | Update to the latest firmware in the S7-1200 download center | 30 min + restart |
11. Frequently Asked Questions
Why does moving M69.2 to M69.3 fix the problem?
Because M69.2 was sharing its byte with a word or DWord that some other code was writing every scan. M69.3 is in the same byte (MB69), so on the surface the move should not help — but if the offending wider reference was, for example, %MW68 (bytes 68–69) and the colliding field was bit 2, then moving to bit 3 puts the bit just outside the collision (until you re-introduce the same conflict). Treat the move as a diagnostic confirmation that the M-area is the problem, not as the final fix. See S7-1200 System Manual, "Bit memory (M) area".
How do I tell whether a bit is a clock-memory bit?
Open the CPU's device configuration in TIA Portal, go to Properties → System and clock memory. The clock memory byte is a single byte; if its address is MB69 then every bit from M69.0 to M69.7 toggles at a fixed rate and is unsafe to use as a user flag. Change the clock-memory byte to a dedicated address (commonly MB2000) and re-download the hardware configuration.
Is the S7-1200's M-area protected from word/DWord overlap?
No. STEP 7 Basic does not enforce a strict type on M-addresses; you can address the same byte as a BOOL, BYTE, WORD, DWORD, or sliced boolean on a wider tag. The compiler accepts all forms. Engineers must design a memory map and adhere to it. Reference: S7-1200 System Manual, "Areas of operands".
What is the safest memory region for free user bits on a 1214C?
For non-safety logic, use a non-retain global DB with a typed UDT, or reserve a high band such as %M2000.0–%M2047.7 for free user bits and document it. For safety logic, use a fail-safe DB inside the F-runtime group — never the M-area.
Can a TIA Portal cross-reference miss an overlapping write?
Yes. Cross-reference follows the symbolic name you click. If the colliding access uses a raw absolute address (e.g. POKE via a MOVE to MW68 with no symbol), the cross-reference on the symbolic tag M69.2 will not show it. Use a watch table monitoring MB69, MW68, MD66, MD67, MD68, MD69 in parallel — this is the only way to expose raw-address collisions that the symbol search cannot see.