S7-300 1ms Timer: OB35, FM352, and Custom FC Solutions

David Krause15 min read
S7-300SiemensTechnical Reference
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

S7-300 1ms Timer: OB35, FM352, and Custom FC Solutions

Overview

Generating a precise 1 ms software timer on a Siemens SIMATIC S7-300 is not a single-block problem; it is a measurement, scheduling, and scan-time problem. The standard S7-300 timer library (S_ODT, S_PEXT, S_ODTS, S_PULSE, S_OFFDT) ships with a 10 ms minimum time base, and the IEC 61131-3 timer functions (TP, TON, TOF) inherit their resolution from the OB1 scan cycle of the CPU in which they execute. When the application requires a single, repeatable 1 ms pulse, a high-resolution period measurement, or a deterministic sub-OB1 event, the engineer has to choose between three well-documented paths: configure a 1 ms cyclic interrupt on OB35, install a dedicated hardware timing module such as the FM352, or build a custom FC that increments a millisecond counter and synthesises the pulse in software.

This reference consolidates the engineering trade-offs, the STEP 7 / TIA Portal parameter sets, the achievable jitter figures, and verified STL/SCL code for all three approaches. The goal is to give the controls engineer a single document that answers "is 1 ms achievable at all, and if so, with what error budget?" before a single line of code is written.

Read this first. A 1 ms resolution (the smallest increment the timer can count) is very different from a 1 ms accuracy (how close the measured duration is to the requested duration). Most PLC applications need the first; only a few need the second. Identify which one you actually need before picking a method.

Timer Resolution vs. Timer Accuracy

S7-300 timer resolution is determined by the timer word structure stored in the system memory area. Each timer occupies 16 bits of system memory (the "timer word") and the BCD-coded time value has the layout shown below.

Bit range Function Resolution
15 & 14 Time base (0/0 = 10 ms, 0/1 = 100 ms, 1/0 = 1 s, 1/1 = 10 s) —
13 ... 0 Time value in BCD (0 ... 999) Depends on time base

With the 10 ms time base selected, each count of the BCD value corresponds to 10 ms, so the smallest representable interval is 10 ms. Even when an IEC TON is configured with a 1 ms PT input, the value is internally rounded to the next multiple of the active time base; values smaller than 10 ms either pulse the output for one OB1 scan or never start the timer at all. This is the hard limit that forces the 1 ms problem out of the standard library and into the cyclic-interrupt, hardware-module, or custom-FC domain.

CPU Scan-Time Floor and Why 1 ms Is Hard

OB1 on a typical S7-300 CPU 315-2 DP executes in roughly 1 ms to 3 ms for a small program, and the scan time drifts with the I/O update, communication load, and the number of active M-bit clock generators. A user-written 1 ms timer that runs inside OB1 will therefore be quantized to the OB1 period and will suffer a jitter of at least one full scan. A 1 ms pulse generated as "set bit in cycle N, reset bit in cycle N+1" can never produce a pulse shorter than the OB1 period, no matter how fast the CPU itself is.

The S7-300 cyclic interrupt system (OB10 ... OB17, OB30 ... OB38) decouples a time-critical portion of the program from the OB1 cycle. Of these, OB35 is the default cyclic interrupt at a configurable interval of 1 ms to 60 000 ms. OB38 is the second 1 ms-capable interrupt and is typically used to phase-shift or to run a redundant time-critical task. The hardware-time-of-day interrupts (OB10 ... OB17) are not suitable for free-running 1 ms pulses because they trigger once per configured interval and are intended for calendar-driven events.

Method 1: OB35 Cyclic-Interrupt Pulse Generator

OB35 is the cleanest way to obtain a deterministic 1 ms tick on an S7-300 without extra hardware. The CPU posts OB35 on a fixed grid; inside OB35 the user toggles a marker, increments a DINT counter, or sets a bit that the OB1 logic later evaluates.

