Resolving Siemens S7 STL Timer Pulse Chain M1.0 Set Failure

David Krause14 min read
HMI ProgrammingSiemensTroubleshooting
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

Problem Definition

The classic failure mode on a Siemens SIMATIC S7-300 or S7-400 PLC is an STL pulse-generator ladder that uses two on-delay timers (T58 and T59) chained to produce a repeating 60-second blink. The programmer observes that the output bit M1.0 is never energized, even though the timers are visibly running in the VAT watch table. The phenomenon is not a defect in the CPU, the timers, or the S5T# time format — it is a scan-order defect in the Statement List (STL) logic. Reordering the two networks restores the bit immediately.

The minimal, symptomatic code looks like this in FC2:


NETWORK 1
  AN    T 59               // T59 NOT active
  L     S5T#30S            // load 30 s time value
  SD    T 58               // start on-delay T58
  NOP   0
  NOP   0
  NOP   0
  NOP   0

NETWORK 2
  A     T 58               // T58 active
  L     S5T#30S
  SD    T 59               // start on-delay T59
  NOP   0
  NOP   0
  NOP   0
  A     T 59               // read T59 status
  S     M 1.0              // set M1.0

With this code, M1.0 remains permanently FALSE in every online observation. The block compiles, downloads, runs OB1 without diagnostic entry, and shows T58 and T59 toggling correctly in the VAT — but the set coil for M1.0 never fires.

Root Cause Analysis

The defect is the relative position of the instruction that reads the timer status against the instruction that starts the timer in the same scan cycle. The on-delay instruction SD in STEP 7 STL is an assignment-style statement: it loads the time value from ACCU1, evaluates the RLO at its input, and arms the timer. The signal state of the timer word (T58 / T59) is updated by the operating system on a fixed time-base tick — every 10 ms for the 10 ms, 100 ms, 1 s, and 10 s time bases of the S5T# syntax — and is not propagated into the user program until the next read of that timer word or the start of the next OB1 cycle.

What happens scan by scan in the buggy version:

  1. Cycle n (T59 was 0 in the previous cycle): Network 1 evaluates AN T59 = TRUE, loads 30 s into ACCU1, executes SD T58. T58 begins timing. Network 2 evaluates A T58 = FALSE (T58 was 0 at the start of the cycle; the SD update has not been sampled yet by the operating system for read-back), so the RLO into the SD T59 instruction is FALSE; T59 is not re-armed. The trailing A T59 therefore reads 0, and S M 1.0 stores a 0 into M1.0.
  2. Cycle n + 1: T58 has now elapsed and reports TRUE. Network 1 sees AN T59 = TRUE, re-arms T58 for another 30 s. Network 2 sees A T58 = TRUE, loads 30 s and executes SD T59. The timer is now started, but the RLO into SD T59 is consumed by the SD; the next instruction A T59 reads the timer word before the OS has propagated the new run-time state. The set coil for M1.0 again sees T59 = 0.
  3. Cycle n + 2 onward: T58 re-arms, T59's 30 s elapses during cycle n + 2's runtime. By the time Network 2's A T59 executes, T59 reports TRUE and M1.0 is finally set — but on the very next cycle, Network 1's AN T59 is now FALSE so T58 is not re-armed, and the pulse chain collapses.

The takeaway: in the S7-300/400 execution model, the S5 timer outputs are not synchronously visible at the point of the SD instruction. You must read the timer before you start it, or in a network that runs strictly after the timer start has been sampled by the OS at a 10 ms boundary.

Anatomy of the Original Code

Network Instruction RLO effect Timer reaction
1 AN T 59 TRUE when T59 = 0 Feeds enable input of SD T58
1 L S5T#30S Loads 30 s into ACCU1 Time value for T58
1 SD T 58 Consumes RLO + ACCU1 Starts T58 if RLO=1
2 A T 58 TRUE when T58 has elapsed Feeds enable of SD T59
2 L S5T#30S Loads 30 s into ACCU1 Time value for T59
2 SD T 59 Consumes RLO + ACCU1 Starts T59 with 30 s preset
2 A T 59 Reads T59 word Drives the set coil for M1.0
2 S M 1.0 Stores 1 in M1.0 if RLO=1 Sets M1.0

The critical dependency is the order of SD T59 and A T59 inside Network 2. STL executes them sequentially, but the operating system only refreshes the T59 word (the bit, the elapsed-time BCD, and the time-base flag) on a 10 ms tick. The instruction immediately following the start cannot observe the new state until that tick has been processed by the OB1 cycle boundary.

The Fixed Network Structure

Two valid fixes exist. The first is to invert the network order so the read happens before the write to the timer:


FUNCTION FC 2 : VOID
TITLE =
VERSION : 0.1
BEGIN
  NETWORK 1                // set M1.0 from T59 first
    A     T 59;
    S     M 1.0;
  NETWORK 2                // then arm T58 from inverted T59
    AN    T 59;
    L     S5T#30S;
    SD    T 58;
  NETWORK 3                // then arm T59 from T58
    A     T 58;
    L     S5T#30S;
    SD    T 59;
END_FUNCTION

