Generating 1-Second Clock Pulses in Siemens S7-300/S7-400 PLCs

David Krause13 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

Periodic clock pulses (clock generators, blink relays, or free-running flags) are a foundational building block in every PLC program. They drive runtime tracking, heartbeat monitoring, toggle logic, watchdog supervision, and time-slot scheduling. On Siemens S7-300 and S7-400 controllers, several production-grade methods exist for producing a 1-Hz impulse without external hardware:

  1. CPU clock memory bits (system feature, zero code)
  2. OB35 (100 ms time-of-day interrupt) counter – divides 100 ms by 10 in user code
  3. IEC/S5 timer pair (on-delay + off-delay self-resetting pair)
  4. OSCAT library blocks CLK_N and CLK_DIV

This reference walks through each method, the corresponding STL and SCL code, the timing accuracy each method provides, and the failure modes that surface when OB1 cycle time grows past the pulse period.

Note on terminology: Siemens documentation uses clock memory for system-generated periodic bits, while engineers commonly call the same feature clock flags, heartbeat bits, or merker pulses. The German original is Taktmerker. All three terms refer to the same hardware feature.

Method 1 – CPU Clock Memory Bits (Recommended Default)

The fastest and most accurate method requires no application code. Every S7-300 and S7-400 CPU supports a configurable set of clock memory bits (Clock Memory) that the operating system toggles at fixed frequencies independent of OB1 cycle time.

Hardware configuration

  1. Open the S7 station in SIMATIC Manager > HW Config.
  2. Open the CPU properties (double-click the CPU slot).
  3. Select the "Cycle/Clock Memory" tab.
  4. Check "Clock memory" and enter the starting byte address (default MB0, but choose an unused range to avoid data conflicts – MB100 is common in plant code).
  5. The default bit frequencies are: bit 0 = 0.1 s, bit 1 = 0.2 s, bit 2 = 0.5 s, bit 3 = 1 s, bit 4 = 2 s, bit 5 = 4 s, bit 6 = 8 s, bit 7 = 16 s.
  6. Download the hardware configuration to the CPU.

Usage in STL

      A     M 100.3      // 1.0 s clock bit
      FP    M 110.0      // positive edge memory (edge flag)
      =     M 110.1      // one-shot pulse, 1 OB1 cycle wide

Bit M100.3 produces a 50% duty-cycle square wave with a 1-second period. Combined with FP (Flankenmerker positive), the result M110.1 is a single-scan TRUE pulse triggered on every rising edge – exactly the "1 s impulse" requested.

Available frequency base is fully documented in the SIMATIC S7-300 CPU 31xC and CPU 31x Reference Manual and the S7-400 Automation System System Manual. Refer to the section "Clock memory" in either manual for the byte allocation rules.

Reserved memory: The entire byte used for clock memory must not be used elsewhere in the program. Even bits that are not toggled by the operating system are still considered reserved.

Method 2 – OB35 Time Interrupt with Counter (CPU-Independent Pulse Generator)

When the application requires a pulse not derived from the clock-memory feature – for example, when MB0 is already consumed by other code, or when a programmable period is needed – the OB35 (100 ms cyclic interrupt) provides a deterministic time base independent of OB1 scan time. OB35 is supported across the entire S7-300 (CPU 312 and above) and S7-400 families.

Hardware configuration

  1. In HW Config, open the CPU properties and select the "Time-of-Day Interrupts" tab.
  2. Set OB35 execution to 100 ms (the default; do not increase above 1 s if the goal is a 1 Hz output pulse).
  3. Ensure OB35 is loaded into the CPU project. The block must exist physically – if the project is compiled without OB35, the CPU enters STOP on the first missing-OB call.

STL implementation in OB35

// OB35 – 100 ms time-of-day interrupt
      L     "DB_Pulse".Cnt_100ms      // INT counter, retentive
      +     1
      T     "DB_Pulse".Cnt_100ms

STL implementation in OB1

