S7-1200 PID_Compact Dynamic OutputUpperLimit Changes in TIA

David Krause11 min read
S7-1200SiemensTutorial / 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

Overview: Why Change PID_Compact Output Limits at Runtime

The PID_Compact technology object in the SIMATIC S7-1200 (firmware V4.0 and later) exposes a configurable OutputUpperLimit and OutputLowerLimit pair that bounds the manipulated variable (MV) before it is written to the analog output or the PWM channel. The default configuration assumes a fixed actuator range defined during commissioning (for example, a 0–10 V proportional valve scaled to 0–27648 raw counts, or a 4–20 mA valve mapped to a user-engineering range).

Many process applications require the upper output bound to be re-computed while the controller is in Automatic mode, without downloading a re-compiled program. Typical scenarios include:

  • Multi-product batch lines where each recipe defines a different valve authority band.
  • Adaptive heating mantles that must cap duty cycle based on measured heater resistance drift.
  • Pressure-control loops where the maximum pump stroke must be reduced when the system pressure approaches a hardware safe-maximum.
  • Energy-management schemes that derate the actuator output during peak-tariff windows.

The TIA Portal configuration editor freezes OutputUpperLimit and OutputLowerLimit as configuration values of the PID technology object, but the underlying technology data block (instance DB) is a normal optimized or standard DB that the user program can write to at runtime. This article documents both the direct write path and the recommended NORM_X / SCALE_X rescaling path, with working SCL and LAD samples.

PID_Compact Technology Object and Instance DB Layout

When you drag PID_Compact from Technology > PID Control > Compact PID into an OB or FB, the compiler generates a technology DB (default name <InstanceName>_DB) and a background DB that holds the run-time parameters. Two important structures exist:

DB Region Symbolic Tag Data Type Function
Configuration Config.OutputUpperLimit REAL Static upper MV limit, written at commissioning and at restart of the technology object.
Configuration Config.OutputLowerLimit REAL Static lower MV limit.
Runtime Retain.CtrlParams.OutputUpperLimit REAL Active upper MV limit used in the current cycle after PID_Compact initialisation.
Runtime Retain.CtrlParams.OutputLowerLimit REAL Active lower MV limit.
Output Output REAL Saturated manipulated variable (already clamped).
Output OutputPER REAL Scaled analog output, typically 0–100 % to drive Output_PWM or OutputPER mapping.
Important: The exact symbolic path depends on the TIA Portal version. In V14–V17 the structure is grouped under Config and Retain.CtrlParams. From V18 onward the layout was reorganised and the active limits are exposed at Config.OutputUpperLimit and mirrored under Retain.CtrlParams. Always confirm the path with the online & diagnostics view of the technology object on the live CPU before writing.

To find the absolute byte offset for an HMI tag or a non-SCL write:

  1. Open the project, expand PLC > Technology objects > PID_Compact_1 [DB].
  2. Switch the DB view to All (right-click the column header).
  3. Right-click the OutputUpperLimit tag and select Copy > Symbolic name or Copy > Address (for non-optimised DBs).
  4. For optimised DBs, the offset is hidden; use the symbolic name exclusively or disable the Optimised block access attribute in the DB properties if cross-device access is required.

Method 1: Direct Write to OutputUpperLimit in the Instance DB

The simplest approach is to overwrite the active runtime tag in the technology DB from user code. The change is picked up by PID_Compact on the next call, no re-initialisation is needed as long as the controller is in Automatic (mode = 3) and sRetain.CtrlParams.bUpdate is not active.

Symbolic write in SCL (recommended for readability):

// FB "RecipeControl" - cycle every 100 ms
IF #RecipeChange THEN
    // Read upper limit from the active recipe data block
    "PID_Compact_1".Retain.CtrlParams.OutputUpperLimit := #CurrentRecipe.MaxMV;
    "PID_Compact_1".Retain.CtrlParams.OutputLowerLimit := #CurrentRecipe.MinMV;
    #RecipeChange := FALSE;
END_IF;

Symbolic write in LAD:

  1. Insert a normally-open contact tag_RecipeChange.
  2. Add two MOVE blocks: source CurrentRecipe.MaxMV → destination "PID_Compact_1".Retain.CtrlParams.OutputUpperLimit, and CurrentRecipe.MinMV → destination "PID_Compact_1".Retain.CtrlParams.OutputLowerLimit.
  3. Reset the change flag with a coil tag_RecipeChange.

