Siemens FB41 PID Controller: OB1 vs OB35 Execution Analysis

David Krause17 min read
PID ControlSiemensTechnical 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

Overview

The Siemens FB41 "CONT_C" continuous PID block from the Standard PID Control library is the most widely deployed regulatory controller on SIMATIC S7-300/400 systems programmed with STEP 7 V5.x. Where the block is called from — the free-cyclic OB1 or a time-triggered cyclic interrupt such as OB35 — has direct consequences for loop accuracy, derivative noise, integral wind-up behavior, scan-time jitter, and CPU utilization. This reference consolidates the architectural rules, the FB41 input/output contract, the sampling-time math, and the tuning workflow required to commission a deterministic PID loop in production.

Organization Block Architecture in S7-300/400

An S7 CPU executes organization blocks (OBs) according to a fixed priority ladder. The two OBs relevant to a PID application are OB1 (priority 1, free-cyclic) and the OB30–OB38 range (priority 2–24, hardware- and time-triggered cyclic interrupts). The STEP 7 help on "Organization Blocks" and the manual "S7-300 Programmable Controller, Hardware and Installation" list the priority class for each OB.

OB Priority Trigger Default Interval Typical Use
OB1 1 End of previous OB1 cycle Scan-time dependent (typ. 5–50 ms) Main sequential logic
OB10 2 Time-of-day (absolute) Configurable Daily/hourly jobs
OB30 7 Cyclic interrupt 5 s default Slow supervisory loops
OB35 12 Cyclic interrupt 100 ms default Standard PID sampling
OB38 24 Cyclic interrupt 10 ms default Fast motion loops
OB40 16–26 Hardware interrupt Process event Fast I/O reaction
OB80–OB87 26 Error/fault Asynchronous Diagnostic handler
OB100 27 Restart One-shot Initialization
OB121 Same as faulted OB Programming error Synchronous Trap I/O faults

Two architectural facts follow directly from the priority structure:

  1. OB35 preempts OB1. A configured OB35 interval elapses during OB1 execution, the CPU suspends OB1 mid-scan, copies the entire stack, executes OB35 to completion, then resumes OB1 where it left off. The technical term "cyclic interrupt" therefore refers to the fact that OB3x interrupts the OB1 cycle, not that it interrupts a hardware line.
  2. OB1 has no guaranteed period. The next OB1 run begins only after the previous OB1 plus any pending higher-priority OBs finish. Anything that increases OB1 scan time — adding a new block, expanding a string operation — silently changes the effective PID sampling rate.

OB1: Main Cyclic Program

OB1 is the free-cyclic main program. With no other OBs loaded, OB1 executes once per cycle and the next OB1 run starts immediately after the current run finishes. A typical mid-range S7-300 station (CPU 315-2 PN/DP) reports OB1 scan times of 10–30 ms; a heavy CPU 417 reports 5–15 ms. The relevant consequence for FB41 is that the actual PID sampling time equals the variable OB1 scan time, not a configured constant.

Pros of FB41 in OB1

  • Simplest possible project structure — only OB1 exists, no hardware configuration of OB35 required.
  • Process image is naturally coherent: all inputs are read once at the top of OB1, FB41 computes on the same image, outputs are written once at the bottom.
  • No preemption, so debug breakpoints behave intuitively.

Cons of FB41 in OB1

  • The CYCLE input of FB41 cannot be tied to a real-time clock value; it is whatever the user types in, and the actual sampling period silently drifts with OB1 scan time. The integrator inside FB41 still adds the discrete increment (GAIN * error / TI) * dt, but the dt is whatever the integrator remembers from the previous call, not what the wall clock has actually elapsed.
  • Differentiator gain TD / CYCLE becomes wrong when the OB1 scan doubles because someone added a recipe loader to OB1.
  • CPU utilization on a CPU 315-2 with two FB41 loops plus HMI traffic can climb above 60% in OB1, leaving little headroom.

OB35: Cyclic Interrupt

OB35 is the cyclic interrupt OB with the Siemens default interval of 100 ms. The interval is set per slot in HW Config → CPU Properties → Cyclic Interrupts; allowable values are 1 ms to 60 000 ms in 1 ms increments, with phase offset in the same dialog. Once configured and downloaded, OB35 fires every 100 ms (± the OB1 jitter of typically < 1 ms) regardless of OB1 length. OB35 is the recommended host for any FB41 / FB42 / FB43 call when:

  • The process has a dominant time constant that is at least 10× the configured interval (Nyquist–Shannon sampling theorem applied to control, see Section 5).
  • Multiple loops share the CPU and OB1 scan time becomes variable under recipe/HMI load.
  • The loop drives a final-control element (valve, VFD, heater) where deterministic sampling is part of the safety case.

