1. Overview of PID Control on S7-300 / S7-400
The SIMATIC S7-300 and S7-400 CPUs ship with a Standard PID Control library that contains the FB41 "CONT_C" continuous-action PID block used in countless closed-loop applications (pressure, flow, temperature, level, position, gas concentration). FB41 is a software PID function block — not a hardware controller — that runs in OB35 (or any cyclic interrupt OB) and is fully integrated in STEP 7 V5.3 and later. The block is located in the Standard Library → "PID Control Blocks" program folder and can be copied into any S7-300 / S7-400 user program without licensing.
FB41 implements a parallel (non-interacting) PID structure with anti-windup, derivative filtering, ramp-rate limited setpoint, manual-to-auto bumpless transfer, and dual output paths (analog LMN in 0.0–100.0 % and LMN_PER as a peripheral word 0–27648). When the task is a single continuous actuator (proportional valve, thyristor power controller, variable-speed drive in torque mode) FB41 is the default choice. For pulse-width modulated outputs use FB42 "CONT_S"; for step controllers with integral actuator (motorised valve) use FB43 "PULSEGEN" with FB41.
The reference for parameter behaviour is the Siemens Standard PID Control manual (entry ID 10859203) and the TIA Portal help page "Controller structures (S7-300, S7-400)" (see Controller structures (S7-300, S7-400)).
2. Prerequisites and Installation
Before instantiating FB41 confirm the engineering environment and hardware interface points meet the following requirements:
- STEP 7 V5.3 or later (recommended V5.5 + SP4 / HF7 for Windows 10 compatibility). The PID Control library is installed with the default STEP 7 setup; if missing, run the SETUP.EXE from the Standard Library DVD.
- SIMATIC S7-300 CPU 312C through 319F-3 PN/DP, or S7-400 CPU 412–417. FB41 occupies 590 bytes of instance-DB work memory and 1 FB slot.
- One analog input channel (4–20 mA, 0–10 V, RTD, or TC) wired to the process variable (PV) sensor.
- One analog output channel (4–20 mA or 0–10 V) for the actuator reference, or a PROFIBUS/PROFINET word to a drive.
- Cyclic interrupt OB (OB35) configured for a 100 ms–1 s cycle. Standard loop time for thermal loops = 1 s; pressure/flow = 100–250 ms; fast position = 50–100 ms.
SAMPLE_T to match the OB35 cycle. If you change OB35 cycle, update SAMPLE_T on the block (input CYCLE in seconds) to keep the integral/derivative terms dimensionally correct.3. FB41 CONT_C Block Architecture
The block diagram from the Siemens Standard PID Control manual is reproduced in the schematic below. The error signal ER = SP_INT − PV is fed into a parallel PID branch. The P, I, and D branches are summed, clipped to 0–100 %, and exported as LMN. A separate scaled path produces LMN_PER for direct output to a peripheral word (0–27648).
The derivative action is applied to the process variable (not the error) by default, eliminating derivative kicks on setpoint changes. A first-order low-pass filter TM_LAG smooths the derivative channel. Internal integrator clamping prevents wind-up when the actuator saturates (this is the "anti-windup" block in the diagram above).
4. I/O Pin Map of FB41
The complete input / output list from the Standard PID Control manual (Siemens entry 10859203) is shown below. The instance-DB (e.g. DB30) exposes all I/O as named tags; you read/write them with symbolic access (e.g. DB30.SP_INT) or with the LAD/FBD instance DB view.
| Pin | Direction | Type | Range / Units | Function |
|---|---|---|---|---|
| SP_INT | IN | REAL | -100.0 to 100.0 % | Internal setpoint in engineering units (0–100 % normalised). Set via HMI / recipe. |
| PV_IN | IN | REAL | -100.0 to 100.0 % | Process value already scaled to 0–100 %. |
| PV_PER | IN | WORD | 0–27648 | Raw peripheral value (e.g. PIW 288). Use when PVPER_ON = TRUE. |
| PVPER_ON | IN | BOOL | TRUE / FALSE | TRUE = use PV_PER, FALSE = use PV_IN. |
| GAIN | IN | REAL | ≥ 0 | Proportional gain (dimensionless). Typical 0.5–5.0. |
| TI | IN | REAL | ≥ 0.0 s | Integral action time (reset time). Set to 0.0 to disable I. |
| TD | IN | REAL | ≥ 0.0 s | Derivative action time. Set to 0.0 to disable D. |
| TM_LAG | IN | REAL | ≥ 0.0 s | Time constant of derivative low-pass filter (typical = TD). |
| DEADB_W | IN | REAL | ≥ 0.0 % | Dead band width on error. 0 = off. |
| LMN_HLM | IN | REAL | LMN_LLM–100.0 | Manipulated-value high limit (e.g. 100.0). |
| LMN_LLM | IN | REAL | 0.0–LMN_HLM | Manipulated-value low limit (e.g. 0.0). |
| PV_FAC | IN | REAL | — | Multiplier applied to PV_PER before scaling to %. |
| PV_OFF | IN | REAL | — | Offset added to PV after multiplication. |
| LMN_FAC | OUT | REAL | — | Factor applied to LMN to produce LMN_PER. |
| LMN_OFF | OUT | REAL | — | Offset added to LMN to produce LMN_PER. |
| MAN | IN | REAL | 0.0–100.0 % | Manual manipulated value. |
| MAN_ON | IN | BOOL | TRUE / FALSE | TRUE = manual mode, FALSE = automatic. |
| CYCLE | IN | REAL | ≥ 0.001 s | Sample time of the block, must match OB35 period. |
| SP_INT_HLM / SP_INT_LLM | IN | REAL | 0–100 | Setpoint ramp high/low clamps. |
| LMN | OUT | REAL | 0.0–100.0 % | Effective manipulated value (scaled). |
| LMN_PER | OUT | WORD | 0–27648 | Manipulated value for direct output to PQW. |
| PV | OUT | REAL | 0.0–100.0 % | Scaled effective process value. |
| ER | OUT | REAL | -100.0 to 100.0 % | Effective error. |
Internal status outputs LMN_P, LMN_I, LMN_D, I_ITVAL, and DISV are visible only in the instance DB and are useful for online tracing of each branch contribution during commissioning.
5. Step-by-Step Configuration
- Open STEP 7 and the project. In SIMATIC Manager, expand the S7-300 station and double-click the Blocks folder.
-
Open the PID library. File → Open → Library → "Standard Library" → "PID Control Blocks". You will see
FB41throughFB43, plus the UDTs (data type 1 forCONT_C). -
Copy FB41 into the project. Drag
FB41from the library into the project Blocks folder. Confirm the version (FB41 V5.0 ships with STEP 7 V5.3+; V5.1 in V5.4 SP1+). -
Create the instance DB. In the project Blocks folder, insert a new DB and assign "FB41" as the function block. Rename the DB to something meaningful, e.g.
DB30 "PID_N2_PRESS". STEP 7 auto-generates the instance view with all I/O. -
Call FB41 from OB35. Open OB35 (Cyclic Interrupt). In the first network insert:
CALL "PID_N2_PRESS" , DB30 SP_INT := MD100 // setpoint %, 0.0–100.0 PV_IN := MD104 // process value already normalised to 0–100 % PV_PER := MW106 // e.g. PIW288 (4–20 mA, 0–27648) PVPER_ON := M110.0 // TRUE = use PV_PER GAIN := 1.2 // tuning parameter TI := T#30s // reset time TD := T#0s // derivative disabled MAN := 0.0 MAN_ON := M110.1 LMN_HLM := 100.0 LMN_LLM := 0.0 CYCLE := 0.1 // 100 ms OB35 LMN_PER := PQW 290 // 4–20 mA to actuator LMN := MD200 -
Wire the peripheral I/O. In HW Config, ensure the AI module (e.g. SM331 6ES7331-1KF02-0AB0) is configured for 4-wire 4–20 mA and that the AO module (SM332 6ES7332-5HD01-0AB0) is 0–10 V or 4–20 mA. FB41's
PV_PERinput maps to the PIW,LMN_PERoutput to the PQW. -
Configure OB35 cycle. HW Config → CPU properties → Cyclic Interrupts → set OB35 to 100 ms. Alternatively, change
CYCLEon FB41 to match any other OB35 period. - Compile and download. Select the S7 program → PLC → Download. Open the instance DB online and verify the tags update each cycle.
6. Scaling the Process Variable
If PVPER_ON = TRUE the block performs scaling internally:
PV (in %) = ( PV_PER / 27648 ) * PV_FAC + PV_OFF
Use this when your sensor is already in the same engineering range (e.g. 4 mA = 0 %, 20 mA = 100 %). For a 0–10 bar pressure transmitter with 4–20 mA and 0 % = 0 bar, 100 % = 10 bar, set PV_FAC = 100.0, PV_OFF = 0.0. For a 4–20 mA transmitter that maps 4 mA to 0.5 bar and 20 mA to 8 bar use the FC105 SCALE block (Standard Library → TI-S7 Converting Blocks) upstream and pass the scaled REAL to PV_IN with PVPER_ON = FALSE. The FC105 formula is:
OUT = [ (FLOAT(IN) - K1) / (K2 - K1) ] * (HI_LIM - LO_LIM) + LO_LIM
For LMN_PER to drive a 4–20 mA output the block computes:
LMN_PER = ( LMN * LMN_FAC + LMN_OFF ) * 276.48
With default LMN_FAC = 1.0 and LMN_OFF = 0.0, LMN = 50.0 % produces LMN_PER = 13824 ≈ 12 mA on a 4–20 mA output.
7. Tuning Procedure
FB41 does not include an auto-tuner; tuning is performed with the closed-loop step-response method (Chien-Hrones-Reswick, Ziegler-Nichols) or with the open-loop "bump test" technique. The recommended field procedure for an S7-300 application is:
- Put the controller in manual (
MAN_ON = TRUE) and drive the actuator to 30 %, 50 %, 70 % while loggingPVfrom a WinCC trend or the STEP 7 variable table. - Determine the plant gain
Kp = ΔPV / ΔMV(in %/% in this normalised world) and the dominant time constantT1(time to reach 63 % of the steady-state PV) plus the dead timeTt(time between MV step and the start of PV movement). - Calculate tuning constants using the Chien-Hrones-Reswick (CHR) formulas for 0 % overshoot, setpoint regulation:
| Mode | GAIN (Kc) | TI | TD |
|---|---|---|---|
| PI (no overshoot, regulator) | 0.3 * (Tt / Kp)⁻¹ = 0.3 / Kp * Tt⁻¹ | 3.3 * Tt | 0 |
| PI (0 % overshoot, servo) | 0.35 / Kp * Tt⁻¹ | 1.2 * T1 | 0 |
| PID (CH-R 0 % overshoot) | 0.6 / Kp * Tt⁻¹ | 1.0 * T1 | 0.5 * Tt |
| PID (CH-R 20 % overshoot) | 0.95 / Kp * Tt⁻¹ | 1.4 * T1 | 0.47 * Tt |
- Write
GAIN,TI(seconds),TD(seconds) into the instance DB. IfTI = 0.0the I branch is disabled, likewiseTD = 0.0disables D. InitialiseTM_LAG = TD / 5to prevent derivative noise amplification. - Set
MAN_ON = FALSE(auto). Drive a small setpoint step (5 % of span). Observe the trend; if the loop oscillates, halveGAIN; if sluggish, increaseGAINby 25 %. - For pressure/level control with integrating behaviour, disable D and tune PI only; a too-aggressive D on a noisy PV creates jitter in the actuator.
MAN_ON = TRUE with MAN = 0 % on CPU STOP, because FB41 freezes the last LMN on STOP and may leave the actuator in a dangerous position.8. Commissioning and Verification
Follow this verification sequence after the initial download:
- Check the wiring. With PLC in STOP, measure the sensor mA at the AI terminals; verify 4 mA = 0 % and 20 mA = 100 % in the online instance DB. Reverse polarity or missing 24 V transducer supply is the most common first-day failure.
-
Check the OB35 cycle. In OB1, add a 1 s timer and toggle a flag; compare to the OB35 instance DB field
CYCLE. If they drift you have time-base corruption; re-verify with the diagnostic buffer (Diagnostic Event ID 0x2A09 "OB35 time error"). -
Check the loop direction. Set
MAN = 50 %,MAN_ON = TRUE. If PV moves opposite of expected, the actuator feedback is reversed. Either swap thePV_FACsign, swap the analogue output wiring, or invert the error sign internally by feeding−PV_IN. -
Run the open-loop step test. Step
MANfrom 30 → 50 %, capturePVin the trend, derive Kp, T1, Tt, then enter the tuning values from §7. -
Run the closed-loop setpoint step. With
MAN_ON = FALSE, changeSP_INTby 10 %, capture the resultingPV,LMN, andERtrends. Compute rise time, overshoot, settling time, and IAE (Integral Absolute Error) as objective KPIs. -
Verify bumpless transfer. Toggle
MAN_ONwhile in steady state. TheLMNshould not jump by more than 0.1 %; FB41 loads the internal integrator with the current LMN on every auto-to-manual transition.
9. Anti-Windup, Bumpless Transfer, and Setpoint Ramps
Anti-windup in FB41 is implemented by clamping the integrator to keep the sum of P + I + D within the configured LMN_HLM / LMN_LLM. If you wire PV_PER from a sensor that can fail to 0 mA (open wire) the controller will integrate the full error and saturate. To detect a wire-break, monitor PV_PER > 32511 (overrange) and force MAN_ON = TRUE with MAN = 0; this is the standard "sensor fail" handling pattern.
Setpoint ramps (useful in batch start-ups) are configured by setting SP_INT_HLM and SP_INT_LLM equal to the current SP_INT, then overwriting SP_INT at a controlled rate from OB35. FB41 itself does not provide an internal ramp generator; a small FB wrapper or a separate ramp block is the usual implementation. For batch thermal processes this is mandatory to avoid overshoot on start-up.
10. Common Errors and Troubleshooting Matrix
| Symptom | Likely Root Cause | Diagnostic / Fix |
|---|---|---|
| LMN_PER stuck at 0 or 27648 | AI wire break (0 mA) or short (≥22 mA). PV_PER overrange / underrange flag set. | Check PV_PER > 32511 (overrange) or PV_PER < 0 (underrange). Verify sensor supply. Force MAN_ON = TRUE on fault. |
| Output cycles between 0 and 100 % at full speed | Loop sign reversed (direct vs reverse acting) or GAIN negative. |
Verify ER = SP − PV; for heating/cooling pick the correct action and confirm wiring. |
| Process never reaches setpoint | Anti-windup not released (LMN saturating). TI too long or P-only mode. |
Reduce GAIN, shorten TI, enable I. Check LMN_HLM/LMN_LLM are not artificially narrow. |
| High-frequency jitter on LMN | Derivative noise on PV (no TM_LAG or too small). Cycle time too fast. |
Increase TM_LAG to TD; increase OB35 cycle to 250–500 ms; add analog input filter in HW Config. |
| Large bump on AUTO→MANUAL | Forgotten bumpless-transfer logic; integrator initialised to 0. | FB41 handles this automatically only if MAN_ON is toggled without changing MAN. Use a HMI that exposes only the AUTO/MAN button, not the MAN value field. |
| SF LED on CPU, OB35 startup event missing | OB35 cycle below minimum, or OB35 not loaded. | Diagnostic buffer ID 0x2370 "Time error". Increase cycle to ≥1 ms (CPU-dependent) or accept watchdog alarm. |
| FB41 input DB initial values all zero, integrator never moves | Instance DB is uninitialised and CPU started in cold-restart with process data = 0. | Initialise GAIN = 0.0 before first call; or feed the call from OB100 (warm restart) to preset integrator. |
| Loop works in simulation, oscillates on real plant | Actuator dead-band (e.g. control valve with stem packing) and on-the-fly load changes not modelled. | Add DEADB_W = 0.5–2.0 %; pre-load from a feedforward signal. |
11. HMI / WinCC Integration
Expose the instance DB tags as WinCC variables to provide operator control of mode, setpoint, and tuning. Recommended faceplate items:
- SP_INT — numeric I/O field, 0.0 to 100.0 %.
- PV — output field only, 0.0 to 100.0 %.
- LMN — output field only, 0.0 to 100.0 %.
- MAN_ON — binary tag, "Auto / Manual".
- MAN — numeric I/O field, visible only in manual mode.
- GAIN, TI, TD, TM_LAG — read-only tags, password-protected write access (level "Tuning").
- ER, LMN_P, LMN_I, LMN_D — internal branch contributions, useful for trend views during commissioning.
Group the Auto/Manual button and the MAN value with visibility animation in WinCC to enforce the rule that operators must not change MAN while AUTO is active. Place PV and SP_INT on a bar-graph display alongside LMN for a single-glance view of regulation health.
12. Migration Notes: STEP 7 V5.5 to TIA Portal
FB41 is binary-compatible. When migrating an S7-300 program to TIA Portal V16+, the block and its instance DB are ported as-is via "Migrate project". Re-instantiate the block from the "PID_Compact" library if the application is new to TIA Portal — PID_Compact (S7-1500) or PID_Basic (S7-1200) integrate auto-tuning, but the FB41 V5.x structure is still supported on S7-300 / S7-400 in TIA Portal V19 for legacy migration. If the S7-300 CPU is replaced by an ET 200SP CPU 1510SP-1 PN or S7-1500, plan a re-tuning campaign because the loop time granularity and floating-point behaviour differ.
On the S7-1500 side, PID_Compact (FB 1139) replaces FB41 with similar inputs and built-in pretuning / fine-tuning; documentation is at Controller structures (S7-300, S7-400).
Where is FB41 located in STEP 7 and which versions ship with it?
FB41 is in the Standard Library → "PID Control Blocks" folder. It is included with every STEP 7 V5.3 and later installation. Open the library from the File menu in SIMATIC Manager, drag the block into your project Blocks folder, and create an instance DB (e.g. DB30). FB41 V5.0 ships with STEP 7 V5.3+; FB41 V5.1 ships with V5.4 SP1 and later.
Which OB should call FB41, and what cycle time should I use?
Call FB41 from a cyclic interrupt OB (typically OB35) so the loop runs at a deterministic rate, not from OB1. Configure the OB35 cycle to 100 ms for pressure / flow, 250–500 ms for level, and 1 s for thermal loops. Set FB41's CYCLE input to the same value in seconds (0.1, 0.25, 0.5, 1.0) so the integral and derivative terms are dimensionally correct.
Why does LMN_PER stay at 0 or 27648 when the controller is running?
The most common cause is a sensor wire break: 0 mA or >22 mA drives PV_PER to the underrange / overrange limit and FB41 saturates. Monitor the wire-break flag (PIW > 32511 or < 0) and force MAN_ON = TRUE with MAN = 0 on fault. The second-most common cause is forgetting to wire PVPER_ON = TRUE when using PV_PER.
How do I tune FB41 without an auto-tuner?
Run a manual bump test: put the loop in manual (MAN_ON = TRUE), step MAN by 20 % of span, record PV in a trend, and read the plant gain Kp, dominant time constant T1, and dead time Tt. Apply the Chien-Hrones-Reswick formulas (0 % overshoot, regulator mode: GAIN = 0.3 / (Kp · Tt), TI = 3.3 · Tt, TD = 0). Then fine-tune in auto using small setpoint steps.
What is the difference between FB41, FB42, and FB43?
FB41 (CONT_C) is a continuous controller that outputs a 0–100 % analog signal. FB42 (CONT_S) is a step controller with binary output for integrating actuators. FB43 (PULSEGEN) is a pulse-width modulator used with FB41 to drive heating/cooling contactors from the continuous LMN signal. Use FB41 for proportional valves, drives in torque mode, and thyristor power controllers; use FB41 + FB43 for solid-state relay pulsed heating.
Why does the loop oscillate after I switch from manual to automatic?
If you change the MAN value manually while MAN_ON = TRUE and then flip to auto, FB41 keeps the internal integrator aligned with the last LMN, so the transition is bumpless only if you toggle MAN_ON without touching MAN. If oscillation persists after the transition, the sign of the loop is reversed, the derivative time constant is too short, or the dead time is larger than the integrator can compensate. Verify the process reaction direction, increase TM_LAG, and re-derive tuning constants.