Absolute-address write (legacy CPUs or non-optimised DBs):

// Only valid when the technology DB is non-optimised
// "PID_Compact_1".Retain.CtrlParams.OutputUpperLimit at DBWxxx (check online view)
L  "CurrentRecipe".MaxMV         // load REAL from recipe DB
T  "PID_Compact_1_DB".OutputUpperLimit_REAL   // symbolic name in classic STEP 7
Engineering rule: Always make OutputLowerLimit < OutputUpperLimit before the write. PID_Compact treats an inverted range as configuration invalid and enters Error state (Status word bit Error = TRUE, error code 16#8001 "Invalid configuration of the technology object"). Validate the recipe data in a separate function block before the write.

Method 2: External Rescaling with NORM_X and SCALE_X

The second, more conservative approach leaves the PID technology object untouched and post-processes its native 0–100 % output into any engineering range you require. The advantage is that the PID remains configured for a canonical 0–100 % span, which simplifies simulation, HMI trending, and controller tuning. The disadvantage is that the controller no longer knows the true plant authority, so anti-windup behaviour is purely numeric and you must handle clamping in the user program.

Pipeline:

  1. Read "PID_Compact_1".Output (REAL, percent of OutputUpperLimit − OutputLowerLimit).
  2. Normalise to 0.0–1.0 with NORM_X(MIN := 0.0, MAX := 100.0, VALUE := PID.Output).
  3. Scale to the dynamic engineering range with SCALE_X(MIN := CurrentRecipe.MinMV, MAX := CurrentRecipe.MaxMV, VALUE := NormResult).
  4. Clamp the result against the recipe range and the hardware safe envelope.
  5. Write the scaled value to the analog output word (for example, QW96 after a manual linearisation).
// SCL: dynamic rescale of PID_Compact output
"PID_Compact_1"();   // call from OB1 or a cyclic OB30

#NormOut := NORM_X(MIN := 0.0, MAX := 100.0, VALUE := "PID_Compact_1".Output);

#ScaledOut := SCALE_X(MIN := #Recipe.MinMV, MAX := #Recipe.MaxMV, VALUE := #NormOut);

// Anti-windup clamp
IF #ScaledOut > #HardwareSafeMax THEN
    #ScaledOut := #HardwareSafeMax;
END_IF;
IF #ScaledOut < #HardwareSafeMin THEN
    #ScaledOut := #HardwareSafeMin;
END_IF;

"MV_to_Plant" := #ScaledOut;

The same pattern can be implemented with the legacy SCALE and UNSCALE instructions if you are on TIA Portal V13 or older. SCALE expects an integer input (0–27648) and returns a REAL scaled between configured MIN and MAX; UNSCALE does the reverse. To use the legacy blocks, multiply PID_Compact output by 276.48 to map percent to raw counts before SCALE.

Working SCL Function Block: DynPIDLimiter

The following self-contained FB can be dropped into any S7-1200 project. It encapsulates the safe write path, the recipe validation, the ramp limiter, and the HMI-readable status word.

FUNCTION_BLOCK "DynPIDLimiter"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT
      i_Enable        : BOOL;          // Master enable
      i_NewMaxMV      : REAL;          // Requested upper MV (%)
      i_NewMinMV      : REAL;          // Requested lower MV (%)
      i_Apply         : BOOL;          // Rising edge triggers the write
      i_RampLimit     : REAL := 5.0;   // Max delta per second (%/s)
   END_VAR

   VAR_OUTPUT
      o_AppliedMaxMV  : REAL;          // What was actually written
      o_AppliedMinMV  : REAL;
      o_Active        : BOOL;          // TRUE after successful write
      o_Error         : BOOL;
      o_Status        : WORD;          // 16#0000 OK, 16#8001 range invalid, ...
   END_VAR

   VAR
      s_LastApply     : BOOL;
      s_TargetMax     : REAL;
      s_TargetMin     : REAL;
      s_LastTime      : TIME;
      "PID_Compact_1" : PID_Compact;   // Multi-instance or call via parameter
   END_VAR

BEGIN
   // 1) Edge detection on Apply
   IF i_Enable AND i_Apply AND NOT s_LastApply THEN
      // 2) Validate range
      IF i_NewMaxMV <= i_NewMinMV THEN
         o_Error := TRUE;
         o_Status := 16#8001;
      ELSIF i_NewMaxMV < 0.0 OR i_NewMinMV < 0.0 OR i_NewMaxMV > 100.0 THEN
         o_Error := TRUE;
         o_Status := 16#8002;
      ELSE
         s_TargetMax := i_NewMaxMV;
         s_TargetMin := i_NewMinMV;
         o_Error := FALSE;
         o_Status := 16#0000;
      END_IF;
   END_IF;
   s_LastApply := i_Apply;

   // 3) Ramp limiter
   IF o_Active THEN
      // dt in seconds since last cycle
      // Use TIA built-in time arithmetic; here simplified:
      IF o_AppliedMaxMV < s_TargetMax THEN
         o_AppliedMaxMV := o_AppliedMaxMV + (i_RampLimit * 0.1);
         IF o_AppliedMaxMV > s_TargetMax THEN o_AppliedMaxMV := s_TargetMax; END_IF;
      ELSIF o_AppliedMaxMV > s_TargetMax THEN
         o_AppliedMaxMV := o_AppliedMaxMV - (i_RampLimit * 0.1);
         IF o_AppliedMaxMV < s_TargetMax THEN o_AppliedMaxMV := s_TargetMax; END_IF;
      END_IF;
      // mirror for Min if needed
      o_AppliedMinMV := s_TargetMin;

      // 4) Write to technology DB
      "PID_Compact_1".Retain.CtrlParams.OutputUpperLimit := o_AppliedMaxMV;
      "PID_Compact_1".Retain.CtrlParams.OutputLowerLimit := o_AppliedMinMV;
   ELSE
      o_AppliedMaxMV := "PID_Compact_1".Retain.CtrlParams.OutputUpperLimit;
      o_AppliedMinMV := "PID_Compact_1".Retain.CtrlParams.OutputLowerLimit;
      o_Active := TRUE;
   END_IF;
END_FUNCTION_BLOCK
Memory note: The Retain.CtrlParams region is retain, meaning the value survives a CPU stop-start. If you change the limit while the CPU is in STOP and then transition to RUN, the new value is loaded into the technology object during initialisation. If you need the new value to apply on the very first cycle after a restart, write it from the startup OB (OB100) before PID_Compact is first called in OB1.

Edge Cases, Watchdogs, and Bumpless Transfer

Three field-proven failure modes appear regularly when limits are re-written at runtime. Address them explicitly:

  1. Bumpless transfer during a recipe change. If the new OutputUpperLimit is lower than the current PID output, the algorithm clamps immediately and may produce a step on the plant. Either ramp the output through a rate limiter as shown in the sample FB, or pre-position the setpoint and the output before the change.
  2. Loss of HMI / recipe source. If the recipe connection is lost mid-cycle, the previously written value is retained. Add a watchdog (for example, a 5 s timeout) that re-asserts the last valid value; never write zero or 100 % as a default.
  3. PID_Compact mode transitions. When the controller transitions from Inactive (mode 0) to Automatic (mode 3), the technology object re-loads its configuration from Config.OutputUpperLimit and ignores anything in Retain.CtrlParams that was written while the controller was stopped. If the recipe-driven limit must survive a re-start, write to both the configuration path and the retain path, or write the recipe value from OB100 on every warm restart.

TIA Portal Version Compatibility

TIA Portal Version PID_Compact Version Tag Path to Active Limit Notes
V13 / V14 V1.x Retain.CtrlParams.OutputUpperLimit First release with PID_Compact; SCALE_X / NORM_X available from V13 SP1.
V15 / V15.1 V2.x Same as V14 Bug fix: writing during Manual (mode 4) is ignored; switch to Automatic first.
V16 / V17 V3.x Same as V14 Added OutputScaling.UpperPointIn / UpperPointOut for piecewise linear mapping.
V18 / V19 V4.x Config.OutputUpperLimit (mirrored to Retain) New structure; the original Retain.CtrlParams path remains valid for backward compatibility but is documented as deprecated.

For the latest official documentation, see the SIMATIC S7-1200 Programmable Controller System Manual and the PID_Compact V4 Function Block Manual. Always cross-check with the entry-point “PID control with S7-1200” in the Siemens Online Support.

Verification and Commissioning Procedure

  1. Static check. Compile and download. Open Online & Diagnostics > PID_Compact_1 > Commissioning. Set the input to a step value, force the controller to Manual, and verify the output clamps at the new upper limit by forcing a setpoint above the configured scale.
  2. Watch table test. Create a watch table with the technology DB and enter a new value into OutputUpperLimit. With the controller in Automatic, the next cycle should reflect the change. Capture sRetain.CtrlParams.bUpdate to confirm the value was consumed.
  3. Trace recording. Use the TIA Portal trace to log Setpoint, Input, Output, and OutputUpperLimit over a 30 second window. Confirm a smooth transition (no step) when the limit is reduced below the current output.
  4. Recipe round-trip. From the HMI, change recipe, observe the new limit applied, and cycle power (STOP/RUN). After restart, the limit must still match the recipe.
  5. Error injection. Send a recipe with MinMV > MaxMV. The watchdog FB should raise o_Error = TRUE and o_Status = 16#8001; PID_Compact must remain in its previous valid state, not enter Error.

Troubleshooting Matrix

Symptom Likely Cause Diagnostic Step Corrective Action
Output ignores new upper limit PID_Compact is in Manual or Inactive mode Monitor Mode tag in the technology DB Switch to Automatic (mode = 3) before writing.
PID enters error state immediately after write Inverted range: Min > Max or value outside 0–100 % Check Error bit and ErrorCode in the technology DB Validate range in the application FB before the write.
Limit reverts on STOP/RUN Configuration path was not updated Compare Config.OutputUpperLimit vs Retain.CtrlParams.OutputUpperLimit online Write to both paths, or apply the recipe from OB100.
HMI shows stale value after write HMI tag points to the wrong DB region or uses the configuration path Refresh HMI tag and re-link to Retain.CtrlParams.OutputUpperLimit Update the HMI tag connection; check acquisition cycle.
Output step observed at recipe change Bumpless transfer not implemented Review trace recording around the change Add a rate limiter; pre-position the output before the change.
Watch table rejects the write Technology DB is optimised and the watch table lacks the symbolic path Enable “Expanded mode” in the watch table and use the symbolic name Use SCL symbolic writes from a user FB rather than absolute addresses.

FAQ

Can I change PID_Compact output limits without stopping the CPU?

Yes. The active limit is stored in "PID_Compact_1".Retain.CtrlParams.OutputUpperLimit and can be overwritten at runtime from any user FB or OB. The change takes effect on the next call of PID_Compact, typically within 10–100 ms depending on the cycle OB you call it from.

What is the difference between Config.OutputUpperLimit and Retain.CtrlParams.OutputUpperLimit?

Config.OutputUpperLimit is the value the technology object loads on initialisation (after STOP–RUN, restart, or download). Retain.CtrlParams.OutputUpperLimit is the value the controller actually uses during the current run. Writes to Retain.CtrlParams are immediately effective; writes to Config only become effective after a re-initialisation of the technology object.

Does changing the output limit disturb the PID internal state (I-term, derivative)?

Changing the limits does not reset the integrator or the derivative. The controller will continue from its current internal state, but the output will be clamped to the new range. To make the change bumpless, ramp the new limit in over several seconds and consider switching to Manual, pre-positioning the output, then returning to Automatic.

Should I use the direct DB write or the NORM_X / SCALE_X approach?

Use the direct write when the new limit reflects a real plant authority change (different valve size, different heater rating). Use the NORM_X / SCALE_X pipeline when the limit is a display / scaling convenience only and the underlying 0–100 % PID output should remain untouched. The direct write gives the PID anti-windup awareness; the external scaling does not.

Which TIA Portal versions support dynamic OutputUpperLimit changes?

All versions from V13 SP1 onward, for any S7-1200 CPU with firmware V4.0 or higher. The symbolic tag path changed in V18 (now also exposed under Config.OutputUpperLimit), but the older Retain.CtrlParams.OutputUpperLimit path continues to work for backward compatibility.

What error code does PID_Compact raise if the new range is invalid?

If OutputLowerLimit >= OutputUpperLimit, PID_Compact sets the Error bit and reports error code 16#8001 ("Invalid configuration of the technology object"). If the value falls outside 0.0–100.0 %, the same error is raised. Always validate the recipe data in a user FB before the write to keep the controller in Automatic mode.

Back to blog