Siemens FB41 CONT_C PID: Cycle Time and OB3x Scheduling

David Krause15 min read
PID ControlSiemensTutorial / 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

1. Overview

FB41 (CONT_C) is the continuous PID controller function block shipped with the Siemens Standard PID Control toolbox for the S7-300 and S7-400 families. It integrates proportional, integral, and derivative action into a single block with bumpless transfer, anti-windup, dead-band, output limiting, and a derivative-lag (DTL) filter. Despite its age, FB41 is still widely used in S7-300 (CPU 312–319F), S7-400, and the WinAC slot PLCs, and it remains the canonical teaching example for sampled PID loops on Siemens platforms.

The single most common field defect with FB41 is a mismatch between the CYCLE input (sample time) and the actual interval at which the block is called by the CPU. When those two values disagree, the controller still runs, but its integral and derivative terms are computed against the wrong dt: GAIN no longer behaves like a proportional band, TI stretches or shrinks the integral action, and TD either spikes or fails to react. Closed-loop behaviour looks "almost right" at low gain, then becomes unstable the moment an engineer starts tuning.

This reference consolidates the correct calling methodology, the mathematics of the CYCLE parameter, the OB1-versus-OB3x trade-off, the loop-scheduler pattern for multi-PID projects, and the 0.1× dominant-time-constant rule of thumb for selecting the sample time. It also covers dead-time dominated processes and the Smith predictor pattern referenced in Siemens application notes.

2. Prerequisites

  • STEP 7 V5.5 or STEP 7 Professional in TIA Portal (V13 or later) with the S7-300/S7-400 CPU family installed.
  • Standard PID Control toolbox (FB41, FB42, FB43, FB58, FB59) registered in the project. In TIA Portal this is the optional package "PID Control (S7-300/400)".
  • CPU 314 or higher recommended for projects with more than three PID loops; CPU 312C/313C integrated I/O is acceptable for single loops.
  • Cycle time of the process available as an estimate (dominant time constant τ_p, dead time θ_p) from step-test or plant documentation.
  • Measured value scaled to engineering units (REAL, e.g. 0.0 – 100.0 °C) and clipped to a sensible range to prevent PV spikes propagating into I-action.

3. FB41 CONT_C Architecture and the CYCLE Parameter

FB41 implements a parallel-form PID with anti-windup, manual-to-auto bumpless transfer, and a first-order derivative lag. The I/O structure relevant to the sample-time discussion is shown below.

FB41 inputs that interact with the sample time
Parameter Type Meaning Notes for CYCLE
CYCLE REAL (s) Sampling interval of the block Must equal the OB period, otherwise the block internally re-derives dt and corrupts tuning
SP_INT REAL Setpoint in engineering units Independent of CYCLE
PV_IN REAL Process variable in engineering units Independent of CYCLE
GAIN REAL Proportional gain Multiplies the error after CYCLE-based normalisation
TI REAL (s) Integral action time Effective integration is dt/TI; mismatch with CYCLE scales the integrator
TD REAL (s) Derivative action time Derivative uses dt; a smaller real dt with a nominal CYCLE produces a stronger D
TM_LAG REAL (s) Derivative lag time constant Acts on the D path independent of CYCLE
DEADB_W REAL Dead-band width Independent of CYCLE
LMN_HLM / LMN_LLM REAL Output limits Anti-windup clamps I-term to these limits
I_ITL BOOL Initialise integrator Use to preload I-term on first run
IT_ON / DISV BOOL / REAL Enable I-term / Disturbance variable Independent of CYCLE

The integrator inside FB41 discretises the integral as a rectangular sum with step size equal to CYCLE:

In+1 = In + (GAIN · en / TI) · CYCLE

The derivative term uses a backward difference across one CYCLE period. If the real call interval drifts to k·CYCLE, the integrator accumulates k times faster and the derivative produces k times the expected response. The visible symptom is a controller that is "too aggressive" on the I-side and "too noisy" on the D-side — a textbook signature of a CYCLE mismatch.

Field rule: The CYCLE input is the contract between you and the block. If you cannot guarantee that OB1 will execute FB41 at a fixed interval, do not put FB41 in OB1.

4. Why OB1 is the Wrong Default for FB41

OB1 on an S7-300/400 executes once per scan. The scan time of OB1 is the sum of every other OB1 activity plus any higher-priority OB that pre-empts it. With HMI communication, distributed I/O updates, and other OB1 logic, the scan time is rarely constant: 80 ms one cycle, 140 ms the next. Calling FB41 directly from OB1 produces a non-uniform sample time, which violates the assumption baked into CYCLE.