// OB1 – application cycle
      A(
      L     "DB_Pulse".Cnt_100ms
      L     10                         // 10 × 100 ms = 1 s
      >=I
      )
      FP    M 120.0                    // positive edge memory
      =     "One_Sec_Pulse"            // 1-scan TRUE pulse per second

      A     "One_Sec_Pulse"
      JCN   _001
      L     0
      T     "DB_Pulse".Cnt_100ms       // reset counter
_001: NOP   0

The counter increments inside OB35 at exactly 10 Hz. OB1 evaluates the comparison "counter ≥ 10" and generates one positive-edge pulse per second. The reset inside the JCN branch guarantees a clean re-arm on the next OB35 tick.

OB35 timing parameters are defined in the SIMATIC S7-300 CPU 31x Reference Manual, section "Cyclic interrupt OBs". The OB priority class, run-time, and phase offset are all settable in HW Config.

Why use OB35 instead of OB1? If OB1 scan time drifts above 100 ms, any pulse generator implemented entirely in OB1 will accumulate jitter. OB35 fires deterministically regardless of OB1's execution time, so the 1 s pulse remains accurate even under heavy CPU load. This is the technique recommended for production systems where OB1 cycle times exceed 200 ms.

Method 3 – IEC/S5 Timer Pair (Self-Resetting On/Off-Delay)

For stand-alone applications that need a 1 s pulse without modifying the hardware configuration, a pair of timers can generate an arbitrarily long on-pulse followed by an off-period, both programmable. This method does not require OB35.

STL implementation

      AN    T 2                         // start T1 when T2 is not active
      L     S5T#5S                      // on-time of T1 (= 5 s in this example)
      SD    T 1                         // on-delay timer
      NOP   0
      NOP   0
      NOP   0
      A     T 1
      L     S5T#5S                      // off-time (= 5 s)
      SF    T 2                         // off-delay timer

// Use T1 directly as the pulse, or transfer to memory:
      A     T 1
      =     M 200.0                     // "One_Sec_Pulse" equivalent

By setting T1 and T2 to the same value, the period is 2 × T1. T1 itself is high for T1 seconds, giving a 50% duty cycle. Smaller pulse widths can be created by transferring T1 to a memory bit and applying FP edge detection in OB1.

S5T# time format

Constant Value
S5T#1S 1 second
S5T#500MS 500 ms
S5T#2M 2 minutes
S5T#1H30M 1 hour 30 minutes

The S5T# format supports 10 ms to 9990 s in 10 ms steps. The format is fully described in the STEP 7 STL/SCL Manual, section "Time constants".

Drawback: The pulse duration equals the on-delay of T1, so a 1-second pulse requires T1 = 1 s and T2 = 1 s, giving a 2-second period. To produce a 1 Hz signal with 50% duty cycle, set T1 = T2 = 500 ms and apply FP edge detection in OB1. Use the OB35-based method instead for sub-100 ms accuracy.

Method 4 – OSCAT Library: CLK_N and CLK_DIV

The OSCAT (Open Source Community for Automation Technology) library provides pre-built clock functions. Two blocks are particularly relevant:

  • CLK_N – produces a pulse every 2^N milliseconds, with N = 0 → 1 ms, N = 1 → 2 ms, N = 2 → 4 ms, … N = 10 → 1024 ms.
  • CLK_DIV – divides a clock input by 1, 2, 4, 8, 16, 32, 64, 128, or 256. Cascade CLK_N → CLK_DIV to reach any desired frequency.

Cascading CLK_N + CLK_DIV for 1 Hz output

CLK_N with N = 9 (512 ms) followed by CLK_DIV with a divisor of 2 will not yield exactly 1 Hz; the correct cascade is:

  1. CLK_N with N = 6 → 64 ms period
  2. CLK_DIV with DIV = 16 → 64 ms × 16 = 1024 ms ≈ 1 s

For an exact 1 s pulse, two CLK_N blocks at N=5 (32 ms) chained with a 16-stage counter, or a single CLK_N at higher N followed by a user-side counter, is the cleanest approach. The OSCAT documentation describes both functions in detail.

Library installation: OSCAT blocks are provided as STEP 7 source files (SCL). Import the relevant FBs/FCs from the OSCAT website into the S7 program, declare an instance DB for the FB, and wire the inputs/outputs in OB1 or OB35.