The second fix is the canonical Siemens pulse-generator using a single timer with self-reset, which is preferred on production code because it has no scan-order hazard:


NETWORK 1
  A     M 1.0;             // self-holding flip-flop
  AN    T 58;
  S     M 1.0;
NETWORK 2
  A     M 1.0;
  L     S5T#60S;
  SD    T 58;
NETWORK 3
  A     T 58;
  R     M 1.0;             // reset on timer expiry

This pattern is documented in the Siemens S7-300/400 STL and SCL programming reference manuals and is immune to the scan-order trap because only one timer is used and the bit is set on the rising edge before the timer is started.

How S5 Timers Update in S7-300/400

The S5T# syntax describes a time in BCD-coded 16-bit format. STEP 7 maps the time base and the duration to a single word, and the operating system maintains a free-running counter for each time base. For a CPU 315-2 PN/DP, CPU 317-2, or CPU 319-3 the four time bases are 10 ms, 100 ms, 1 s, and 10 s. The on-delay instruction SD decrements the elapsed counter at each tick of the relevant time base; when the elapsed value reaches zero, the timer bit is set in the process-image update at the next OB1 boundary.

Time-base flag (bits 14-13) Resolution Maximum value
00 10 ms 9 s 990 ms
01 100 ms 1 m 39 s 900 ms
10 1 s 16 m 39 s
11 10 s 2 h 46 m 30 s

For S5T#30S the value field is 30 and the time-base field is 10 (1 s base). The internal representation is W#16#0300. The CPU subtracts 1 from the elapsed value at every 1 s tick. After 30 ticks, the bit T58 is set. The set bit is held as long as the SD enable input is TRUE; the moment the enable flips FALSE, the timer is reset to its preset and the bit clears.

Timer Time Base and Resolution

A frequent follow-on question is why the bit looks "late" in the VAT. The answer is the 1 s time base selected by S5T#30S. A 30 s on-delay at a 1 s base can only resolve to the next 1 s boundary, so the bit can transition anywhere inside a 1 s window relative to the expected t = 30 s mark. For sub-second pulse work use S5T#300MS or S5T#30MS (10 ms base) and accept that the resolution is coarser than the duration. The IEC timer functions TP, TON, TOF in the S7-300/400 instruction set give deterministic millisecond resolution if you require it.

Engineering note: The IEC on-delay timer (FB / FC with TON) uses the system clock of the CPU at 1 ms resolution and is recommended for any pulse chain that drives safety-relevant outputs, where the S5T# 1 s base is too coarse for diagnostic purposes.

Step-by-Step Fix Procedure

  1. Open the SIMATIC Manager (or TIA Portal if the project was migrated). Drill into the S7 program and locate the FC containing the T58 / T59 chain — in the source project this is FC2.
  2. Right-click the FC and select Open in STL editor. Switch the view from LAD/FBD to STL with View > STL.
  3. Identify the network that contains SD T 58 and the network that contains SD T 59 plus the trailing A T 59; S M 1.0 set coil.
  4. Move the A T 59; S M 1.0 pair to a new network that runs before the network containing SD T 58. The two read-and-set instructions must execute against a T59 word that has already been updated by a previous cycle.
  5. If you want the safest pattern, replace the entire chain with the single-timer self-reset pulse shown above. Delete T59 from the timer list (PLC > Timer > Clear) and remove its references from all blocks.
  6. Save the FC, recompile the S7 program, and download the blocks to the CPU in RUN-P (or STOP with restart).
  7. Open a VAT (Variable Table) and monitor T58, T59, and M1.0. Toggle the CPU to RUN.

Verification with PLCSIM

PLCSIM is the correct tool to confirm the fix before touching the real CPU. The procedure is:

  1. Start S7-PLCSIM from SIMATIC Manager (Options > Simulate PLC) or from TIA Portal (Online > Simulation > Start). Use PLCSIM V5.4 SP8 or later for STEP 7 V5.6 projects; for TIA Portal V18 and later use PLCSIM V18.
  2. Download the S7 program to the simulated PLC instance (CPU 315-2 PN/DP or CPU 314, any instance works for this logic).
  3. Switch the simulated CPU to RUN. The SF / BF LEDs should be off, and the RUN LED should be solid green.
  4. Open a VAT and add the symbols T58, T59, and M1.0. Set the display format to Binary for all three.
  5. Set the VAT to Monitor / Modify with a trigger on Monitor all and click the green eye icon.
  6. Watch T58 toggle every 30 s and T59 toggle every 30 s offset from T58 by 30 s. M1.0 must be TRUE for the entire interval between T59 rising and T59 falling. If M1.0 stays FALSE, you have not moved the S M 1.0 coil into a network that executes before SD T 58.
  7. Use the Single Scan button in PLCSIM to step OB1 manually and confirm the network order on a per-cycle basis. This is the fastest way to prove the scan-order fix.
Verification tip: In PLCSIM, set the CPU clock to "Time scaling" of 1:10. A 60 s pulse chain then completes in 6 s of real time, letting you confirm the full blink cycle in under a minute.

Diagnostic Procedure

If the symptom persists after the reorder, work through this matrix:

