Time-Stamping 700 DI Signals on S7-315-2DP for WinCC

David Krause14 min read
S7-300SiemensTutorial / How-to
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

Overview

Generating accurate, time-stamped event records for hundreds of digital inputs on a SIMATIC S7-315-2DP and forwarding them to a WinCC HMI/SCADA station is one of the most common long-tail problems in S7-300 engineering. The CPU supports time-of-day interrupts and a 40 ALARM_S concurrent instance cap (per Siemens Entry ID 841294), which makes the textbook Alarm-S path unusable for the typical 600–700 discrete signal scale. This article shows the engineered workaround: a polled high-speed input scan, a double-buffered SOE (Sequence of Events) DB in the CPU, and a WinCC tag/project configuration that consumes the buffer like a chronological message stream.

The approach below preserves the standard SIMATIC time model (UTC, no DST flag), works with STEP 7 V5.5 / V5.6 and WinCC V7.x or WinCC Professional (TIA Portal) V16–V18, and degrades gracefully when the buffer is full. The methods described are also valid for the S7-314, S7-315-2 PN/DP, S7-317, and S7-319 CPUs because they all share the same SFC 17/18 ALARM_S architecture and OB1 / OB40 dispatching model.

Field note: Siemens S7-300 CPUs do not support hardware time-stamping on integrated digital inputs the way an S7-400H with an MCP/FM350 or the ET 200SP modules with the TM (Time stamping) feature do. Resolution is bounded by the OB1 scan time and any OB40 hardware-interrupt latency. Plan the worst-case timestamp error at 1× OB1 + 1× input filter time.

Prerequisites

Item Required value Notes
CPU 6ES7 315-2AFxx / 6ES7 315-2EHxx (S7-315-2DP / -2 PN/DP) Firmware V2.x–V3.x. OB40 must be present.
STEP 7 V5.5 SP4 or V5.6 with S7-CPU update package For SFC 17/18 + IEC timers
WinCC V7.4 SP1 / V7.5 / V16 Professional Tag management + Alarm Logging
DI module SM 321 (6ES7 321-1BL00-0AA0) or ET 200M (6ES7 153-1AA03) Input filter 0.5–3 ms typical
Time source SIMATIC procedure (master clock on CPU) or NTP via CP Recommended: synchronize via SFC 0 SET_CLK once per shift
OB blocks OB1, OB40, OB82, OB100, OB121 OB40 is critical for sub-cycle event capture

Time-Stamping Methods on S7-300: Comparison

Three implementation paths are available. The first two consume ALARM_S resources and are not viable at 700-signal scale; the third is the only one that scales.

Method Resolution Max events / scan Hardware cost Recommended for S7-315-2DP?
ALARM_S via SFC 17/18 (OB40 hardware interrupt + time-of-day) 1 ms (time-of-day stamp embedded by CPU) 40 concurrent ALARM_S blocks per CPU None No — hard cap is 40
S7-400 MCP/FM 350-1/2 hardware time stamping ≤1 ms (synchronised, distributed) 32 channels per module, expandable MCP card, FM 350, isolated backplane slot No — S7-400 only
Software polling + ring-buffer DB (this article) OB1 cycle time, typically 5–20 ms Unlimited (configurable ring depth, e.g. 4096 entries) None Yes — standard S7-300 + SM 321

Why the 40 ALARM_S Limit Exists

Siemens Entry ID 841294 documents that the S7-300 firmware maintains a fixed-size instance table for active ALARM_S / ALARM_8 / ALARM_8P blocks. Each ALARM_S instance costs one slot; the slot is held until the associated message acknowledgment state machine closes. With 700 monitored DIs, you would need at least 700 active instances during a worst-case event storm, which exceeds the 40-slot table and triggers Wöhler-style overflow errors (CPU diagnostic buffer entry "OB40 queue overflow" or "ALARM_S resource exhausted").

Two options remain on the S7-315-2DP:

  1. Use the standard WinCC chronological message path with a small number of high-priority signals only (process alarms, ESD trips, breaker status).
  2. Use a polled ring-buffer DB that the application program fills; WinCC reads the DB and generates chronological messages from a 1-second internal polling cycle.

