Problem Description
Symptom observed on a SIMATIC S7-1200 (firmware V4.x) coupled to a KTP400 Basic PN HMI, configured in TIA Portal V13:
- An up-counter (CTU) operating on a photo-electric sensor counts real production pieces correctly most of the time.
- The connected HMI tag, however, renders as a hash character (
#), the digit4, or any other non-monotonic value, and appears to flash or jump. - A separate timer tag displayed on the same screen reads cleanly and is not affected.
- The counter program is implemented inside a Function Block (FB) with a single-instance Data Block; the HMI tag points to a default tag table address that is, in this case,
%MW0.
The reported resolution was to move the counter from %MW0 to %MW500 (or %MW5000), after which the HMI value stabilised. The remainder of this article explains exactly why that worked, how to prove the same root cause in your own project, and how to prevent it from recurring.
Root Cause: Clock Memory and System Memory Overlap with %MW0
The S7-1200 provides two special bit ranges that the CPU owns and toggles automatically:
| Range | Default address | Purpose |
|---|---|---|
| System Memory Byte / Bits | SMB0 / SMB1 (S7-1200) or configurable | Status bits (first cycle, always-ON, diagnostic) |
| Clock Memory Byte | Default = MB0 (configurable in Device Configuration → Properties → System & Clock Memory) | Eight square-wave generators, each running at a fixed frequency |
By default in TIA Portal V13 (and later), the Clock Memory Byte is enabled and assigned to MB0. The eight bits of MB0 then oscillate at the frequencies configured in the CPU properties dialog (typical defaults: M0.0 = 10 Hz, M0.1 = 5 Hz, M0.2 = 2.5 Hz, M0.3 = 2 Hz, M0.4 = 1.25 Hz, M0.5 = 1 Hz, M0.6 = 0.625 Hz, M0.7 = 0.5 Hz).
%MW0 is the 16-bit word formed by MB0 and MB1, the CPU is overwriting the value the CTU block writes into MW0 with the live clock-memory bit pattern. The HMI samples MW0 many times per second and reflects whichever value the CPU happens to have latched, which is why the operator sees #, 4, and other fluctuating numbers in rapid succession.Memory layout that is colliding
| Address symbol | Coverage | Overlapping the counter? |
|---|---|---|
| %MW0 (word) | Bytes MB0 and MB1 | Yes — same byte range used by the Clock Memory Byte |
| MB0 / MB1 (bytes) | Bits M0.0 … M1.7 | Yes |
| MD0 (double word) | Bytes MB0 … MB3 | Yes |
| M0.0 – M0.7 (bits) | Individual clock flags | Yes |
Writing a CTU's CV output to %MW0 is therefore equivalent to letting the CPU and the clock generator share the same register, with the clock generator winning at every cycle. The visible flash is not random: it is the binary waveform of MB0 reinterpreted as a signed integer. Bit pattern 0000 0100 = decimal 4, 0010 0011 = decimal 35, etc., and pattern 0000 0000 simply shows as 0 on the HMI if a character is mapped for that.
Why a Separate Timer Did Not Show the Same Symptom
The user reported that the timer field rendered correctly. This is consistent with the timer tag being placed at a different address (for example %MW2, %MW4, or a tag in the instance DB) that does not overlap the clock byte. The corruption is purely a function of which physical byte range the offending tag references, not of the data type or block origin.
Pre-Fix Diagnostic Procedure
Use this checklist to confirm the same root cause in your project before changing any code.
- Open the Watch and Force Tables folder of the S7-1200 device in the project tree and add a new table.
- Add the exact address used by the HMI tag (e.g.
%MW0). It must be the same address that the IO field on the KTP400 page references — symbolic tags can resolve to unexpected absolute addresses if the DB was recompiled. - Go online with the PLC and observe the value. If the displayed number wobbles between 0, 1, 2, 4, 8, 16, 32, 64, 128 (and combinations) and changes at a rate that matches the configured clock frequencies, the byte range is owned by the clock generator.
- Open Device Configuration → Properties → System & Clock Memory. Read the Clock memory byte field. If it is set to
0, the colliding address is MB0. - For S7-1200 FW4.0+ and S7-1500 controllers, use the Traces function (Project tree → Traces) to record the counter's current value over time. A trace will show a staircase pattern chopped up by clock-bit transitions.
Step-by-Step Resolution
Option A — Move the counter into free memory (recommended)
- In TIA Portal, change the CTU's
CV(current value) output destination from%MW0to a free address such as%MW500or%MW5000. Reserve at least 50 MW of headroom in your naming scheme for future tags. - Update the HMI tag (or the symbolic reference) to point to the new address. If you are using a default tag table with an absolute address, change the address on the tag itself.
- Compile the PLC project (Build → Compile) and then compile the HMI project.
- Download both to the S7-1200 and the KTP400.
- Cycle the photo-sensor input a few times and observe the HMI — the value should now increment monotonically and never display
#or jump to unexpected values.
Option B — Disable or relocate the Clock Memory Byte
- Open Device Configuration for the S7-1200 CPU.
- Navigate to Properties → System & Clock Memory.
- Either uncheck Enable clock memory byte (recommended if you do not actually use it in your logic), or change the byte to a non-conflicting value such as
100(reserving MB100–MB101 from any other use). - Recompile and download.
Memory Map and Reservation Table
For a typical S7-1214C / S7-1215C station, allocate reserved regions in the bit-memory (M) area so that automatic CPU resources and application tags never collide.
| Range | Reserved for | Notes |
|---|---|---|
| MB0 – MB1 | Clock Memory (or do not use if feature disabled) | If kept at 0, treat the entire M0.0 – M1.7 area as reserved |
| MB2 – MB9 | System status bits and first-cycle flags | Read-only from application |
| MB10 – MB99 | Free for sticky flags and handshakes | Retained, if needed |
| MW100 – MW499 | Integer tag area exposed to HMI | Use only 16-bit word boundaries |
| MW500 – MW999 | Counters and production totals | Mirror to retentive area if power loss matters |
| MW1000+ | Buffer / recipes / future | Document as you add tags |
This is a convention, not a Siemens requirement — but it eliminates the entire class of clock-memory aliasing bugs.
Edge-Trigger Hygiene: Avoiding False Counts
A second, independent cause of the user's report was a counter that incremented on every PLC scan, not on every piece. Even after fixing the MW0 overlap, verify that the counter input is conditioned with a positive edge:
// SCL example for S7-1200
IF "PhotoSensor" AND NOT "SensorPrev" THEN
"DB_Counter".CTU_DB.CV := "DB_Counter".CTU_DB.CV + 1;
END_IF;
"SensorPrev" := "PhotoSensor";
Or, equivalently in LAD/FBD, place a normally-open contact of "PhotoSensor" in series with a P (edge-detect) coil, and feed that pulse into the CTU's CU input. The TIA Portal online help on the CTU block explicitly states that the current value is updated only on a rising edge of CU and that, for the IEC counter implementation, the value ranges from 0 to 32 767 for an INT and from -2 147 483 648 to 2 147 483 647 for a DINT.
INT vs DINT Overflow Behaviour
| Data type | Range | Wraps at | Visible symptom on HMI |
|---|---|---|---|
| INT | -32 768 to 32 767 | 32 767 + 1 → -32 768 | Counter "jumps" from a positive maximum to a large negative number |
| DINT | -2 147 483 648 to 2 147 483 647 | 2 147 483 647 + 1 → min negative | Same jump, but only after billions of counts |
| REAL | ±3.4e38 | Precision loss long before wrap | Display shows scientific notation or 1.#INF
|
For a piece counter on a packaging line, DINT is almost always the correct choice. Convert the CTU's CV from INT to DINT in the FB static section, and update the HMI tag data type accordingly.
HMI-Side Checks on the KTP400
Even with a clean PLC tag, the HMI itself can produce the # glyph if the configured display cannot render the value:
- Open the IO field properties on the affected screen in the KTP400 configuration.
- Confirm the Display format matches the tag data type (Decimal for INT/DINT, Float for REAL). A binary or BCD format will render bits as on/off rather than as a number.
- Verify the field width: an IO field configured for 5 characters that suddenly receives a 6-digit number will often render
#rather than truncate. - Open Animations on the IO field and remove any visibility, appearance, or motion animation that may be toggling at a high rate.
- Confirm the HMI connection is to the correct PLC and the correct DB; an HMI tag that is bound to a non-existent or wrong DB will display
#when the runtime cannot resolve the symbol.
Symbolic vs Absolute Addressing on the HMI
TIA Portal V13 supports both symbolic and absolute addressing for HMI tags. A common source of "the value used to work, then it went wrong" complaints is the loss of a symbolic link after a project edit:
| Mode | Pros | Cons |
|---|---|---|
| Symbolic (preferred) | Renames propagate, link follows DB recompile | Initial setup is more verbose; broken links are harder to spot in the HMI editor |
| Absolute | Direct, obvious | Will silently point to a different byte if the DB layout changes; clock-memory collisions are easier to introduce |
If the user's counter tag had been symbolic, the symptom of MW0 aliasing would have been the same — the data type and address would not have changed — but the troubleshooting path would have led directly back to the PLC program rather than to "the HMI shows a number I did not set".
Verification Procedure After the Fix
- Open the watch table created earlier and confirm the value of the new MW address (e.g.
%MW500) increments by exactly 1 per sensed piece. - Check MB0 in the same watch table. If Clock Memory is still enabled, MB0 should still toggle, but the counter tag should no longer reference it.
- From the TIA Portal Online & Diagnostics view, run a Trace on the new MW and the sensor input simultaneously. You should see clean 1-step increments aligned to the rising edge of the sensor.
- Power-cycle the CPU to confirm the counter behaves correctly from a cold start (watch for any uninitialised-memory effects on the instance DB).
- Force a value via the watch table above the INT ceiling and confirm the expected wrap (or that your DINT conversion prevents the wrap).
Recommended Project Hygiene
- Document the M area. Maintain a single memory-map document or PLC data block comment header that lists every reserved byte, including the clock memory byte, system memory byte, retentive areas, and HMI tag regions.
- Avoid M0.0 – M1.7 for any user tag unless you have explicitly turned Clock Memory off and never use the System Memory Byte either.
- Use DINT for production counters. Even if the line will never produce 32 767 pieces, DINT removes a class of future bug.
- Prefer symbolic HMI tags. Symbolic links in TIA Portal V13+ survive DB renumbering and refactoring better than absolute addresses.
- Always condition counter inputs with a positive-edge evaluation; never feed a raw level into a CTU's CU input.
Troubleshooting Matrix
| Symptom on HMI | Likely cause | Diagnostic | Fix |
|---|---|---|---|
# glyph |
Display format mismatch, field too narrow, or address not resolvable | Check IO field width and format; verify tag is online | Adjust format / widen field / repair tag |
Flashing 4, 2, 1, etc. |
Clock Memory Byte aliasing the counter word | Read MB0 in watch table; check CPU clock-memory setting | Remap counter or move clock byte |
| Counter occasionally jumps by more than 1 | Sensor input not edge-conditioned | Trace the CU input; check for bouncing input | Add positive-edge evaluation; debounce input |
| Counter wraps to negative at high count | INT overflow | Inspect data type of CV | Promote CV to DINT |
| Counter reads correctly in PLCSIM but wrong on panel | HMI tag resolves to a different address than expected | Compare absolute address on the HMI tag with the PLC tag | Re-link the HMI tag to the correct symbol or address |
| Counter OK in simulation, wrong in TIA online test | Different project / different DB instance downloaded to target | Compare project checksum in Online & Diagnostics | Download current project to target |
Reference Material
- SIMATIC S7-1200 Programmable Controller — System Manual (entry ID 109751706): support.industry.siemens.com — S7-1200 System Manual
- SIMATIC S7-1200 / S7-1500 — Clock Memory and System Memory Bytes (entry ID 87603991): support.industry.siemens.com — System & Clock Memory
- SIMATIC KTP400 Basic — Operating Instructions (entry ID 21859050): support.industry.siemens.com — KTP400 Basic PN
- TIA Portal V13 — Programming and Operating Manual (entry ID 109751706, sections on CTU, edge detection, and tag binding)
- S7-1200 CPU 1214C DC/DC/DC — Device Manual (entry ID 106474690): support.industry.siemens.com — S7-1200 CPU 1214C
Why does my S7-1200 counter show the digit 4 or a # on the KTP400 HMI?
The most common cause is that the counter word is bound to %MW0, which overlaps the default Clock Memory Byte at MB0. The CPU continuously overwrites MB0 with a binary square-wave pattern, so the HMI samples a toggling bit pattern that can read as 4, 2, 1, 0, etc., depending on which moment it polls the value. Move the counter to a free address such as %MW500.
How do I disable the S7-1200 Clock Memory Byte?
Open Device Configuration for the CPU in TIA Portal, then Properties → System & Clock Memory, and uncheck Enable clock memory byte. Recompile and download. Alternatively, change the byte number from the default 0 to a value such as 100 to remove the conflict with M0.0–M0.7.
My counter goes negative at 32 768 pieces. What is the fix?
You are using an INT current value, which wraps at 32 767. Change the CTU's CV to a DINT in the FB static section, update the HMI tag data type to DINT, and re-download. A DINT counter will run from 0 to 2 147 483 647 before any wrap.
How can I monitor the counter value with a watch table?
Project tree → PLC device → Watch and force tables → Add new watch table. Enter the absolute address the HMI uses (e.g. %MW500) and the sensor input address, then go online. For S7-1200 FW4.0+ and S7-1500 you can also use the Traces function for a time-stamped recording.
Should the HMI tag be symbolic or absolute in TIA Portal V13?
Prefer symbolic HMI tags tied to PLC tag names. The link survives DB renumbering and avoids silent aliasing when the DB layout changes. Absolute addressing is acceptable for one-off commissioning but should be converted to symbolic before the project is released.