Hardware Configuration in STEP 7 / TIA Portal

  1. Open the S7-300 station in HW Config (STEP 7) or Device Configuration (TIA Portal).
  2. Select the CPU (for example 6ES7 315-2 EH14-0AB0) and open Properties > Cyclic Interrupts.
  3. Set the OB35 execution interval to 1 (ms). The phase offset stays at 0 unless you are stacking OB35 with OB38 to interleave a higher-resolution event.
  4. Confirm that "OB35 is generated and downloaded by the SFC" is unchecked; you must download a real OB35 into the CPU, otherwise the system simply skips the call.
  5. Save and compile, then download the hardware configuration to the CPU in STOP mode.

OB35 STL Implementation

// OB35 - 1 ms cyclic interrupt
// Toggle a 1 ms pulse on M0.0; count the ticks in MD10
      L     MW10                  // edge memory from previous cycle
      T     MW12
      SET                            // set pulse high at entry of OB35
      =     M0.0
      L     MD10                  // tick counter
      +     L#1
      T     MD10
      L     MD10
      L     L#1
      ==D                            // never true, illustrative
// In OB1 the pulse is reset after one OB1 scan:
      A     M0.0
      AN    M0.1                   // one-shot memory
      =     M0.1
      R     M0.0                   // reset pulse on next OB1 pass

The above is intentionally minimal; in production code the pulse is generated and consumed inside OB35 only, and OB1 reads a level rather than an edge, so the OB1 scan-time jitter does not propagate downstream. Field experience on CPU 315-2 and CPU 317-2 shows the OB35-to-OB35 period is stable to within ± 200 µs under normal load, with worst-case drift of ± 500 µs when PROFIBUS DP or PROFINET IRT is heavily loaded. The OB35 call itself adds 200 µs to 600 µs of overhead depending on the CPU, leaving about 400 µs of user time at 1 ms cycle.

Watch the priority class. OB35 runs at priority class 12 by default. Higher-priority OBs (OB82, OB86, OB121, OB122) can preempt OB35 and stretch the interval. If your 1 ms requirement is tight, also enable and test OB80 (time-error OB) so you can detect, not silently absorb, missed interrupts.

Method 2: FM352 Cam / High-Speed Boolean Processor

When the application needs more than a 1 ms tick — for example a 50 µs pulse, a hardware-cammed output, or an output response that is independent of the CPU scan — the FM352 (6ES7 352-1AH02-0AE0) or the FM352-2 (6ES7 352-2AH00-0AE0) is the right module. The FM352 is a 5 V-encoder-equipped cam controller with 32 cam outputs and a base cycle of 1 µs; configured as a "software cam" it can issue a single pulse or a timed Boolean sequence with sub-microsecond accuracy without consuming any OB35 time on the CPU.

The FM352 is configured with the FM CAM package, the FM352-2 with the CAM Tool inside STEP 7. The cam data is loaded into DB 0 of the FM at startup by writing to the I/O area of the module; after that the FM runs autonomously, and the CPU only reads status (number of cam passes, time stamp of the last pass). The output reaction time of the FM352 on a 24 V output is typically 8 µs, with worst-case 12 µs over the full operating-temperature range.

When FM352 Is the Right Choice

  • Output pulse width below 200 µs, which is too short for OB35 to resolve.
  • Multiple independent cam tracks (the FM352 supports 32 tracks; software in OB35 scales linearly with the number of tracks and the OB1 jitter budget is consumed quickly).
  • Galvanic isolation from the CPU backplane; the FM352 outputs are isolated to 500 V AC and can drive 24 V loads up to 0.5 A per output.
  • Deterministic behaviour that must survive CPU restart; the FM352 keeps its cam data in non-volatile memory and resumes output after a CPU STOP/RUN transition within 1 ms of the CPU returning to RUN.

FM352 Configuration Snippet (FB CAM)

// Call FB CAM (FB31 in FM CAM library) from OB100 / OB1
      CALL  FB31, DB31
        CAM_MOD_ADR  := W#16#100    // logical base address of FM352
        CAM_TYPE     := B#16#1      // 1 = FM352, 2 = FM352-2
        CAM_INIT     := TRUE        // initialise on first scan
        CAM_RESET    := FALSE
        CAM_QTSL     := MD40        // actual cam position (DINT, 1 us units)
        CAM_QFL      := MB42         // byte-wise cam output image