Comparison of Methods

Method Accuracy Code Size OB1 Load Period Range Recommended For
CPU clock memory ±0.1 % (OS-driven) 0 lines Negligible 100 ms – 16 s (8 fixed freqs) Default – nearly all S7 programs
OB35 + counter ±1 OB35 tick (±100 ms worst case) ~10 lines + DB Low Programmable, 100 ms steps Long OB1 scan times, high jitter rejection
IEC/S5 timer pair ±1 scan ~6 lines None in OB35 10 ms – 9990 s Stand-alone pulse, no OB35
OSCAT CLK_N + CLK_DIV ±1 ms 2 FB calls Negligible 1 ms – any multiple Reusable, parameterised frequency

Positive Edge Detection (FP) in STL

All four methods produce a square wave, but most applications need a single-scan TRUE pulse on each rising edge. The STL instruction FP <edge memory> performs positive-edge detection: the result is TRUE for exactly one OB1 cycle on the transition from 0 to 1 of the input.

      A     M 100.3      // 1 s clock bit
      FP    M 110.0      // edge memory bit – MUST be retentive-free
      =     M 110.1      // single-scan pulse
Edge memory requirements: The edge memory bit (M 110.0 in the example) must be in a non-retentive area and must be initialised to 0. The instruction reads the previous state of the bit and compares it to the current input. If the previous state is undefined (first scan after restart), the pulse may be triggered erroneously. Force the bit to 0 in OB100 (restart OB) to prevent this.

Startup reset block (OB100)

      SET
      R     M 110.0      // clear edge memory
      R     M 110.1      // clear pulse output
      L     0
      T     "DB_Pulse".Cnt_100ms

Application Patterns

Pattern A – Toggle flip-flop (1 Hz blink)

      A     "One_Sec_Pulse"
      FP    M 121.0
      AN    M 121.1
      =     M 121.1
      A     M 121.1
      FP    M 121.0      // re-use with care; or use a separate edge bit

A simpler form uses XOR:

      A     "One_Sec_Pulse"
      FP    M 121.0
      X     M 121.1
      =     M 121.1      // toggles on every "One_Sec_Pulse"

Pattern B – Watchdog supervision

Use the 1 s pulse to reset a runtime counter; if the counter ever reaches a limit, the program has stopped cycling.

      A     "One_Sec_Pulse"
      JC    _reset
      L     "Watch_Sec"
      +     1
      T     "Watch_Sec"
      L     30
      >I
      S     "PLC_Fault"               // set fault if no pulse for 30 s
_010: SPA   _020
_reset: L     0
      T     "Watch_Sec"
_020: NOP   0

Pattern C – Time-slot scheduler

Use the 1 s pulse to advance a slot pointer modulo N. Each OB1 scan reads the slot pointer to dispatch the corresponding task. This is the foundation of cyclic executive scheduling on S7-300/400.

Verification Procedure

  1. Open the S7 program online in STEP 7 and select the relevant block (OB1, OB35, or the clock-memory byte).
  2. Trigger Monitor/Modify on the pulse output bit (e.g. M110.1).
  3. Read the bit every 100 ms. It should toggle TRUE exactly once per second, and the duration of each TRUE state should equal exactly one OB1 cycle.
  4. Use a stopwatch or the CPU online time stamp to measure 60 consecutive pulses. Elapsed real time should equal 60 s ± 1 OB1 cycle.
  5. Force OB1 to a 1.5 s cycle (heavy program load) and re-verify. The clock-memory method and OB35-counter method should remain unaffected; the timer-pair method may drift.
  6. Trigger a STOP→RUN transition (restart) and verify the edge memory is cleared. Use OB100 reset to avoid the spurious first-scan pulse.

Troubleshooting Matrix