Pros of FB41 in OB35

  • Constant sampling rate. Set CYCLE := T#100ms on FB41 and it stays 100 ms forever. Derivative and integral gain stop drifting.
  • Reduced OB1 load. Heavy computation moves out of OB1, which becomes shorter and more deterministic. On a CPU 314 with three FB41 loops, moving them from OB1 to OB35 typically drops OB1 from ~45 ms to ~12 ms.
  • Predictable PID output. The LMN_PER / LMN values are computed at a known cadence, making trend recordings and acceptance tests reproducible.

Cons of FB41 in OB35

  • Process image read by FB41 inside OB35 is the "last OB1" image unless a partial update with SFC 26 "UPDAT_PI" / SFC 27 "UPDAT_PO" is programmed. For PID this is usually fine (one analog input + one analog output per loop), but multiple loops sharing an input module must each perform their own update.
  • OB35 execution time still counts toward the overall scan; exceeding the OB35 interval triggers OB80 (time error) and the CPU goes to STOP if not handled.
  • Debug breakpoints inside OB35 are intrusive: pausing inside OB35 while the wall clock keeps ticking causes an OB80 immediately on the next trigger.

Sampling-Time Theory for Digital PID

The discrete-time equivalent of a continuous PID is the velocity form:

delta_u(k) = Kp * [ (e(k) - e(k-1)) + (Ts/Ti) * e(k) + (Td/Ts) * (e(k) - 2*e(k-1) + e(k-2)) ]

where Ts is the sampling period. Three engineering rules apply:

  1. Rule of ten. Ts <= 0.1 * T_process, where T_process is the dominant time constant (63 % rise of the open-loop step response). For a temperature loop with T_process = 90 s the maximum acceptable Ts is 9 s; for a flow loop with T_process = 0.6 s, Ts must be ≤ 60 ms.
  2. Rule of Ziegler–Nichols closed-loop. Ts ≈ 0.1 * Tu, where Tu is the ultimate period measured with P-only control at the critical gain K_u.
  3. Nyquist bound. Disturbance rejection above 1/(2·Ts) cannot be improved by the loop. For Ts = 100 ms this is 5 Hz — well above the bandwidth of virtually every thermal, level, pressure, and slow-flow loop, but a hard ceiling for fast pressure or hydraulic loops that demand Ts = 10 ms (OB38) or hardware interrupts (OB40).
Process Type Typical T_process Recommended Ts Recommended OB
Temperature (furnace, extruder) 60 – 600 s 1 – 10 s OB35 (or OB34 at 500 ms)
Level (tank) 10 – 120 s 500 ms – 2 s OB35
Pressure (slow) 1 – 10 s 100 – 200 ms OB35 (default 100 ms)
Flow (liquid) 0.3 – 3 s 50 – 100 ms OB35 or OB38
Pressure (hydraulic) 0.05 – 0.5 s 5 – 20 ms OB38 (10 ms default) or OB40
Position / motion 0.01 – 0.2 s 1 – 4 ms OB40 with FM 458 / SIMOTION

FB41 "CONT_C" Block Specification

FB41 resides in Standard Library → PID Control Blocks. The instance DB is created once per loop and stores the integrator state, derivative state, and output limiter across power cycles. Critical inputs:

