Siemens FB41 LMN Output Stuck at ER×GAIN: COM_RST & I_SEL Fix

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

Problem Description

A Step 7 Professional V5.5 project is calling the standard PID block FB41 "CONT_C" from a cyclic interrupt organization block OB35 configured at 100 ms. The instance DB2215 shows all inputs wired, the setpoint (SP_INT) is 30, the process variable (PV_IN) is fed from a scaled analog input, and the manipulated value (LMN) is monitored online. Instead of ramping toward saturation as a textbook PI controller should, LMN sits at a flat value equal to the error (ER) multiplied by the gain. Changing GAIN from 0.01 to 10 shifts LMN from 0.1606 to 1.606 — exactly the proportional-only formula LMN(t) = I_ITLVAL + GAIN · ER_NORM(t) documented in the Siemens Standard PID Control manual (page 4-41). No integration windup, no derivative action, and no movement despite a sustained error.

This is one of the most common FB41 field failures on S7-300/S7-400 CPUs, and the symptoms almost always trace to one of three root causes: the integrator and derivative paths are disabled through I_SEL/D_SEL, the COM_RST pulse never reaches the block long enough to initialize the integrator, or MAN_ON is latched forcing the output to follow MAN instead of the PID algorithm. The remainder of this article walks through each root cause, the exact procedure to recover control, and the verification checks that prove the controller is alive.

FB41 CONT_C Architecture Overview

FB41 "CONT_C" is a continuous-action PID controller with one analog setpoint input, one analog process-value input, one analog manipulated-value output, and a manual/automatic mode toggle. Internally it implements the block diagram published in the Standard PID Control manual:

  • Setpoint branch: SP_INT → setpoint limiter → SP-format conversion
  • Process-value branch: PV_IN or PV_PER → PV-NORM → CRP_IN range conversion
  • Error formation: ER = SP_NORM − PV_NORM (with optional dead-band DEADB_W)
  • Three parallel paths multiplied by select switches: P-path (always on), I-path (I_SEL), D-path (D_SEL)
  • Integrator with I_ITLVAL pre-load, I_ITL_ON enable, and INT_HOLD freeze
  • Differentiator with T_D time and TD_FLT filter
  • Output scaler with LMN_FAC/LMN_OFF, LMN_HLM/LMN_LLM clamps, and final LMN/LMN_P/LMN_I/LMN_D outputs

The key equation that explains the observed behavior is the normalized proportional path:

LMN(t) = I_ITLVAL + GAIN · ER_NORM(t)   (with I_SEL = 0 and D_SEL = 0)

When I_SEL = 0 the integrator is bypassed entirely and LMN collapses to the proportional-only result. When D_SEL = 0 the derivative path is bypassed. With PV_IN stuck at a constant and a constant setpoint, ER is constant, and the output is a flat number. This is mathematically correct behavior for a P-only controller — not a bug.

Diagnosis first, code change second. Before touching COM_RST, MAN_ON, or the integrator selector, monitor SP_INT, PV_IN, ER, LMN_P, LMN_I, and LMN_D in a VAT. If LMN_I never changes while ER is non-zero, the integrator is disabled or has been reset. If LMN follows MAN exactly, MAN_ON = TRUE is the cause regardless of what the integrator is doing.

Root Cause 1 — Integrator and Derivative Are Disabled

The single most common reason a "PID" block on FB41 behaves like a P controller is that the integrator and/or differentiator are turned off through the selector inputs. With I_SEL = 0 the I-term contribution LMN_I stays frozen at the pre-load value I_ITLVAL; with D_SEL = 0 the D-term stays at 0. The expected action — LMN ramping to saturation while a constant error exists — is impossible without an integrator.

Required Parameter Settings

Input Meaning Value for Full PID Value for PI Value for P-only (current state)
I_SEL Enable integrator TRUE (1) TRUE (1) FALSE (0)
D_SEL Enable differentiator TRUE (1) FALSE (0) FALSE (0)
GAIN Proportional gain Process-tuned Process-tuned 0.01 (current)
TI Integral time (s) Process-tuned Process-tuned Ignored
TD Derivative time (s) Process-tuned Ignored Ignored