Method 3: Custom FC Block with Millisecond Counter

When OB35 is consumed by other tasks and adding a second cyclic interrupt would overload the CPU, the third option is a software counter driven by the built-in clock memory bit M_BIT_CLK at 1 Hz, 0.5 Hz, ... 10 Hz, scaled up to a millisecond counter. This is the approach Siemens service engineers document for "long" timers (multi-year durations) but the same scaffolding can be reused for any 1 ms resolution requirement that does not demand sub-millisecond accuracy.

Time-Base Selection

Time base Counter type Range Roll-over
10 ms (clock bit at 100 Hz) DINT (MD) 0 ... 2 147 483 647 × 10 ms ~ 248 days
100 ms (clock bit at 10 Hz) DINT (MD) 0 ... 2 147 483 647 × 100 ms ~ 6.8 years
1 s (clock bit at 1 Hz) DINT (MD) 0 ... 2 147 483 647 × 1 s ~ 68 years

FC "FB_Timer_1ms" — STL Implementation

FUNCTION_BLOCK FB_Timer_1ms
VAR_INPUT
  IN    : BOOL;          // start input (positive edge)
  RESET : BOOL;          // reset accumulated time
  PT    : TIME;          // preset time, 1 ms resolution requested
END_VAR
VAR_OUTPUT
  Q     : BOOL;          // done bit
  ET    : TIME;          // elapsed time
END_VAR
VAR
  Edge    : BOOL;        // one-shot on IN
  StartTime : TIME;      // start timestamp from system clock
  Running : BOOL;
END_VAR
BEGIN
  // Edge detect on IN
  IF IN AND NOT Edge THEN
       StartTime := CLK_LST;          // system clock, 1 ms tick
       Running  := TRUE;
  END_IF;
  Edge := IN;

  // Reset
  IF RESET THEN
       Running := FALSE;
       ET := T#0ms;
       Q  := FALSE;
       RETURN;
  END_IF;

  // Accumulate
  IF Running THEN
       ET := CLK_LST - StartTime;
       IF ET >= PT THEN
            Q := TRUE;
            Running := FALSE;
       ELSE
            Q := FALSE;
       END_IF;
  END_IF;
END_FUNCTION_BLOCK

The CLK_LST system clock on S7-300 increments every 10 ms by default; to get 1 ms resolution the engineer must configure the clock memory byte in the CPU properties and read the bit at 100 Hz as the time base. The FC still runs in OB1, so the achievable resolution is the OB1 scan period, not 1 ms. The block is therefore only useful for timing intervals longer than the OB1 scan; it cannot synthesize a 1 ms output pulse on its own.

Clock memory vs. CLK_LST. CLK_LST (SFC64 "TIME_TCK") returns a 1 ms time stamp on every S7-300 CPU; the value is independent of the clock memory byte. The clock memory byte is implemented as a hardware counter on the CPU and is therefore deterministic with respect to OB1, while CLK_LST is read at the moment of the call and is subject to scan-time jitter. Use CLK_LST for long-duration timers and the clock-memory bit for events that must be phase-locked to OB35.

Code: OB35 Pulse Generator (SCL)

The SCL equivalent of the OB35 pulse generator is the form most S7-300 engineers will deploy in TIA Portal V18+ projects. Place the code in OB35 and call FB_Tick from OB1.

// OB35 - 1 ms tick
"DB_Tick".Phase1 := TRUE;
"DB_Tick".Phase2 := FALSE;
IF "DB_Tick".TickNo > 0 THEN
    "DB_Tick".Pulse := TRUE;
    "DB_Tick".TickNo := "DB_Tick".TickNo - 1;
ELSE
    "DB_Tick".Pulse := FALSE;
END_IF;
IF "DB_Tick".Enable AND NOT "DB_Tick".EnableOld THEN
    "DB_Tick".TickNo := "DB_Tick".PulseCount;
