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:
- 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.
- 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
CYCLEinput 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 thedtis whatever the integrator remembers from the previous call, not what the wall clock has actually elapsed. - Differentiator gain
TD / CYCLEbecomes 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#100mson 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:
-
Rule of ten.
Ts <= 0.1 * T_process, whereT_processis the dominant time constant (63 % rise of the open-loop step response). For a temperature loop withT_process = 90 sthe maximum acceptableTsis 9 s; for a flow loop withT_process = 0.6 s,Tsmust be ≤ 60 ms. -
Rule of Ziegler–Nichols closed-loop.
Ts ≈ 0.1 * Tu, whereTuis the ultimate period measured with P-only control at the critical gainK_u. -
Nyquist bound. Disturbance rejection above
1/(2·Ts)cannot be improved by the loop. ForTs = 100 msthis 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 demandTs = 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 |
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
-
Enable OB35. Open the S7 station in HW Config, double-click the CPU, select the Cyclic Interrupts tab. Set OB35 to
100 msand leave phase offset at0 ms. Compile and download the hardware. -
Insert FB41. In the LAD/FBD/ST editor, open OB35 and call
FB41with a name (e.g."PID_FURNACE"). STEP 7 prompts to create the instance DB; accept and assign DB number 50. -
Wire setpoint and process value. Connect
SP_INTto a data-block REAL or directly to a CFC tag. Convert the raw PIW to percent usingFC105 "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. -
Set CYCLE. Open DB50 and confirm
CYCLE = T#100MS. If you use OB38 instead, change it toT#10MS. -
Initial parameters. Start with
GAIN = 1.0,TI = T#300S,TD = T#0S(P+I mode for first tuning). -
Bumpless transfer. Always wire
MAN_ON := FALSEandMAN := LMNfrom the previous scan (using the same instance-DB output), or accept the manufacturer's default auto-tracking by leaving MAN = 0.0. - Compile and download. Save the project, download blocks to the CPU, and place the CPU in RUN.
Verification
- Open the instance DB online and confirm
CYCLEis the value you set and notT#0MS. - Watch
QLMHLM / QLMLLM— they should be FALSE in normal operation; persistent TRUE means the output is clamped. - Force a 5 % step on
SP_INTand tracePVandLMNin the trend recorder. The response should be stable, no overshoot above 10 %, settling within 3 dominant time constants. - 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 |
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)
- Set
TD = T#0MS,DEADB_W = 0.0,TM_LAG = T#100MS. Switch to manual (MAN_ON = TRUE). - Bring
MANto a value that holdsPVat the desired operating point. ConfirmPVis stable for at least one time constant. - Switch to automatic (
MAN_ON = FALSE). Apply the Ziegler–Nichols PI formulas from Section 8.1. - Step
SP_INTby 5 %. Observe overshoot and settling. If overshoot > 15 %, reduceGAINby 30 % and increaseTIby 50 %. - If a residual steady-state error remains, reduce
TIin steps of 20 % until the error vanishes. - If the process has measurable dead time but you want faster settling, add derivative:
TD = 0.25 · TI, then reduceGAINby 10 % to compensate for the increased high-frequency gain. - Tune the disturbance feed-forward: wire
DISVto 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_HLMandLMN_LLMto 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±100if the actuator is narrower. - For bumpless transfer from manual to auto, set
MANto the actual actuator feedback (not to the last LMN_PER value) so the integrator starts at the right state. - Use
QLMNDTin 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.