Architecture: Polled SOE Buffer + WinCC Chronological View

The DB is a flat array of UDTs that the application writes on every DI edge. WinCC is configured with one WinCC tag per signal plus a shared "stamp / tail / overflow" triplet that tells the HMI which entries are new since the last read. The same triplets can drive a WinCC Alarm Logging control as user-defined messages via dynamic limits, or they can be displayed in a custom VB / C / C# script on the WinCC client.

SM 321 DI32 / ET 200M Process I/O 0–700 Filter 0.5–3 ms S7-315-2DP OB1 / OB40 Edge detect (FC 100) Time stamp via SFC 1 READ_CLK DB 1000 SOE Ring 4096 entries UDT 10 Head / Tail / Overflow WinCC V7.4+ / V16 Tag mgmt + Alarm Logging 1 s polling, WinCC timer S7 connection (MPI / PROFIBUS / TCP)

Step-by-Step: Build the SOE DB and the Edge-Detect FC

Create the UDT, the ring-buffer DB, the edge-detect FC, and the OB40 dispatcher in STEP 7. All sample code targets STEP 7 V5.5 / V5.6 in STL/SCL.

Step 1 – Define UDT 10 (one SOE entry)


TYPE UDT 10
STRUCT
  di_index  : INT ;     // 0..699 - which DI changed
  di_state  : BOOL ;    // FALSE->TRUE=0 / TRUE->FALSE=1
  reserved  : BYTE ;    // alignment
  ms_since  : DWORD ;   // PLC tick in ms (SFC 64 TIME_TCK diff)
  tod       : DATE_AND_TIME ;  // 8 bytes - SFC 1 READ_CLK
END_STRUCT
END_TYPE

Step 2 – Create DB 1000 (the ring buffer)


DATA_BLOCK DB 1000
  TITLE = 'SOE Ring Buffer (4096 entries)'
  STRUCT
    head      : INT ;          // write pointer (0..4095)
    tail      : INT ;          // read pointer (WinCC side, updated by WinCC)
    overflow  : BOOL ;         // ring wrapped while WinCC did not read
    loss_cnt  : DWORD ;        // events lost on overflow
    last_tick : DWORD ;        // last SFC 64 value for ms diff
    buf       : ARRAY[0..4095] OF UDT 10 ;
  END_STRUCT
BEGIN
  head := 0; tail := 0; overflow := FALSE;
  loss_cnt := 0; last_tick := 0;
END_DATA_BLOCK
Memory budget: UDT 10 is 16 bytes; 4096 entries occupy 65 536 bytes. This fits a 315-2DP work memory of 128 KB (6ES7 315-2AF03, 6ES7 315-2EH14). For older 64 KB CPUs, use 2048 entries.

Step 3 — FC 100: Edge-detect on the 700 DIs

The function compares the current input image PEW/PEB against the previous image stored in a static DB. On any bit change, it records the DI index, new state, SFC 64 tick diff, and the current DATE_AND_TIME from SFC 1.


FUNCTION FC 100 : VOID
VAR_TEMP
  t_di_word_idx   : INT ;
  t_bit_idx       : INT ;
  t_prev_word     : WORD ;
  t_curr_word     : WORD ;
  t_diff_word     : WORD ;
  t_di_index      : INT ;
  t_tick_now      : DWORD ;
  t_tick_prev     : DWORD ;
  t_tod           : DATE_AND_TIME ;
  t_retval        : INT ;