END_IF;
"DB_Tick".EnableOld := "DB_Tick".Enable;
"DB_Tick".TickCount := "DB_Tick".TickCount + 1;

When called from OB1, the consumer sees a deterministic 1 ms tick because OB35 runs at priority class 12 and pre-empts OB1 at a 1 ms grid. The pulse stays high for the entire interval between two OB35 invocations, which means a downstream edge-detect on the pulse will see a 1 ms edge, not a single-cycle spike.

Timing Accuracy and Jitter Analysis

The jitter budget of a 1 ms timer has three principal contributors: the OB35 period stability, the time stamp resolution, and the consumer's read timing. The table below summarises the contribution of each source for the three methods described above.

Source OB35 (1 ms) FM352 FC + CLK_LST
Time-base resolution 1 ms 1 µs 10 ms (clock memory) or 1 ms (CLK_LST)
Period jitter (typical) ± 200 µs ± 1 µs ± 1 OB1 scan
Period jitter (worst case, comms loaded) ± 500 µs ± 2 µs ± 5 ms
CPU load impact Medium (200 µs to 600 µs of OB35 time per ms) None (autonomous) Low
Output response One OB1 scan later 8 µs to 12 µs One OB1 scan later
Hardware cost None FM352 + 5 V supply None

For a single 1 ms pulse that does not have to be regenerated continuously, the OB35 approach is usually the right answer. For a stream of 1 ms pulses, or for any pulse that has to survive a CPU scan-time excursion, the FM352 is the only fully deterministic option.

Edge Cases and Field-Proven Pitfalls

  1. OB35 not called at all. If the OB35 priority class is not assigned in HW Config, the CPU silently skips the call. Always verify the priority and download OB35 with the project.
  2. OB80 time-error overflow. When OB35 is set to 1 ms but the actual execution time of the OB35 body is greater than 1 ms, OB80 is triggered and OB35 is suspended until OB80 finishes. Keep the OB35 body under 500 µs in CPU 315-2 and under 800 µs in CPU 317-2.
  3. Communication load jitter. PROFIBUS DP and PROFINET IRT can stretch OB35 by hundreds of microseconds. Always measure with the worst-case comms load configured, not in a stand-alone lab.
  4. Multiple OB35 instances on a multi-CPU rack. Each CPU schedules its own OB35 independently; the two streams are not phase-locked. Use a single CPU and route the time stamp to other stations over PROFINET IRT if synchronisation is required.
  5. FM352 address clash. The FM352 occupies a 16-byte I/O area; the default address in STEP 7 is 256 ... 271. If a CP or FM at a conflicting address is on the rack, OB1 will see a peripheral-access error (OB122) and the FM will not start.
  6. FC-based timer with a 10 ms BCD time base. Forgetting to set the time base to 10 ms (or reading the timer word as INT and treating it as TIME) leads to a 10x or 100x error. Always inspect the time-base bits 15/14 of the timer word before reusing it as a TIME value.

Comparison: Which Method To Choose

Criterion OB35 FM352 Custom FC
Sub-millisecond accuracy required? No Yes No
Hardware budget available? Any ~ 1 500 EUR for FM352 + CAM SW Any
Spare cyclic-interrupt slot? Yes — —
Long-duration timer (days/years)? Not ideal No Best fit
Multiple independent 1 ms tracks? Up to 4 in OB35 + OB38 Up to 32 1 per FC
CPU restart behaviour Resume on RUN Resume within 1 ms Reset

Verification Procedure

  1. Confirm OB35 is firing. In STEP 7 / TIA, open the online view, force MD10 to 0, and observe that it increments by exactly 1 every second when OB35 is set to 1 ms (verify with a watch table on MD10 and the cycle time of the watch-table refresh set to 1 s).
  2. Measure OB35 period. Use SFC 64 "TIME_TCK" at the start and end of OB35, and write the delta to a marker. The 1000-sample average should be 1.000 ms with a standard deviation under 50 µs.
  3. Watch OB80. Add a counter that increments inside OB80. Any non-zero value means OB35 has been suspended by the CPU. The expected steady-state count is zero.
  4. Cross-load the timer. On a CPU 317-2, set OB35 = 1 ms and a parallel OB38 = 500 µs (priority 11). OB38 should be called twice for every OB35 call. If the ratio is not 2:1, the OB35 priority is wrong.
  5. End-to-end stimulus. Drive a fast counter module (FM 350-1 or FM 350-2) with the OB35 pulse and read the count over PROFIBUS. A 10 000-tick train should produce a measured duration of 10.000 s ± 0.020 s.