To reproduce the expected "LMN ramps to 100 % with constant error" behavior described in the field report, set I_SEL = TRUE while keeping D_SEL = FALSE. The integrator will then accumulate (GAIN · ER) / TI every block call. At OB35 = 100 ms the block is called every 100 ms, so an integral time of 1000 s accumulates 0.01 % of the proportional output per call for a step error of 100 % — the textbook ramp behavior.

Watch the TI units. TI is in seconds, not milliseconds. A TI of T#1s is 1.0 s, while a value of T#0s disables integration internally (the Standard PID Control manual documents this division-by-zero guard). TI must be greater than 0 for any integrator action.

Root Cause 2 — COM_RST Pulse Never Reaches the Block

FB41 initializes its internal integrator, differentiator, and the displayed LMN pre-load only when the COM_RST input is TRUE at the start of a call. The Siemens FAQ "What should you watch out for when calling and assigning parameters to the controller functions (S)FB41, (S)FB42, and (S)FB43?" states explicitly that COM_RST must be TRUE for one (and only one) call to trigger the initialization. If it is held TRUE for the entire run-up, or never becomes TRUE at all, the block can remain in a partially initialized state where the output never reaches expected operating points.

The recommended field pattern is:

  1. Create OB100 (warm restart). Inside OB100, set a BOOL tag (e.g. "InitPID") to TRUE.
  2. In OB1, call FB41 with COM_RST := "InitPID" and at the very last network of OB1 reset "InitPID" to FALSE.
  3. On a STOP→RUN transition the order of execution is: OB100 runs to completion first, then OB1 begins. When OB1 reaches FB41 on its first scan, COM_RST is TRUE, the block initializes, and the trailing network in OB1 clears COM_RST for all subsequent calls.

This pattern is sometimes called the "single-pulse COM_RST" and is the only documented correct usage. Holding COM_RST TRUE permanently causes FB41 to re-initialize every scan, which prevents LMN from following the PID algorithm between resets and locks the integrator to I_ITLVAL. The field report's manual edit-and-download approach (open the instance DB, set COM_RST = TRUE, download) is not equivalent to a controlled single-pulse reset because the online write does not affect the static variables inside the multi-instance nor does it synchronize with the OB35 call timing.

Recommended Code Snippet

// OB100 - Warm restart
SET
S "InitPID"     // COM_RST pulse flag
// OB1 - cyclic program
// Network 1: call PID
CALL FB41, DB2215
  COM_RST := "InitPID"
  MAN_ON  := FALSE
  I_SEL   := TRUE
  D_SEL   := FALSE
  SP_INT  := 30.0
  PV_IN   := "ProcessValue"
  GAIN    := 0.5
  TI      := T#5s
  TD      := T#0s
  LMN     := "ActuatorOutput"
  // ...

// Network 99: clear COM_RST pulse (LAST network in OB1)
A "InitPID"
R "InitPID"

Root Cause 3 — MAN_ON Latched to TRUE

If MAN_ON is TRUE, FB41 routes the value at input MAN directly to LMN and freezes the integrator at its current value. This is the manual-mode override and is the second most common cause of a stuck LMN. The block diagram shows a switch that selects between the PID output and the manual value; with MAN_ON = TRUE the switch stays in the manual position indefinitely until the user toggles it back to automatic.

Verify the MAN_ON state in a VAT and confirm it returns FALSE on every call. If the program logic drives MAN_ON from an HMI button or a sequence step, audit the tag that feeds it — a sticky HMI bit, a non-volatile flag, or a forgotten initialization in OB100 can leave the controller in manual across reboots.

OB35 Cycle Time Verification