Two failure modes appear in real plants:

  1. Slow scan creep: Scan time grows from 100 ms to 200 ms as more code is added. The controller silently becomes two times more aggressive on the I-term, which looks like a tuning problem until the engineer realises the scan-time monitor is the smoking gun.
  2. Long-tail scans: A single 800 ms scan (caused by a flash write or a PROFIBUS reconfiguration) makes the controller output a step of 8·(normal step) on the next call. The output limiter saves the actuator but the I-term winds up to the rail and takes minutes to bleed off.

Siemens documents this in the Standard PID Control manual, which states that FB41 must be called at a fixed time interval, and that the time interval must be entered in the CYCLE parameter.

5. Step-by-Step: Calling FB41 in a Cyclic Interrupt OB (OB3x)

The recommended pattern is to place FB41 inside a cyclic interrupt OB. S7-300 and S7-400 CPUs support OB30 through OB38. Their default and allowed periods are:

Default periods of cyclic interrupt OBs on S7-300/400
OB Default period Min Max Resolution
OB30 5 s 1 s 60 s 1 ms
OB31 2 s 500 ms 60 s 1 ms
OB32 1 s 250 ms 60 s 1 ms
OB33 500 ms 100 ms 60 s 1 ms
OB34 200 ms 50 ms 60 s 1 ms
OB35 100 ms 10 ms 60 s 1 ms
OB36 50 ms 5 ms 60 s 1 ms
OB37 20 ms 2 ms 60 s 1 ms
OB38 10 ms 1 ms 60 s 1 ms

Procedure:

  1. Open the S7 project in STEP 7 / TIA Portal and navigate to the project tree.
  2. Add a new FB instance for FB41 by inserting a call from the Standard PID Control library. Accept the default instance DB (e.g. DB41) and assign a symbol, e.g. PID_TEMP_FURNACE.
  3. Right-click the Blocks folder, choose "Insert New Object → Organization Block", and select a cyclic interrupt OB, for example OB35 (100 ms). Give it a symbolic name, e.g. OB35_PID_100MS.
  4. Inside OB35, call the FB41 instance. Wire SP_INT, PV_IN, GAIN, TI, TD, and the output LMN (analogue output) or LMN_PER (peripheral output for direct PA writes).
  5. Wire CYCLE to a real constant that matches the OB period. If OB35 is set to 100 ms, hard-code CYCLE := T#100ms in seconds, i.e. 0.1 s. Use a global constant OB35_PERIOD_S := 0.1 to keep this in one place.
  6. Configure the OB35 period in HW Config → CPU properties → "Cyclic Interrupts" tab. Enter 100 ms and a phase offset of 0 ms.
  7. Download and test. The PID self-test should now show a uniform call interval in the trend.
Phase offset: Stagger OB30, OB32, OB35 with different phase offsets if multiple PIDs need to run in the same window. Phase offset is configured in the same dialog and prevents the cyclic OBs from queuing behind each other at startup.

6. Step-by-Step: Calling FB41 in OB1 with a Software Timer

For projects on a CPU that has only one cyclic interrupt (S7-300 with OB35 only) and several PID loops of widely different speed, the loop-scheduler pattern inside OB35 is the field-proven solution. Calling FB41 from OB1 with a self-managed timer is also possible but requires care.

Procedure for the OB1 self-timer approach:

  1. For each PID loop create two IEC timers or a counter pair: one for the desired CYCLE (e.g. 5 s) and a flag PID_x_DUE.
  2. In OB1, on every scan, decrement the timer. When it expires, set the PID_x_DUE flag and reload the timer.
  3. Immediately after, call FB41 inside an IF/THEN guard:

IF PID1_DUE THEN
  PID1_DUE := FALSE;
  PID1(SP_INT := 80.0,
       PV_IN := PV_FURNACE,
       GAIN := 1.2,
       TI := 120.0,
       TD := 0.0,
       CYCLE := 5.0, // seconds, matches timer
       LMN := MV_FURNACE);
END_IF;

This approach is functionally allowed because the CYCLE constant matches the timer period exactly, so FB41 sees a uniform dt. The disadvantage is that the next call can never be earlier than the next OB1 scan; if OB1 itself takes 250 ms, the effective call is 250 ms + residual timer, not exactly 5.0 s. For a slow process (5 s, 10 s) this is negligible. For fast PIDs it is unacceptable.

The Siemens-recommended approach is to keep all PIDs in OB35 and use a loop scheduler to release them at different multiples of the OB35 period. See Section 8.

7. Cycle Time Selection and the 0.1× Time Constant Rule