END_VAR
BEGIN
  // Read high-resolution tick (1 ms if OB period = 1 ms) - SFC 64
  t_retval := TIME_TCK();            // returns t_tick_now
  t_tick_prev := DB1000.last_tick;
  DB1000.last_tick := t_tick_now;

  FOR t_di_word_idx := 0 TO 21 DO           // 22 words * 32 = 704 bits
    t_prev_word := WORD_TO_BLOCK_DB(900).DW[t_di_word_idx];
    t_curr_word := PIW[t_di_word_idx * 2]; // 0..43 process image
    t_diff_word := t_prev_word XOR t_curr_word;

    IF t_diff_word <> 0 THEN
      FOR t_bit_idx := 0 TO 15 DO
        IF (t_diff_word SHR t_bit_idx) AND 1 = 1 THEN
          t_di_index := t_di_word_idx * 32 + t_bit_idx;
          t_tod := DT0;                    // placeholder - see call below

          // SFC 1: read time-of-day
          t_retval := READ_CLK(LADDER:= t_tod);

          // Write to ring buffer
          DB1000.buf[DB1000.head].di_index := t_di_index;
          DB1000.buf[DB1000.head].di_state := (t_curr_word SHR t_bit_idx) AND 1;
          DB1000.buf[DB1000.head].ms_since := t_tick_now - t_tick_prev;
          DB1000.buf[DB1000.head].tod := t_tod;

          // Advance head with wrap, detect overflow vs tail
          IF DB1000.head = 4095 THEN
            DB1000.head := 0;
          ELSE
            DB1000.head := DB1000.head + 1;
          END_IF;

          IF DB1000.head = DB1000.tail THEN
            DB1000.overflow := TRUE;
            DB1000.loss_cnt := DB1000.loss_cnt + 1;
          END_IF;
        END_IF;
      END_FOR;
    END_IF;

    WORD_TO_BLOCK_DB(900).DW[t_di_word_idx] := t_curr_word;
  END_FOR;
END_FUNCTION

Step 4 — Wire FC 100 into OB1 (or OB40 for sub-cycle response)

For fastest capture, call FC 100 from OB40. Configure the SM 321 module hardware interrupts to fire on either rising, falling, or both edges. Each OB40 event indicates which channel changed; the FC then batches the additional bits that flipped during the same scan.


ORGANIZATION_BLOCK OB 40
  TITLE = 'Hardware interrupt - DI edge dispatcher'
BEGIN
  // OB40_POINT_ADDR tells us which channel triggered
  IF OB40_POINT_ADDR >= 0 AND OB40_POINT_ADDR <= 21 THEN
    CALL FC 100 ;
  END_IF;
END_ORGANIZATION_BLOCK

Step 5 — Time synchronisation

Bring the CPU to wall-clock time using SFC 0 SET_CLK from a higher-level clock, or enable SIMATIC time on the CP 343-1 Lean (S7-300 family) so the CPU clock is a stratum slave. Without synchronisation, the SFC 1 timestamp drifts by the RTC tolerance (± a few seconds per day on standard 315-2DP).


// In OB100 (startup) - initialise CPU time from CP
t_retval := SET_CLK(SET := t_external_dt);
Time-zone pitfall: The DATE_AND_TIME field in WinCC is a UTC offset, not a localised timestamp. Per Siemens 7604251, the time stamp sent from the AS contains no zone or DST information. Set the WinCC computer's time zone to UTC and let the OS or WinCC perform the local conversion; otherwise you will see a one-hour DST shift in spring/autumn.

Step-by-Step: WinCC Project Configuration

  1. Open the WinCC Explorer, right-click Tag Management › SIMATIC S7 PROTOCOL SUITE › PROFIBUS (or TCP/IP) and create a new connection. Station address = CPU MPI / IP, slot = 2, rack = 0.
  2. Create a WinCC tag of type Raw Data Tag (16-bit) for the head pointer at DB1000, DBB0 (INT). Repeat for tail at DB1000, DBB2 and overflow at DB1000, DBX4.0. Update cycle: 1 s.
  3. For every DI in the SOE buffer, create a structure tag of type Text tag with user-defined length pointing to a single UDT 10 element, e.g. DB1000, DBB12 + i*16. The actual array is best loaded into a single 64 KB "SOE Shadow" data block, and the WinCC alarm control consumes the new entries from head→tail movement.
  4. Open Alarm Logging › Message Classes and add a new class SOE with archive enabled.
  5. Add a single User-defined message with 2 process values (DI index, DI state) and select the message number dynamically. Drive the message number from a C / VB action that converts head - tail into message numbers 100001–104096. Set the message text to "DI %1 changed to %2 at %3".
  6. Enable the Chronological messaging option in Alarm Logging › Properties › Time and select Time stamp from AS. This is the WinCC V7.x switch that triggers the PC time = CPU time behaviour.
  7. Place an AlarmControl on the desired picture, bind it to the SOE message class, and set sort order to Chronological descending with Process time as the secondary key.