The FB41 instance's CYCLE parameter sets the block's expected sampling time and is used for the discrete-time integration algorithm. The Siemens manual recommends that CYCLE match the actual call interval of the OB in which FB41 runs. The field report asks how to verify the OB35 cycle time — the answer is twofold:

  1. Hardware configuration: open HW Config, navigate to the CPU properties, and check the Cyclic Interrupts tab. OB35 has its own period field. A value of 100 000 µs corresponds to 100 ms. Confirm this matches the program expectation.
  2. Runtime measurement: use a VAT to monitor the system clock or a counter incremented inside OB35. A common pattern is:
    // OB35
    L "OB35Counter"   // DWORD
    + 1
    T "OB35Counter"   // counts calls

    Read OB35Counter at t0, wait 60 s, read it again at t1. The delta should equal 600 for a 100 ms period. Deviations above 5 % indicate the cyclic interrupt is being delayed by longer OBs (typically OB1 in error or oversized) or by the CPU scan-time watchdog.

CYCLE mismatch hides integrator behavior. If CYCLE in the FB41 instance is set to T#1s but the block is called every 100 ms, the discrete-time integral accumulates ten times faster than expected. The opposite mismatch (block called every 1 s but CYCLE = T#100ms) makes the integrator ten times slower. Always align CYCLE with the OB35 period in the instance DB at download time.

Step-by-Step Recovery Procedure

Use this procedure to bring a stuck FB41 instance back to a working PI/PID loop.

  1. Online open the instance DB (DB2215 in the field report) and put the CPU in STOP if you intend to make structural changes.
  2. Open a VAT on DB2215. Monitor the following addresses continuously during every test step:
    • DB2215.DBD12SP_INT
    • DB2215.DBD16PV_IN
    • DB2215.DBD20ER (calculated internally; visible at offset 22 per Siemens instance layout)
    • DB2215.DBD68LMN
    • DB2215.DBD72LMN_P
    • DB2215.DBD76LMN_I
    • DB2215.DBD80LMN_D
  3. Confirm the formula: with the current parameter set (GAIN = 0.01, I_SEL = 0, D_SEL = 0), verify that LMN equals ER × GAIN to four decimal places. If yes, the proportional path is healthy and only the integrator is missing.
  4. Enable the integrator by setting I_SEL := TRUE in the instance and forcing the value online. Re-verify: LMN_I should now begin ramping in the direction of ER.
  5. Add the COM_RST pulse following the OB100/OB1 pattern. Download in STOP, restart, and confirm LMN_I starts from I_ITLVAL (default 0.0) on the very first OB35 call after restart.
  6. Verify the OB35 period with the counter method above. Adjust CYCLE in the instance if needed.
  7. Confirm MAN_ON is FALSE at every call. If an HMI drives it, audit the button logic.
  8. Force a step response: change SP_INT online by 20 %, observe LMN tracking with the expected integral ramp and eventual saturation at LMN_HLM/LMN_LLM.

FB41 Parameter Reference Table

Parameter Direction Type Default Purpose
COM_RST IN BOOL FALSE Complete restart; TRUE for one call initializes the block
MAN_ON IN BOOL TRUE Manual mode toggle — TRUE routes MAN to LMN
SP_INT IN REAL 0.0 Setpoint in normalized range (0–100 % typical)
PV_IN IN REAL 0.0 Process variable, normalized
PV_PER IN INT 0 Process variable, peripheral (raw ADC value)
DISV IN REAL 0.0 Disturbance variable for feed-forward
INT_HOLD IN BOOL FALSE Freeze integrator output
I_SEL IN BOOL TRUE Enable integrator
I_ITL_ON IN BOOL FALSE Use I_ITLVAL as initial integrator value
I_ITLVAL IN REAL 0.0 Initial integrator value (used when I_ITL_ON and COM_RST fire)
D_SEL IN BOOL FALSE Enable differentiator
CYCLE IN TIME T#1s Block sample time; must match the calling OB period
GAIN IN REAL 2.0 Proportional gain
TI IN TIME T#20s Integral time (reset time)
TD IN TIME T#10s Derivative time
TM_LAG IN TIME T#2s Derivative low-pass time
DEADB_W IN REAL 0.0 Error dead-band width
PV_FAC IN REAL 1.0 PV multiplication factor
PV_OFF IN REAL 0.0 PV offset
LMN_FAC IN REAL 1.0 Output scaling factor
LMN_OFF IN REAL 0.0 Output offset
LMN_HLM IN REAL 100.0 Output high clamp
LMN_LLM IN REAL 0.0 Output low clamp
MAN IN REAL 0.0 Manual manipulated value
LMN OUT REAL Manipulated value output (real)
LMN_P OUT REAL Proportional component
LMN_I OUT REAL Integral component
LMN_D OUT REAL Derivative component
PV OUT REAL Process value (after PV_FAC/PV_OFF)
ER OUT REAL Effective error signal