Working with STEP 7 / TIA Portal Versions

The 1 ms OB35 parameter is available on every S7-300 CPU from firmware V2.0 onward. TIA Portal V13 SP1 and later expose the same parameter; the SCL syntax shown above is valid from TIA V15.1. The S_ODT instruction documented at the Siemens TIA Portal documentation for S_ODT confirms that the on-delay timer has a 10 ms minimum time base, and the same constraint applies to S_PEXT, S_ODTS, S_PULSE, and S_OFFDT. The IEC 61131-3 TON/TOF/TP blocks inherit their time base from the OB in which they are called and therefore cannot exceed the OB1 scan period in resolution.

References to the Standard S7-300 Timer Instruction

The "Assign on-delay timer parameters and start" instruction, documented as S_ODT, is the workhorse timer block on S7-300. Its parameters are:

Parameter Type Meaning
S BOOL (input) Start input, positive edge starts the timer
TV S5TIME (input) Preset time in S5 format, BCD-coded with time base
R BOOL (input) Reset, clears the running time and Q output
Q BOOL (output) Timer status, 1 while ET < PT
BI WORD (output) Remaining time, binary-coded (no time base)
BCD WORD (output) Remaining time, BCD-coded with time base

The S5TIME format is a 16-bit word with the two MSBs selecting the time base. The minimum TV value that can be loaded is therefore 10 ms, and a TV smaller than 10 ms is rejected by the CPU at the time of the S_ODT call (the timer never starts). For more detail, see the official Siemens TIA Portal V21 S_ODT instruction reference.

Frequently Asked Questions

What is the absolute minimum time base of an S7-300 standard timer?

The five standard SIMATIC timer blocks (S_PULSE, S_PEXT, S_ODT, S_ODTS, S_OFFDT) all use a 16-bit S5TIME word with a 10 ms minimum time base, so 10 ms is the smallest interval that can be loaded. A TV value of 1 ms is treated as 0 and the timer never starts. To obtain 1 ms, use OB35, an FM352/FM352-2, or a custom FC driven by a 100 Hz clock memory bit.

How accurate is a 1 ms OB35 pulse on a CPU 315-2?

Under typical comms load the period is stable to within ± 200 µs, with a worst-case drift of ± 500 µs when PROFIBUS DP or PROFINET IRT is heavily loaded. The OB35 call itself adds 200 µs to 600 µs of overhead depending on the CPU, leaving roughly 400 µs of user time per 1 ms interval.

Can I use the IEC TON block for a 1 ms timer?

No. The IEC TON/TOF/TP blocks have a 1 ms time base only at the input; the effective resolution is set by the OB1 scan period. A TON with PT = T#1ms will produce a pulse that lasts one OB1 scan, not 1 ms, and the duration of that pulse varies with the program load. For deterministic 1 ms, move the timing logic into OB35.

When should I choose the FM352 over OB35?

Choose the FM352 when you need sub-200 µs accuracy, multiple independent cam tracks (up to 32), output response that is independent of the CPU scan, or pulse generation that must survive CPU STOP/RUN transitions within 1 ms. The FM352 runs autonomously and does not consume any OB35 time on the CPU.

How do I detect a missed OB35 interrupt?

Enable OB80 (time-error OB) in HW Config and increment a counter inside it. Any non-zero value of the OB80 counter means OB35 has been suspended, usually because the OB35 body took longer than 1 ms or a higher-priority OB (OB82, OB86, OB121, OB122) preempted it. With a well-sized OB35 body the OB80 counter should be zero throughout the lifetime of the CPU.

Back to blog