Symptom Likely cause Check / Fix
M1.0 never sets, T58 / T59 run correctly Read-after-write scan-order bug Move S M1.0 ahead of SD T58
M1.0 never sets, T58 / T59 stay 0 Time value zero, wrong time base, or timer not declared Inspect the FC for L S5T#30S payload; check the S7 program timer allocation (PLC > Timer)
M1.0 set, but immediately reset by another block Overlapping access to M1.0 from FC, OB, or system clock memory Search the project for M 1.0 with Overlapping access to memory areas enabled; verify the CPU hardware configuration is not assigning M1.0 to the system clock byte
M1.0 set, but a R M 1.0 somewhere else clears it Reset coil in a different network or cyclic OB Cross-reference the address (Ctrl+F in STEP 7, or Cross-reference in TIA Portal)
M1.0 toggles erratically every scan Set and reset both TRUE in the same cycle Confirm only one network drives M1.0
M1.0 never visible, but a different bit M1.1 / M1.2 is set Symbol mismatch between editor and symbol table Re-import the symbol table from the S7 program

The System Clock Memory bit in the CPU hardware configuration is a frequent silent cause: if a check-box has been set in HW Config under CPU Properties > Cycle/Clock Memory and the clock-memory byte is set to MB1, then MB1 (M1.0 through M1.7) is overwritten by the OS each cycle with a periodic pattern, and any user logic writing to those bits is overwritten. Clear the clock-memory byte assignment or move M1.0 to a byte that is not reserved by the CPU.

Common Variants and Edge Cases

Edge case 1 — IEC timers in TIA Portal. The same scan-order trap exists in TIA Portal SCL and FBD if the user wires a TON output back to its own enable. The IEC TP (pulse) block is the correct replacement for the two-SD pattern; it generates a fixed-duration pulse on a rising edge with no scan-order hazard. Use TP (SFB3 / FB) for any pulse that drives a safety-related function.

Edge case 2 — Hardware interrupts. If the T58 / T59 chain is started from OB40 (hardware interrupt), the scan-order trap is amplified because OB40 runs to completion before the OS has a chance to refresh the timer words. The read of T59 inside the same OB40 will always return the value sampled at the OB40 entry. Fix: read T59, set M1.0, and only then start the next SD.

Edge case 3 — Restart / OB100. After a warm restart the timer words are zeroed by the OS. The first scan of OB1 will see T59 = 0, Network 1 will arm T58, Network 2 will see T58 = 0, and T59 will not be re-armed. The first M1.0 set will only happen on the second pulse cycle. If M1.0 must be TRUE immediately after restart, preset it in OB100 with SET ; SAVE ; CLR ; = M 1.0 (or in LAD with an Initial Set contact).

Edge case 4 — Time base rollover. An on-delay timer with a preset at the upper end of its time base (for example S5T#9990S in the 10 s base) can wrap to zero and produce an unexpected second transition. Use a longer time base or an IEC timer for any duration near the limit.

Why does the timer status read FALSE immediately after the SD instruction in the same network?

The S5 timer instructions in the S7-300/400 update the timer word at the next 10 ms (or 100 ms / 1 s / 10 s) tick of the relevant time base. The operating system does not propagate the new timer state into the user-visible process image until the next OB1 cycle boundary. Reading the timer bit in the same STL instruction stream as the SD will always return the pre-update value.

How do I know whether my CPU uses the 10 ms or 100 ms time base for S5T#?

The time base is encoded in bits 14 and 13 of the BCD word and is selected by STEP 7 from the duration value: ≤ 9 s 990 ms uses the 10 ms base, ≤ 1 m 39 s 900 ms uses 100 ms, ≤ 16 m 39 s uses 1 s, and up to 2 h 46 m 30 s uses 10 s. S5T#30S selects the 1 s base. You can read the base in a VAT by switching the display format to Hex on the timer word.

Can the IEC TP pulse block replace my T58 / T59 chain on S7-300/400?

Yes. The TP (SFB3) block in the STEP 7 standard library generates a fixed-duration pulse from a rising edge and resolves to the CPU's 1 ms system clock. It eliminates the scan-order trap entirely and is the recommended pattern for any new code. For S7-300 use SFB3 / SFB4 / SFB5 (TP / TON / TOF) from the Standard Library; for S7-400 the same blocks are available.

Is M1.0 reserved by the system clock memory feature?

It can be. If CPU Properties > Cycle/Clock Memory in HW Config has the clock-memory check-box enabled and the clock byte is set to MB1, then bits M1.0 through M1.7 are driven by the OS as periodic clock signals and overwrite any user value. Move the user bit to a free byte (for example M2.0) or disable the clock-memory feature.

How do I step through the FC instruction by instruction in PLCSIM to prove the scan order?

Start PLCSIM, download the program, switch the CPU to RUN, then use the Single Scan button in the PLCSIM toolbar (or the Step command in STEP 7 with the program status open). The active instruction is highlighted in the STL editor and the timer word, RLO, ACCU1, and ACCU2 are visible in the online monitor. This is the fastest way to confirm that SD T 59 executes before A T 59 and that the read returns the pre-update value.

Back to blog