Symptom Probable Cause Corrective Action
No pulse on clock-memory bit Clock memory not enabled in HW Config, or MB100 is overwritten by other code Open CPU properties > Cycle/Clock Memory tab; verify the start byte and check the program for any write access to the reserved byte
CPU goes to STOP OB35 referenced in HW Config but not loaded in the S7 program Insert OB35 in the project, add the increment code, and download
Counter never reaches 10 OB35 not firing (priority class issue) or counter variable is being reset elsewhere Use Monitor to verify OB35 execution in the CPU diagnostic buffer; check for writes to the counter from OB1
Pulse fires twice on startup Edge memory bit M 110.0 undefined at restart Add OB100 to reset the edge bit and the counter
Pulse period drifts (timer pair method) OB1 cycle time exceeds the off-delay of T2 Switch to OB35 counter method or use the clock memory
OB35 call time shown in diagnostic buffer > period OB35 priority is being starved by higher-priority OBs (OB80, OB121, etc.) Check diagnostic buffer for OB80/OB121 errors; reduce OB35 workload or increase its priority class
OSCAT block does not compile Library version mismatch with STEP 7 version Download the matching OSCAT release for the STEP 7 version in use (V5.5, V5.6, TIA V15–V18)

Hardware & Firmware Considerations

OB35 is supported on every S7-300 CPU starting with the 312 and on every S7-400 CPU. Clock memory support is universal on both families. The S7-300 CPU 312 IFM and the early CPU 312C variants are limited to a 2-byte clock-memory area; later CPUs (315-2 PN/DP, 317, 319, and the entire S7-400 range) accept the full 8-bit pattern. Refer to the S7-300 CPU 31x Reference Manual for the full list of cyclic interrupt OBs and their per-CPU support matrix.

For S7-1200 and S7-1500 controllers, the same logic applies but the implementation lives in TIA Portal. The S7-1500 System Manual documents the equivalent cyclic interrupt OB (OB30–OB38 in TIA terminology) and the new Clock_Generator system clock.

Best-Practice Recommendations

  • Use CPU clock memory for the default 1 s pulse. It is OS-driven, immune to OB1 scan drift, and consumes zero application code.
  • Use the OB35 counter method only when the period is non-standard (for example 250 ms, 5 s, or 30 s) or when the clock-memory byte is already used by another system function.
  • Use the timer pair only for very long periods (minutes, hours) and where the duty cycle accuracy is non-critical.
  • Use the OSCAT library when reusable, parameterised clock functions are needed across many programs.
  • Always clear the edge memory in OB100 to prevent spurious first-scan pulses.
  • Document the clock-memory byte in the program header so that future programmers do not overwrite it.
  • Never use the same edge memory bit for two different FP instructions – each edge detection requires its own dedicated bit.

What is the simplest way to generate a 1-second pulse in a Siemens S7-300/400 PLC?

Enable the CPU clock memory in HW Config (CPU properties > Cycle/Clock Memory tab) and use bit 3 of the configured byte (for example M100.3). It toggles with a 1 s period at 50% duty cycle, driven by the CPU operating system with no application code required.

Why is my OB35-based pulse inaccurate when OB1 scan time increases?

OB35 fires deterministically every 100 ms regardless of OB1 cycle time, so the OB35 method is actually more accurate under heavy OB1 load. If you see drift, check the diagnostic buffer for OB80 (time error) or OB121 (programming error) – these indicate the OB35 run-time exceeded its scheduled window.

How do I produce a pulse with a non-standard period, like 250 ms or 5 s?

Use the OB35 counter method. Set OB35 to 100 ms and count down from 3 (for 300 ms) or 50 (for 5 s) inside OB35, then perform the comparison and FP edge in OB1. The clock memory feature only provides the 8 fixed frequencies 0.1 s through 16 s.

What is the S5T# time format and how is it used?

S5T# is a legacy Siemens time constant format: the prefix S5T# followed by a value with units S (seconds), M (minutes), H (hours), MS (milliseconds). Example: S5T#500MS = 500 ms, S5T#2M30S = 2 min 30 s. It is used with legacy timers SD, SF, SP, SE, SS, SI.

What causes a spurious first-scan pulse on restart, and how do I prevent it?

The FP (positive edge) instruction reads the previous state of its edge memory bit. After a STOP→RUN transition, the bit is undefined and may produce a false rising edge. Insert OB100 (restart OB) in the program and reset the edge memory bit to 0 there, ensuring the next FP evaluation starts from a clean state.

Back to blog