Configuring the User-Defined Message Trigger

When a new entry is detected at the WinCC side, fire a single user-defined message with the DiagEvent API or MSG_EVENT C function. The two process values are populated from the shadow DB.


// VBScript bound to a 1 s cyclic trigger
Dim t_idx, t_state, t_text, t_msgno
t_idx = HMIRuntime.Tags("SOE_NewIndex").Read
t_state = HMIRuntime.Tags("SOE_NewState").Read
t_text = "DI " & t_idx & " -> " & t_state
t_msgno = 100000 + t_idx
HMIRuntime.AlarmLogging.Messages.Add t_msgno, vbCrLf & t_text, 0

For TIA Portal / WinCC Professional (V16–V18), the equivalent is the HMIRuntime.Alarm .NET API. See the WinCC Professional scripting manual for the C# overloads.

Time-Stamp Resolution and OB40 Latency

Source of jitter Typical Worst case Mitigation
DI module input filter 1.2–3 ms 3 ms Configure SM 321 input filter to 0.5 ms (0.5 ms hardware debounce)
OB1 cycle time at 700 I/O 8–12 ms 20 ms (with 100% I/O update) Switch update to partial process image (PII 1–9) and call FC 100 from OB40 only
OB40 hardware interrupt dispatch 100 µs 500 µs Keep OB40 short; do not call SFC 1 from OB40 — it may take 200 µs
CP / MPI transfer latency to WinCC 5–10 ms 30 ms (MPI 187.5 kbit/s) Use TCP/IP via CP 343-1 Lean; limit shadow-DB to 4 KB to fit 100 ms cycle
Resolution budget: With SM 321 input filter 0.5 ms, OB1 cycle 10 ms, and TCP/IP transfer 10 ms, the worst-case SOE timestamp error vs the true electrical edge is 0.5 + 10 + 10 = ~20 ms. This is acceptable for SCADA chronological event recording per IEC 61850 Type 1 timing class (1 ms) only with additional hardware timestamping; for IEC 60870-5-103 and DNP3 sequence-of-events class, 20 ms is sufficient for the standard 10 ms class.

Edge Cases and Field-Proven Caveats

  • Burst overruns: If 100 DIs flip in a single 10 ms scan, FC 100 records 100 entries before WinCC can drain. The ring buffer absorbs this, but the overflow flag latches. Have the HMI alarm on the flag and force a manual acknowledge.
  • DATE_AND_TIME wraparound: DATE_AND_TIME is encoded as BCD and the century byte is the high byte of the year. SFC 1 always returns the year in the range 1990–2089; do not decode it as a raw byte or you will see the year 2089 for a system clocked in 2025.
  • OB40 module removal: If the DI module is removed/reinserted, the previous-image DB (DB 900) holds stale bits. Initialize DB 900 with the current PIW in OB100 (startup) to avoid a 700-event storm on the first scan.
  • WinCC tag count limits: WinCC V7.4 limits a single channel to ~8 K tags. For 700 DIs plus the shadow tags (head, tail, overflow, plus shadow-DB as a 4 KB blob), use the Tag Multiplexing feature: define one 64 KB raw tag and re-map logical subranges with calculated field names.
  • CPU clock drift: Standard 315-2DP has no battery-backed RTC by default on 6ES7 315-2AF03 – add a backup battery or a CP with SIMATIC time to keep the clock alive across power cycles.

Verification Procedure

  1. In STEP 7 PLCSIM, create a DB instance of DB 1000 and force specific bits in PIW 0–43. Observe that head advances and the corresponding UDT entries populate with the PLCSIM clock.
  2. In WinCC online tag diagnostics, watch the head and tail tags. The delta should never exceed 4095 and the overflow bit should remain 0 under normal load.
  3. Use the AlarmControl test mode. Force a new edge and verify that a single SOE message appears with the correct process values and that the timestamp matches the WinCC computer clock within the 20 ms resolution budget.
  4. Force a sustained burst (set 200 bits in PIW simultaneously) and confirm the overflow flag latches, the loss counter increments, and WinCC raises the SOE_Overflow operator message.
  5. Power-cycle the WinCC station while the PLC keeps running. On restart, WinCC should re-acquire the tail from the current head and download the backlog. Verify the chronological view is complete.