Input Type Range / Units Meaning
SP_INT REAL −100.0 to 100.0 % Setpoint in % (engineering-normalized)
PV_IN REAL −100.0 to 100.0 % Process value in % from FB / CFC logic
PV_PER INT 0 to 27 648 Process value direct from analog input (PIW)
DEADB_W REAL ≥ 0.0 % Dead-band width for noise suppression
MAN REAL −100.0 to 100.0 % Manual output for bumpless transfer
MAN_ON BOOL 0/1 1 = manual mode
GAIN REAL > 0 Proportional gain
TI TIME >= CYCLE Integral time (reset time)
TD TIME >= CYCLE Derivative time
TM_LAG TIME >= CYCLE/2 Derivative lag (first-order filter)
DISV REAL −100.0 to 100.0 % Feed-forward disturbance
CYCLE TIME >= 1 ms Sampling time must match real call period
LMN_HLM / LMN_LLM REAL −100.0 to 100.0 % Output high/low limits
LMN_FAC / LMN_OFF REAL REAL Output linear scaling: LMN_PER = LMN * LMN_FAC + LMN_OFF
Output Type Meaning
LMN REAL Manipulated variable in %
LMN_PER INT Manipulated variable for direct analog output (PQW)
QLMNDT BOOL 1 = output limited at LMN_HLM / LMN_LLM
QLMHLM / QLMLLM BOOL High / low limit reached
QVLMN BOOL 1 = LMN_PER / LMN valid
BI / BTI REAL Current effective setpoint / process value
Critical parameter rule: CYCLE must equal the real wall-clock period of the call. With FB41 in OB35 at the default 100 ms, set CYCLE := T#100MS. If OB35 is later changed in HW Config, change the FB41 instance-DB value too, or the integrator/derivative will silently misbehave.

Step-by-Step: Configure FB41 in OB35

Prerequisites

  • STEP 7 V5.5 or V5.6 with Standard Library > PID Control Blocks visible.
  • CPU 31x or 41x with enough free work memory (FB41 instance DB ≈ 80 bytes per loop).
  • Analog input module wired to the PV sensor, analog output module wired to the final control element.
  • Known dominant time constant of the process (open-loop step test result, or P&ID data sheet).

Procedure

  1. Enable OB35. Open the S7 station in HW Config, double-click the CPU, select the Cyclic Interrupts tab. Set OB35 to 100 ms and leave phase offset at 0 ms. Compile and download the hardware.
  2. Insert FB41. In the LAD/FBD/ST editor, open OB35 and call FB41 with a name (e.g. "PID_FURNACE"). STEP 7 prompts to create the instance DB; accept and assign DB number 50.
  3. Wire setpoint and process value. Connect SP_INT to a data-block REAL or directly to a CFC tag. Convert the raw PIW to percent using FC105 "SCALE" or the PV_PER path of FB41. The PV_PER path is preferred because FB41 internally scales the integer to percent using the 0–27 648 Siemens convention.
  4. Set CYCLE. Open DB50 and confirm CYCLE = T#100MS. If you use OB38 instead, change it to T#10MS.
  5. Initial parameters. Start with GAIN = 1.0, TI = T#300S, TD = T#0S (P+I mode for first tuning).
  6. Bumpless transfer. Always wire MAN_ON := FALSE and MAN := LMN from the previous scan (using the same instance-DB output), or accept the manufacturer's default auto-tracking by leaving MAN = 0.0.
  7. Compile and download. Save the project, download blocks to the CPU, and place the CPU in RUN.

Verification

  1. Open the instance DB online and confirm CYCLE is the value you set and not T#0MS.
  2. Watch QLMHLM / QLMLLM — they should be FALSE in normal operation; persistent TRUE means the output is clamped.
  3. Force a 5 % step on SP_INT and trace PV and LMN in the trend recorder. The response should be stable, no overshoot above 10 %, settling within 3 dominant time constants.
  4. Read the OB35 execution time with the SFC 78 / SFC 79 diagnostics or the CPU diagnostic buffer. If OB35 ever exceeds 100 ms (OB80 event), increase the configured interval or reduce the loop count.

PID Tuning Methods

Tuning is the empirical selection of GAIN, TI, and TD that stabilizes the closed loop as quickly as possible after a setpoint change or disturbance with minimum overshoot. Five well-documented methods cover roughly 95 % of industrial practice.

Ziegler–Nichols Open-Loop Step Response

Apply a small step (5–10 %) to MAN_ON while in manual and capture the PV ramp. Read off the process gain K_p (%/% rise over % step), the dead time L (delay until PV leaves its noise band), and the time constant T (63 % of total rise).

Controller GAIN TI TD
P T / (K_p · L)
PI 0.9 · T / (K_p · L) 3.33 · L
PID 1.2 · T / (K_p · L) 2.0 · L 0.5 · L

Ziegler–Nichols assumes a self-regulating process with a clear dead time. It tends to overshoot; reduce GAIN by 30 % if overshoot is unacceptable.

Ziegler–Nichols Closed-Loop Ultimate Gain

