Problem Description
An Siemens S7-1200 CPU 1215C (firmware V4.x) was commissioned with the following time configuration in TIA Portal:
- Time zone:
UTC+01:00 Europe/Zagreb - Daylight Saving start rule:
Last Sunday of March, 02:00 CET - Daylight Saving end rule:
Last Sunday of October, 03:00 CEST
Two months after commissioning — immediately after the October DST end transition — the reported local time on the PLC started to lag the actual local time by exactly one hour (60 minutes). The reported UTC time remained correct, indicating the offset was applied in the wrong direction or that DST rules were being applied twice. Report timestamps, audit trails, and shift logs generated from PLC tags carried an incorrect timestamp for the entire post-DST period.
The engineer removed the DST block from the hardware configuration to allow manual overwriting from the HMI, but the same one-hour lag persisted. After enabling NTP synchronization against a SCADA workstation, the PLC time appeared to "flip-flop" — every NTP poll (minimum configurable interval is 10 seconds) caused the displayed time to briefly drop back one hour, then snap forward again as the local-time conversion was re-applied. The engineering team confirmed that no user logic was writing to the system clock via WR_SYS_T (Set time of day) or SET_TIMEZONE.
S7-1200 Time Architecture: System Time vs. Local Time
Every S7-1200 CPU tracks time as UTC internally (system time). The CPU then exposes a derived local time by applying the configured time-zone offset and the DST rule defined in the device configuration. Whether a particular instruction, tag, or HMI field returns the system or local value depends on the tag path or the instruction variant used.
| Source | Returns | Typical Use |
|---|---|---|
PLC tag %SystemTime (system clock tag) |
Local time (DST-adjusted) | HMI display, time-stamped reports |
PLC tag %LocalTime (legacy) |
Local time | Operator displays |
RD_SYS_T (Read system time / clock) |
System time (UTC) – DTL format | UTC logging, NTP client comparisons |
RD_LOC_T (Read local time) |
Local time – DTL format | Local-time logging, scheduling |
WR_SYS_T (Set time of day) |
Writes UTC; DST/TZ derived after write | NTP, manual time set from HMI |
T_CONFIG / T_CTRL / T_CONV |
Per-instruction behavior (see manual) | Time conversion, timer blocks |
If the application reads RD_SYS_T and then expects a local-time result, or if the HMI is bound to a tag that returns UTC without conversion, the time will be off by the configured offset (typically 1 h or 2 h depending on DST state). See the official S7-1200 Date, time-of-day, and clock functions reference for ENO behavior and tag references.
Root Cause Analysis
After working through the diagnostic checklist below, the failure mode observed here matches DST-rule re-application after a TIA Portal download: the project-side hardware configuration had the DST rules defined, but the running CPU retained its pre-download local-time offset of +02:00 for the CEST portion of the year. When the calendar rolled past the October end rule, the project would have reduced the offset to +01:00, but because the running CPU had not fully re-applied the rule set, it continued to display UTC+02:00 as if still in summer time — producing a one-hour-forward display. Because the SCADA / NTP source was writing UTC, the user's perception of "one hour behind" depended on which clock face the application bound.
The secondary fault observed — flip-flopping under NTP polling — is caused by the interaction between WR_SYS_T and the local-time derivation: every NTP write resets UTC, then the local time is re-calculated. If the DST block is inconsistent (for example, DST rule still active for an end-date that has passed, or DST rule missing entirely), each re-derivation can yield a different offset until the rule set is rebuilt.
Common root causes for "one hour off" reports on S7-1200
- Reading UTC where local time is expected. Many engineers assume the system clock tag is local. It is UTC.
- DST rule not downloaded / not committed. A change to the time-zone or DST rule requires a full configuration download and, in some firmware versions, a STOP/RUN transition to take effect.
- Time-zone configured but DST rule absent. Without a DST rule, the local time equals UTC + TZ offset year-round. With a DST rule but no end-date, the offset can stick at +02:00.
-
Multiple writers to the clock. HMI time set, NTP, and a logic-driven
WR_SYS_Tall racing against each other. - CPU battery low / removed. Without battery backup, the real-time clock loses time on power-cycle and reverts to a default that may not match project TZ/DST.
- Project online vs. offline mismatch. After editing the device configuration (Properties > Time of day), the change must be downloaded; "Go online" alone does not push new TZ/DST data.
Diagnostic Procedure
Follow this sequence before changing any project configuration. Capture each value into a data block for post-mortem review.
-
Verify project vs. running configuration
In TIA Portal, right-click the CPU → Online & Diagnostics → Time of day. Compare the displayed Time zone and Daylight saving values against the offline project (Device configuration → Properties → Time of day). If they differ, the running CPU is using stale TZ/DST data. The Time section on the lower-left also shows PG/PC time side-by-side with CPU time for direct comparison. -
Capture both clocks into a DB
Add a global DB with twoDTLtags and the following logic in OB1 (or a cyclic OB):
The expected delta for UTC+01:00 in winter (CET) is// OB1 – cyclic capture of system and local clocks "diagDB".systemTime := RD_SYS_T(); // UTC "diagDB".localTime := RD_LOC_T(); // Local (TZ + DST applied) "diagDB".deltaSec := TIME_TO_INT("diagDB".systemTime - "diagDB".localTime);-3600s and-7200s in summer (CEST). Any value outside ±10 s of these baselines confirms a TZ/DST problem. -
Inspect the diagnostic buffer
Online & Diagnostics → Diagnostic buffer. Look for entries tagged Time changed by ..., Time set by NTP, or Time jump. These entries record eachWR_SYS_Tinvocation. -
Search the program for clock writers
Cross-reference the project for any call toWR_SYS_T,SET_TIMEZONE, the Time set HMI function, and the Set time of day system function block. Disable all writers except the one chosen as the master (typically NTP). -
Check the battery / power-fail behavior
Online & Diagnostics → Diagnostics status. A "Battery exhausted" or "Battery low" status indicates the buffered real-time clock cannot retain time across power cycles and will revert to the default 01.01.2000 00:00 in UTC. -
Validate HMI bindings
On the HMI side, confirm the time field reads from a tag whose path is%SystemTime(local time) — notRD_SYS_T. If the HMI is bound to the wrong tag it will display UTC regardless of the PLC's local time.
Solution
Apply the following changes in the order listed. After each step, download to the CPU and verify with the diagnostic procedure above.
-
Re-establish the TZ/DST configuration
Open Device configuration → Properties → Time of day and set:- Time zone:
(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb - Activate Daylight saving time: Yes
- DST start rule: Last Sunday of March, 02:00, +01:00 (switch standard → daylight, offset +01:00)
- DST end rule: Last Sunday of October, 03:00, 00:00 (switch daylight → standard, offset 0)
- Time zone:
-
Pick a single clock master
Disable the HMI Set time of day function. Disable any user program call toWR_SYS_T. Leave only the NTP client as the writer. The NTP server in the SCADA workstation should be configured to serve UTC, not local time. -
Tune the NTP poll interval
S7-1200 supports a minimum NTP poll of 10 s on firmware V4.2+ (server interval Synchronization interval in device configuration → Time of day → NTP). 10 s is acceptable when the only writer is NTP; the flip-flop will not occur becauseWR_SYS_Tand the local-time derivation are now consistent. For a stable display, increase the interval to 60 s or 300 s to reduce diagnostic-buffer churn. -
Replace the CPU battery if low
For the 1215C, the buffer battery is a CR1025 lithium cell accessible behind the lower access flap. Power down the CPU, replace the cell, power up, then re-trigger NTP sync. -
Re-bind HMI time field
In the HMI project, change the binding of the clock display from any custom tag to%SystemTime(local). For KTP and Comfort Panels this is found under Connections → Area pointers → Date/Time. -
Audit historical data
For the affected post-DST period, re-stamp any reports using UTC + manual offset knowledge. Add a one-line note to the audit log indicating the time offset and the affected window.
Working with RD_SYS_T and RD_LOC_T
The two instructions return a DTL (date-and-time, 8-byte) structure. A practical ladder/ST snippet for computing the local-vs-system delta in seconds:
// Compute local - system delta in seconds
#localT := RD_LOC_T(); // DTL with local offset applied
#systemT := RD_SYS_T(); // DTL, always UTC
#delta := DTL_TO_INT(#localT) - DTL_TO_INT(#systemT); // seconds
IF ABS(#delta - (-3600)) > 10 AND ABS(#delta - (-7200)) > 10 THEN
"diagDB".timeInvalid := TRUE; // latch a fault bit
END_IF;
For more advanced conversions (for example, producing a Unix timestamp for an NTP client running inside the PLC), the S7-1200 Date and time-of-day instructions page documents T_CONV, T_ADD, and T_SUB which operate on the TIME and DTL types.
Verification
After each configuration change, run this verification matrix:
| Check | Expected (winter / CET) | Expected (summer / CEST) | How to read |
|---|---|---|---|
RD_LOC_T - RD_SYS_T
|
-3600 s ± 1 s | -7200 s ± 1 s | DB tag in TIA Portal watch table |
| Online & Diagnostics → Time of day → PLC time vs. PG/PC time | Match ±2 s | Match ±2 s | Lower-left of working pane |
| HMI displayed time vs. wall-clock local | Match ±1 s | Match ±1 s | HMI faceplate |
| Diagnostic buffer entries <em>Time changed</em> | One per NTP poll, no jumps | One per NTP poll, no jumps | Diagnostic buffer |
| Report timestamp for a known event | Local time, no offset | Local time, no offset | Sample report |
NTP Configuration Details
NTP on the S7-1200 is configured under Device configuration → Properties → Time of day → NTP. Key parameters:
| Parameter | Setting | Notes |
|---|---|---|
| NTP server address | SCADA PC IP, or pool.ntp.org | Up to 4 servers; first reachable wins |
| Update interval | 10 s (min), 60 s recommended | Shorter intervals increase CPU load and diagnostic-buffer churn |
| Time zone of NTP source | UTC | NTP always carries UTC; do not point the PLC at a local-time source |
| Authentication | Optional (MD5 / SHA-1) | Use when network is shared with non-trusted devices |
| Firmware requirement | V4.2 minimum for full NTP client | Earlier firmware lacks NTP; use SIMATIC Time Sender or external master clock |
Edge Cases and Field-Proven Caveats
- Firmware V4.0 / V4.1 DST behaviour. On early V4.x firmware, changing the DST rule set requires a STOP/RUN transition; a download at RUN does not re-apply the DST table until the next OB1 scan after a power-cycle.
- CPU 1212C vs 1215C. Both share the same time-of-day firmware path; the 1215C's higher part number does not change DST handling.
- Battery removal during commissioning. If the battery is removed or never installed, the PLC's real-time clock starts from the default (2000-01-01 00:00 UTC). The CPU will not flag this on first start; NTP must be the trusted source until the battery is verified.
- Multi-project / multi-master. When the same SCADA serves many PLCs, ensure the SCADA NTP server is itself synchronized to a stratum-1 source. A drifting SCADA clock will propagate drift to every PLC that polls it.
- Summer/winter transition windows. At the exact DST transition (last Sunday of March 02:00 → 03:00 and last Sunday of October 03:00 → 02:00), do not schedule logic that depends on a one-hour monotonic counter. Schedule such logic for 30 minutes after the transition.
Troubleshooting Matrix
| Symptom | Likely Cause | Action |
|---|---|---|
| Time is exactly 1 h ahead of UTC | Local-time tag bound to a UTC source plus an extra TZ offset | Re-bind HMI to %SystemTime tag |
| Time is exactly 1 h behind after October | DST rule not applied; offset stuck at +02:00 | Re-download hardware config and STOP/RUN |
| Time flip-flops every 10 s | Multiple writers (NTP + HMI + logic) racing | Disable all but one writer |
| Time is 2 h behind after October | TZ set to UTC+02:00 with DST adding +01:00 incorrectly | Set TZ to UTC+01:00 and enable DST |
| Time drifts slowly after power-cycle | Battery exhausted | Replace CR1025 battery on 1215C |
| Time is correct on PG but wrong on HMI | HMI bound to UTC tag or wrong area pointer | Use Date/Time area pointer |
| Time reads 01.01.2000 after power-cycle | Battery removed, NTP not running | Install battery, enable NTP, force sync |
Safety and Audit Considerations
Time-of-day errors on a logged-data system have audit consequences even if no process upset occurs. Treat any one-hour or two-hour offset in report timestamps as a data-integrity event and document the affected window. If the PLC is part of a safety-related function (F-CPU 1215FC, F-CPU 1214FC), do not rely on the PLC clock for safety event time-stamping — use the F-CPU's diagnostic buffer entries which carry their own sequence counters and are independent of the user TZ/DST configuration.
FAQ
Why does my S7-1200 1215C show the wrong time after the October DST end date?
The CPU maintains UTC internally and derives local time using the TZ/DST rule set. After the October transition, the offset must drop from +02:00 to +01:00. If the rule set was not re-downloaded, or if the running CPU retained the +02:00 offset, the local-time display will lag real local time by one hour. Re-download the hardware configuration and perform STOP/RUN to commit the new DST table.
What is the difference between RD_SYS_T and RD_LOC_T on the S7-1200?
RD_SYS_T returns the system time in UTC as a DTL value. RD_LOC_T returns the local time after applying the configured time-zone and DST offset. Use RD_LOC_T for operator displays and RD_SYS_T for UTC logging or NTP comparisons. See the official S7-1200 Date, time-of-day, and clock functions reference for full behavior.
What is the minimum NTP poll interval on an S7-1200?
10 seconds on firmware V4.2 and later. Shorter intervals are not configurable. For most plant networks, 60 s or 300 s is sufficient and reduces diagnostic-buffer churn.
Do I need a STOP/RUN transition after changing the DST settings?
On firmware V4.0 to V4.2, yes — the DST rule table is committed at the next STOP/RUN. On V4.4 and later, the new rule set is accepted at RUN. Always verify with the Online & Diagnostics "Time of day" pane after download.
How do I stop the PLC time from "flip-flopping" every 10 seconds under NTP?
Ensure only one writer (the NTP client) calls WR_SYS_T. Disable the HMI "Set time of day" function and any user logic that writes the clock. With a single writer, each NTP poll writes a consistent UTC value and the local-time derivation produces a stable result until the next poll.