STAT Variable Reference (Instance DB Layout)

The STAT section of the instance DB holds the integrator accumulator and the differentiator state. These are the addresses engineers usually want to inspect when FB41 behaves abnormally. The exact offsets depend on the FB41 source version; the values below correspond to the Standard Library FB41 shipped with Step 7 V5.5 and SCL/ STL calling convention.

Symbolic name Type Purpose
LMN_P REAL Proportional contribution; equals GAIN · ER
LMN_I REAL Integrator state. Watch this to confirm integration is alive
LMN_D REAL Derivative contribution; depends on d/dt of ER
PV REAL Process value after CRP_IN scaling
ER REAL Error = SP_NORM − PV_NORM, after dead-band
INT_HPOS BOOL Integrator upper limit reached
INT_HNEG BOOL Integrator lower limit reached
SP_NORM REAL Normalized setpoint
PV_NORM REAL Normalized process value
Watch LMN_I first. The fastest way to determine whether FB41 is integrating at all is to put LMN_I in a VAT watch, hold a constant error of 30 % for 60 s, and verify that LMN_I moves in the expected direction. A flat LMN_I confirms that the integrator is disabled, the TI value is wrong, or the integrator was reset to I_ITLVAL and held there.

Verification with a VAT Table

The VAT (Variable Table) tool inside Step 7 is the only practical way to diagnose FB41 in real time. Build a single watch table that includes the following rows in monitor/modify format:

Address          Symbol         Display    Modify value
DB2215.DBX0.0    COM_RST        BOOL       -
DB2215.DBX0.1    MAN_ON         BOOL       -
DB2215.DBX0.2    I_SEL          BOOL       -
DB2215.DBX0.3    D_SEL          BOOL       -
DB2215.DBD12     SP_INT         FLOAT      30.0
DB2215.DBD16     PV_IN          FLOAT      -
DB2215.DBD68     LMN            FLOAT      -
DB2215.DBD72     LMN_P          FLOAT      -
DB2215.DBD76     LMN_I          FLOAT      -
DB2215.DBD80     LMN_D          FLOAT      -
DB2215.DBD84     ER             FLOAT      -
MW100            OB35Counter    DEC        -

Power-cycle the CPU so OB100 runs. Confirm the COM_RST pulse is observed for exactly one scan of OB1 (visible as a single rising edge in DB2215.DBX0.0). Apply a step setpoint change. Verify the time-domain response matches the expected first-order-plus-dead-time behavior of the plant.

Common Pitfalls and Field-Proven Caveats

  1. Calling FB41 in OB1 instead of a time-interrupt OB. OB1 scan time is variable on S7-300/400; the discrete-time integral will produce jittery control. Use OB32, OB33, OB34, or OB35 — the dedicated cyclic interrupt OBs whose periods are guaranteed.
  2. FB41 multi-instance aliasing. If the project uses a multi-instance FB that calls FB41 internally, the COM_RST pulse must reach the inner instance. Place the reset in the calling FB, not in OB1 alone.
  3. Block call inside a conditional network. A FB41 call inside an IF condition that is not always TRUE effectively skips the integrator update on missed scans, causing windup or non-deterministic behavior.
  4. OB35 priority conflicts. OB35 has priority class 12 by default. If OB1 is in RUN and an error OB (OB80–OB87) fires, OB35 may be delayed. Monitor the diagnostic buffer for OB80 "time error" events.
  5. Spurious COM_RST from an HMI. If an HMI tag maps to COM_RST and the operator toggles a button, the integrator resets to I_ITLVAL. Use an HMI-tag-to-COM_RST path with a confirmed-clear after the single pulse.
  6. Watch the floating-point format. Inputs and outputs are REAL (IEEE-754 single precision). A connection from an INT analog input (such as PEW272) without first converting through FC105 "SCALE" or its REAL-equivalent will feed nonsense into PV_IN.
  7. CYCLE in instance vs. OB35 period. Step 7 V5.5 does not auto-update CYCLE from HW Config. Set it manually to match the OB35 period or to a known fixed value for documentation.
  8. Watch for LMN_HLM and LMN_LLM clamping. A symmetric ±100 % bipolar actuator setup needs LMN_HLM = 100.0 and LMN_LLM = -100.0. The default LMN_LLM = 0.0 will clip the output to unidirectional control and hide a negative error's effect on LMN_I ramp direction.

