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:
- CPU clock memory bits (system feature, zero code)
- OB35 (100 ms time-of-day interrupt) counter – divides 100 ms by 10 in user code
- IEC/S5 timer pair (on-delay + off-delay self-resetting pair)
- 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.
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
- Open the S7 station in SIMATIC Manager > HW Config.
- Open the CPU properties (double-click the CPU slot).
- Select the "Cycle/Clock Memory" tab.
- Check "Clock memory" and enter the starting byte address (default
MB0, but choose an unused range to avoid data conflicts –MB100is common in plant code). - 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.
- 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.
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
- In HW Config, open the CPU properties and select the "Time-of-Day Interrupts" tab.
- Set OB35 execution to 100 ms (the default; do not increase above 1 s if the goal is a 1 Hz output pulse).
- 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.
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".
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:
- CLK_N with N = 6 → 64 ms period
- 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.
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
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
- Open the S7 program online in STEP 7 and select the relevant block (OB1, OB35, or the clock-memory byte).
- Trigger Monitor/Modify on the pulse output bit (e.g.
M110.1). - 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.
- Use a stopwatch or the CPU online time stamp to measure 60 consecutive pulses. Elapsed real time should equal 60 s ± 1 OB1 cycle.
- 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.
- 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.