With TI = T#∞ (enter T#999999MS or the maximum TIME constant) and TD = T#0MS, raise GAIN in steps until the PV oscillates with constant amplitude. Record the gain K_u and the oscillation period T_u.

Controller GAIN TI TD
P 0.5 · K_u
PI 0.45 · K_u 0.8 · T_u
PID 0.6 · K_u 0.5 · T_u 0.125 · T_u
Caution: Never leave the loop at K_u for production; this is a test condition only. Stop the test by returning to manual mode if the oscillation grows.

Cohen–Coon

Uses the same step-response parameters K_p, L, T but produces less overshoot for processes with L / T > 0.3 (large dead time). Coefficients are tabulated in "Process Control: A Practical Approach" and the Siemens PID Self-Tuner manual. For PI mode: GAIN = (1/K_p) · (T/L) · (0.9 + L/(12·T)), TI = L · (30 + 3·L/T) / (9 + 20·L/T).

IMC (Internal Model Control)

Best for setpoint tracking. For a first-order-plus-dead-time model G(s) = K_p · e^{-Ls} / (T·s + 1) choose GAIN = T / (K_p · (L + lambda)), TI = T, TD = 0, where the closed-loop time constant lambda is chosen as lambda >= 0.8 · L. Larger lambda means slower but more robust response.

Lambda Tuning

European variant of IMC with explicit lambda. The recommended starting point is lambda = T. On integrating processes use GAIN = T / (K_p · lambda) with TI = 2 · lambda.

Auto-Tuning with Siemens PID Self-Tuner (FB58 "TCONT_CP")

For new projects, prefer the PID Self-Tuner (FB58 TCONT_CP) over FB41. FB58 has a built-in warm-start phase that identifies the process parameters online and writes GAIN, TI, TD into the same instance DB automatically. It can be left running during commissioning without the engineer manually applying Ziegler–Nichols numbers.

Practical Tuning Procedure (P-I first, then D)

  1. Set TD = T#0MS, DEADB_W = 0.0, TM_LAG = T#100MS. Switch to manual (MAN_ON = TRUE).
  2. Bring MAN to a value that holds PV at the desired operating point. Confirm PV is stable for at least one time constant.
  3. Switch to automatic (MAN_ON = FALSE). Apply the Ziegler–Nichols PI formulas from Section 8.1.
  4. Step SP_INT by 5 %. Observe overshoot and settling. If overshoot > 15 %, reduce GAIN by 30 % and increase TI by 50 %.
  5. If a residual steady-state error remains, reduce TI in steps of 20 % until the error vanishes.
  6. If the process has measurable dead time but you want faster settling, add derivative: TD = 0.25 · TI, then reduce GAIN by 10 % to compensate for the increased high-frequency gain.
  7. Tune the disturbance feed-forward: wire DISV to the measured disturbance (e.g. inlet flow for an outlet temperature loop) and scale so the disturbance feed-forward cancels 70 % of the expected excursion.

Anti Wind-up and Bumpless Transfer

FB41 has a built-in anti-windup that freezes the integrator while LMN is at LMN_HLM or LMN_LLM. The associated flag is QLMNDT. To get the best behaviour:

  • Set LMN_HLM and LMN_LLM to the actual physical limits of the actuator (e.g. 0–100 % for a valve, or 4–20 mA-equivalent 0–100 % for a current loop). Never leave them at the default ±100 if the actuator is narrower.
  • For bumpless transfer from manual to auto, set MAN to the actual actuator feedback (not to the last LMN_PER value) so the integrator starts at the right state.
  • Use QLMNDT in the HMI faceplate to warn operators that the loop is in saturation.

Diagnostics and Verification

Check Method Pass Criterion
OB35 cycle time honored Read CPU diagnostic buffer "OB35 started" entries; SFC 78 "READ_SZL" list 0x0131/0x0132 No OB80 time-error events
FB41 sampling consistency Instance DB online → CYCLE field CYCLE equals OB35 interval from HW Config
Process image freshness Compare PIW value in OB1 vs OB35 via VAT Difference ≤ 1 scan
Loop stability 5 % setpoint step, trend PV Overshoot < 10 %, settling within 3·T_process
Saturation count Count QLMNDT pulses per hour < 5 % of OB35 calls
Integral wind-up Move actuator to limit; read I_ITVAL in DB Stops accumulating when LMN at limit

Troubleshooting Matrix