Cross-Reference to FB42 and FB43

The same COM_RST single-pulse rule applies to:

  • FB42 "CONT_S" — step-controller variant (used for servo-position control with integral-action pulse outputs)
  • FB43 "PULSEGEN" — pulse generator used in combination with FB41 for three-step or analog-with-duty-cycle final-control elements

The Siemens FAQ on parameter assignment for the controller blocks covers all three. Apply the same OB100-pulse pattern whenever any of these three blocks is initialized in a project.

Documentation References

The authoritative references for FB41 behavior are:

  • Siemens Standard PID Control manual (entry ID 388573) — defines the block diagram, normalized equations, and the integrator/differentiator internal structures
  • Siemens FAQ "What should you watch out for when calling and assigning parameters to the controller functions (S)FB41, (S)FB42 and (S)FB43?" (entry ID 23923925) — documents the single-pulse COM_RST requirement
  • Step 7 Professional V5.5 Online Help for FB41 — describes each input and output with default values

Always cross-check the parameter definitions against the Standard PID Control manual and the FB41/42/43 calling FAQ before commissioning a closed loop. The block is mathematically documented, but the operating-mode and initialization rules are field-tested and enforced by Siemens support.

Why does my FB41 LMN output stay flat at ER × GAIN even with a sustained error?

Because I_SEL = 0 in the instance DB disables the integrator branch and the controller collapses to a P-only controller. With a constant error and no integrator, the output cannot ramp — it is mathematically forced to remain at the proportional value. Set I_SEL := TRUE and ensure TI > 0 s to enable integration.

What is the correct way to issue COM_RST to FB41 in Step 7 V5.5?

Set a BOOL tag to TRUE in OB100, feed it into the COM_RST input of FB41 in OB1, and clear the tag at the last network of OB1. This produces a single-cycle TRUE pulse that initializes the integrator, differentiator, and the I_ITLVAL pre-load exactly once per restart. The Siemens FAQ entry ID 23923925 documents this pattern.

How do I verify that OB35 is actually running at 100 ms in my S7-300/S7-400 CPU?

Open HW Config, inspect the CPU's Cyclic Interrupts tab, and confirm OB35's period is 100 000 µs. Then implement a counter incremented inside OB35 and measure the count delta over a 60-second wall-clock interval. The expected count is 600 for a 100 ms period; deviations above 5 % indicate scan-time overruns or OB80 "time error" events.

What is the difference between LMN, LMN_P, LMN_I, and LMN_D in FB41?

LMN_P is the proportional component (GAIN · ER), LMN_I is the integrator accumulator state, LMN_D is the derivative component, and LMN is the final sum of all enabled contributions after scaling by LMN_FAC/LMN_OFF and clamping by LMN_HLM/LMN_LLM. Monitoring all four in a VAT is the fastest way to see which path is alive or stuck.

Why does my FB41 output follow MAN exactly and ignore the PID calculation?

Because MAN_ON = TRUE forces FB41 into manual mode and routes the value at input MAN directly to LMN, while the integrator is frozen. The controller stays in manual until MAN_ON is cleared. Audit any HMI tag or sequence step that drives MAN_ON, and confirm it returns FALSE on every scan except during operator-driven manual overrides.

Back to blog