Troubleshooting Matrix

Symptom Likely cause Diagnostic step Fix
Head does not advance when DIs change PIW mapped to PII wrong / module on wrong slot STEP 7 › HW Config › Inputs Re-order address ranges; verify DI start address
Head advances but timestamps are all 0 SFC 1 READ_CLK not executed CPU diagnostic buffer Call READ_CLK from FC 100; check return code
SOE messages in WinCC show wrong time OS time zone / DST not set to UTC Control Panel › Time Zone Set Windows TZ = UTC, let WinCC show local; per 7604251
Overflow latches immediately WinCC never reads tail; tail stuck at 0 WinCC tag diagnostics on tail Update tail with a WinCC script or use a 2nd PLC for handshake
Timestamp off by exactly 1 hour in spring/autumn DST flag in DATE_AND_TIME not respected by WinCC Compare CPU time vs WinCC time Run CPU in UTC, set WinCC TZ = UTC, see Siemens 7604251
Only first 40 events captured per scan Hit ALARM_S instance limit on a different code path CPU buffer — search "ALARM_S" Disable any other ALARM_S blocks; we are using FC 100 only
Chronological view shows events out of order OB40 dispatching order varies Check OB40 priority and OB1 nesting Add a 1 ms TIME_TCK discriminator to UDT 10 and sort in WinCC

Standards Cross-Reference

  • IEC 61850-5 — Type 1 timing class requires 1 ms synchronisation. The software approach documented here does not meet Type 1; it meets Type 4 (10 ms) which is the typical SCADA requirement.
  • IEC 60870-5-103 — Class 1 (10 ms) sequence-of-events, achievable with the present design if the SM 321 filter is set to 0.5 ms and OB40 latency is below 1 ms.
  • IEEE C37.118 — Synchrophasor timing; not applicable to a 315-2DP SOE buffer.

FAQ

Can a S7-315-2DP handle 700 time-stamped digital inputs at all?

Yes, but not via the standard ALARM_S/ALARM_8 blocks: the firmware limit is 40 concurrent instances. Use a polled ring-buffer DB (FC 100 → DB 1000 in this article) that captures all 700 DIs in OB1 or OB40 and writes a UDT 10 entry per edge; the timestamp resolution is then bounded by OB1 cycle time plus DI filter, typically 10–20 ms total.

What timestamp resolution can I realistically achieve on a 315-2DP?

With a 0.5 ms SM 321 input filter, a 10 ms OB1 cycle, and OB40 dispatch for the first edge, you will see ~20 ms worst-case error versus the actual electrical transition. For sub-millisecond SOE recording you need an S7-400 with an MCP/FM 350 module, or an ET 200SP TM (Time stamping) submodule.

How do I avoid the 1-hour DST error in WinCC chronological messages?

Run the CPU in UTC (no DST), set the WinCC computer's time zone to UTC, and let the operator client perform the local conversion. Siemens document 7604251 explains that the AS time stamp carries no zone or DST information, so all localisation must be done in the SCADA layer.

Does WinCC need a special option to read the SOE DB?

No special option. The WinCC tag manager plus Alarm Logging with the Chronological messaging property and Time stamp from AS enabled is sufficient. The S7 connection (PROFIBUS or TCP/IP via the CP 343-1 Lean) is the same channel you use for cyclic I/O.

How is the buffer protected against WinCC downtime?

The ring depth (4096 entries × ~20 ms worst-case event spacing) gives roughly 80 s of buffering at 50 events/s. If WinCC stays offline longer than that, the overflow flag latches and the loss counter increments. The recommended response is a WinCC startup routine that sets tail := head on initial connect to discard the backlog and immediately log a system message.

Back to blog