The sample time CYCLE is selected based on the process dynamics, not on a generic "fast is better" instinct. The widely used engineering rule of thumb is:

CYCLE ≈ 0.1 · τp

where τp is the dominant (slowest significant) time constant of the process. This rule is stated explicitly in the Siemens Standard PID Control documentation. It produces a controller that is responsive to disturbances without aliasing the dominant mode.

Cycle time selection by process type
Process Typical τp Suggested CYCLE OB
Pressure (hydraulic) 0.5 – 2 s 50 – 200 ms OB34 / OB35
Flow (water / air) 1 – 5 s 100 – 500 ms OB35 / OB33
Level (tank) 5 – 60 s 500 ms – 6 s OB33 / OB32 / OB31
Temperature (small furnace) 30 – 300 s 3 – 30 s OB30 + scheduler
Temperature (large kiln) 300 – 3600 s 30 – 360 s OB30 + scheduler
Position / pH 5 – 60 s 500 ms – 6 s OB33 / OB32

If τp is unknown, perform an open-loop step test: drive the output to a small step (5 %), record PV, and fit a first-order-plus-dead-time (FOPDT) model. The plant gain K, time constant τp, and dead time θp come out of the fit and feed both CYCLE and the initial PI/PID tuning (Ziegler-Nichols, Cohen-Coon, or Lambda tuning).

For Lambda tuning the recommended CYCLE is usually a fraction (0.05 to 0.1) of τp; for very slow processes the CYCLE is allowed to be in the multi-second range and the controller will still track a setpoint change with a smooth, low-noise output.

8. Multi-Loop Scheduling: The Loop Scheduler Pattern

When the project contains PIDs with very different cycle times, a single OB35 at 100 ms is wasteful for slow loops and insufficient for fast ones. The loop scheduler is a small cyclic dispatcher inside a fast OB3x that calls each FB41 only when its own period has elapsed.

Pattern (SCL or STL inside OB35):

// Master cycle in OB35 = 100 ms
// Slow loop scheduled every 50 master cycles = 5 s
// Fast loop scheduled every master cycle = 100 ms
// Medium loop every 10 master cycles = 1 s
IF SCHED_FAST THEN
  PID_FAST(CYCLE := 0.1, ...);
END_IF;
IF SCHED_MED THEN
  PID_MED(CYCLE := 1.0, ...);
END_IF;
IF SCHED_SLOW THEN
  PID_SLOW(CYCLE := 5.0, ...);
END_IF;

The scheduler is typically a wraparound counter plus three preloads. Each tick of OB35 increments the counter; when the counter equals the preload, the corresponding SCHED_x flag is set and the counter is reset to 0. This pattern is documented in Siemens application notes and is also implemented in the optional "Modular PID Controller" and "Standard PID Controller" packages as the Loop Scheduler element. For an S7-300 with a single OB35 the scheduler avoids the need for OB30 / OB32 / OB33 and gives every PID its own CYCLE.

For an S7-400 with all eight OB3x available, an alternative is to place each PID in a different OB3x and set the OB period to the required CYCLE. Phase offsets prevent OB3x from queuing at startup. The trade-off is OB count versus dispatcher overhead; for fewer than four PIDs the dispatcher is usually lighter, for more than four the multiple-OB approach is more transparent in the online view.

9. Dead-Time Dominated Processes and the Smith Predictor

FB41 is a single-loop PID and assumes a process whose dynamics are captured by the sampled integrator. Processes with significant dead time (transport delay, chromatograph, long pipe, batch reactor with temperature propagation) do not behave as expected: a CYCLE change that reduces dt does not reduce the observed dead time, so the I-action has to be detuned heavily to remain stable.

The Smith predictor is the standard Siemens-recommended remedy. The structure uses an internal model of the process (gain K, time constant τ, dead time θ) to predict what the PV would be without the delay, and feeds the difference between the predicted and actual PV into the PID. The visible effect is that the PID "sees" a process with no dead time, allowing more aggressive tuning than a classical PID on the real plant.

A pragmatic alternative when Smith is too complex is to add a first-order lag to the PV (PT1) and lengthen CYCLE, which sacrifices dynamic response for stability. The choice is project-dependent and should be documented in the control narrative.

10. Verification and Diagnostics