Symptom Likely Root Cause Remediation
Loop oscillates at the OB1 scan frequency FB41 in OB1 with CYCLE ≠ OB1 scan time Move FB41 to OB35, set CYCLE = OB35 interval
Loop oscillates faster after a code change OB1 scan time grew; derivative gain increased with shorter perceived Ts Set DEADB_W to the noise band, increase TM_LAG, or move to OB35
CPU goes to STOP with "OB80 time error" OB35 exceeds configured interval Raise OB35 interval, split loops across OB34/OB35, reduce code in OB35
Output bumps when switching MAN → AUTO MAN ≠ LMN at switchover Wire MAN to actuator feedback; enable bumpless transfer in HMI
Integral never settles, output hits limit Sensor polarity inverted or GAIN sign wrong Reverse PV scaling, multiply GAIN by −1, or use negative GAIN with reversed actuator
Derivative action spikes on noisy PV TD too large or DEADB_W = 0 Set DEADB_W = 2–3× noise band; increase TM_LAG to T#1S
Different loop response on second CPU OB35 interval not downloaded, OB35 phase offset ≠ 0 Re-download HW Config, verify CPU Properties → Cyclic Interrupts
SF LED on, diagnostic buffer "PID process value invalid" Analog input broken-wire or underrange Check FB125 "MULTIPLEX" or FC105 scaling; verify PIW status bits
Output does not update despite changing SP MAN_ON = TRUE stuck, or integrator saturated and SP inside deadband Check HMI tag for MAN_ON, lower DEADB_W, raise LMN_HLM

Migration Notes: FB41 → FB58 "TCONT_CP"

For new projects in STEP 7 V5.5 and TIA Portal V14+ Siemens recommends FB58 "TCONT_CP" (PID Self-Tuner) and the technology object "PID_Compact" in TIA Portal. FB58 keeps the same inputs/outputs as FB41 plus TUN_ON, RET_CPF, SAVE_PAR, and uses the same CYCLE semantics. Existing FB41 programs can be migrated 1:1 by re-importing the FB41 source into a new project and replacing the FB call; the instance DB schema is compatible except for the added self-tuning fields.

FAQ

Should FB41 be called in OB1 or OB35?

Use OB35 for almost every temperature, level, pressure, and flow loop. OB1 is acceptable only for very slow loops (> 60 s time constant) on lightly loaded CPUs where you accept that the effective sampling time drifts with OB1 scan. Set the FB41 CYCLE input to match the OB35 interval configured in HW Config (default 100 ms).

What does "cyclic interrupt" mean for OB35?

OB35 is a time-triggered organization block that preempts OB1 every 100 ms (or the configured interval). The name "interrupt" reflects that OB35 interrupts the OB1 cycle, not a hardware interrupt line. OB3x is one of several watchdog-style time interrupts used to schedule periodic tasks at a guaranteed cadence.

Why does moving FB41 to OB35 reduce CPU load?

OB1 is called only when its previous run completes; with FB41 in OB1 the PID math runs every OB1 cycle (often 25–45 ms, so up to 40 times per second). In OB35 the same FB41 runs only 10 times per second (at 100 ms), so the integrator and derivative add roughly one quarter of the OB1 arithmetic load. The remaining OB1 becomes shorter, scans faster, and frees headroom for HMI and other tasks.

How do I tune a loop that already has FB41 in OB35?

Start with a P-only step test to find the critical gain Ku and ultimate period Tu (Ziegler–Nichols closed loop), then apply GAIN ≈ 0.45·Ku, TI ≈ 0.8·Tu, TD = 0 for PI. If the open-loop step response gives clear Kp, L, T use Ziegler–Nichols open-loop or Cohen–Coon. Avoid leaving the loop at Ku for production; it is a transient test value only.

What happens if I forget to set CYCLE on FB41?

The default instance-DB value is T#1S, regardless of where the block is called. The integrator computes its discrete increment using 1 s even though OB35 fires every 100 ms. The result is a sluggish loop with an apparent Ti four times smaller than configured. Always open the instance DB online and confirm CYCLE matches the OB35 interval before commissioning.

Can I run multiple FB41 loops in the same OB35?

Yes, with two constraints. The total execution time of all FB41 instances inside OB35 must stay below the OB35 interval or an OB80 time error is raised. For two PI loops on a CPU 315 budget roughly 4 ms per loop; for eight loops budget 25 ms total and verify with the diagnostic buffer.

Back to blog