After commissioning, verify the loop is actually running at the configured CYCLE:

  1. Open the FB41 instance DB online in STEP 7 / TIA Portal and trend CYCLE against an internal time stamp. Confirm the effective interval is constant.
  2. Use the CPU's online diagnostics (Module Information → Scan Times) to read OB35 worst-case execution time. If the worst-case approaches the period, increase the OB period or split the load into two OBs.
  3. Apply a small setpoint step (5 %) and observe the response. The characteristic rise time should be 2 to 4 times the configured CYCLE for a properly tuned temperature loop, and 0.5 to 1 times for a fast flow or pressure loop.
  4. Check I_ITL on startup. Preload the integrator with the expected steady-state MV (computed from the valve curve or known duty cycle) to avoid the first few minutes of windup on cold start.

11. Common Errors and Field Notes

Symptom → root cause → fix
Symptom Likely root cause Fix
Output oscillates with period of several seconds at low gain CYCLE does not match OB period, I-term runs at wrong rate Verify CYCLE constant vs. HW Config period; trend to confirm
MV jumps to LMN_HLM on the first disturbance Anti-windup not primed, or I-term saturated from a long scan gap Preload integrator with I_ITL on first run; check LMN_HLM
Controller sluggish on slow process CYCLE is much smaller than τp, integral action builds on noise Increase CYCLE to 0.1·τp or use scheduler
MV noisy on D-term Derivative action picks up sensor noise amplified by short CYCLE Increase TM_LAG; check PV filtering; increase CYCLE
Loop runs fine in simulation but unstable on plant Real scan time differs from simulator; OB35 period default of 100 ms may not match Re-check HW Config → Cyclic Interrupts
OB3x time-out alarm (OB80) OB3x execution longer than its period Move PIDs to a slower OB or split the dispatcher
Documentation reference: The Standard PID Control manual (Siemens entry ID 1135493 and the S7-300/400 PID Control manual, edition 2006, A5E00204550) is the authoritative source for FB41 behaviour, including the explicit statement that the block must be called at a fixed time interval equal to CYCLE. Always cross-check tuning and timing rules against the latest edition of the manual for the firmware version installed in your CPU.

12. Quick Checklist

  • FB41 placed in OB3x whose period equals CYCLE, not in OB1.
  • HW Config → CPU properties → Cyclic Interrupts shows the intended period.
  • Phase offset set so multiple OB3x do not queue.
  • Loop scheduler used when more than three PIDs share a single OB.
  • CYCLE ≈ 0.1·τp, validated by open-loop step test.
  • FB41 instance DB has I_ITL primed for cold start.
  • Online trend confirms uniform call interval.

Does FB41 have to be called in a cyclic interrupt OB, or can it stay in OB1?

It can stay in OB1 only if OB1 itself has a constant scan time and the CYCLE constant matches that scan time. In practice the recommended and far more robust approach is to call FB41 from a cyclic interrupt OB (OB30–OB38) and to set the CYCLE input to the OB's configured period. For multi-PID projects, keep all PIDs in OB35 and use a loop scheduler to release each one at its own multiple of 100 ms.

What is the default period of OB35 and how do I change it?

OB35 is pre-configured for 100 ms on most S7-300/400 CPUs. Open the HW Config, select the CPU, and go to Properties → Cyclic Interrupts. Enter the desired period (10 ms to 60 s with 1 ms resolution) and a phase offset (0 to period − 1 ms). The change must be downloaded to the CPU and typically requires a STOP→START transition to take effect.

How do I pick the CYCLE value for a temperature loop on a large furnace?

Perform an open-loop step test and fit a first-order-plus-dead-time model to obtain τp. Set CYCLE to roughly 0.1·τp. For a furnace with τp of 600 s, CYCLE should be 60 s; put the FB41 in OB30 and use a 60 s period, or keep it in OB35 with a scheduler that releases it every 600 master cycles (assuming OB35 is 100 ms).

Can I call multiple FB41 instances in the same OB3x?

Yes, but their CYCLE values must be the same if they share a common call point. If two loops need different CYCLE values, place each in its own OB3x (e.g. OB32 for 1 s, OB35 for 100 ms) or run a loop scheduler inside OB35 that releases each FB41 at its own multiple. The latter is the standard solution for S7-300 CPUs that have only one cyclic interrupt OB.

My controller drifts and then suddenly winds up. Is this FB41 or CYCLE mismatch?

Both are possible, but a windup episode that takes minutes to bleed off after a long OB1 scan gap is a strong indicator of CYCLE mismatch. Trend CYCLE in the instance DB while the scan monitor is active: if the interval varies by more than 5 %, move the FB41 to a dedicated OB3x with a guaranteed period. Also check that LMN_HLM / LMN_LLM are realistic; over-large limits combined with a CYCLE mismatch produce exactly the drift-then-spike signature you are seeing.

Back to blog