Implementing S7-1200 PID Control for Proportional Valve Position
Closed-loop position control of a hydraulic cylinder driven by a proportional directional valve is a common industrial requirement — press feed, injection molding clamp, packaging actuator, and test rig applications all follow the same pattern: compare a measured position to a target trajectory, compute a valve command, and let the hydraulic actuator close the loop. The Siemens S7-1200 family supports this application through its on-board PID instruction set in TIA Portal, but the choice of block, the I/O scaling, and the deadband handling are what separate a stable production loop from a chattering valve. This reference walks through the engineering decisions and the concrete configuration values for a 100-point program curve with a 4-20 mA proportional valve command that uses 12 mA as the closed-port null.
1. Plant Characteristics of a Hydraulic Position Servo
A hydraulic cylinder driven by a proportional valve is a nonlinear, time-varying plant. The dominant non-idealities are:
- Valve overlap (spool underlap): a small range of command current near null produces zero net flow. The deadband is typically 0.5-2% of full-scale current and is the principal source of integrator windup.
- Flow-pressure coupling: cylinder velocity depends on both valve opening and load pressure. As load rises, the effective gain of the valve falls.
- Oil bulk modulus variation: air entrainment and temperature shift the effective stiffness of the column of oil, changing the natural frequency of the cylinder-mass system.
- Friction: static (stiction) and Coulomb friction introduce a position-error plateau near zero velocity that the integrator must overcome.
These characteristics make the loop gain drift with operating point, which is why a single set of PID gains is rarely optimal across the full stroke. A deadband, integrator anti-windup, and optional gain scheduling are all required for production-grade performance.
2. Proportional Valve Command Signal
Industrial proportional directional valves accept one of three command formats:
| Format | Null position | Full-flow position | Typical application |
|---|---|---|---|
| 0-20 mA unipolar | 0 mA or 12 mA (with overlap) | 20 mA | Low-cost on/off proportional |
| 4-20 mA with internal driver | 12 mA | 4 mA or 20 mA (direction-dependent) | Most industrial proportional valves |
| ±10 V bipolar | 0 V | -10 V / +10 V | Valves with on-board amplifier card |
The application described uses a 4-20 mA command with 12 mA as the closed-port null. The relationship between current and commanded spool position is:
- 4 mA — full flow one direction (typically retract, but verify on the bench)
- 12 mA — ports blocked (null)
- 20 mA — full flow the other direction (typically extend)
Each 8 mA segment from null represents 100% of the controller's output range in that direction. The S7-1200 SM 1232 analog output module in 4-20 mA mode produces 0 LSB at 4 mA and 27648 LSB at 20 mA, so 12 mA = 13824 LSB and ±8 mA = ±11060 LSB, or ±110.6 LSB per 1% of MV.
3. Selecting the Right PID Block
TIA Portal ships three PID instructions in the "Technology > PID Control" palette. For an analog proportional valve, the canonical choice is PID_Compact, not PID_3STEP. The three blocks are:
| Block | Output type | Best fit | Why |
|---|---|---|---|
| PID_Compact | Continuous REAL MV, optional Output_PER | Direct drive of proportional valve via SM 1232 AQ | Output maps cleanly to 4-20 mA with bipolar scaling |
| PID_3STEP | Two boolean outputs (UP/DN) plus internal integrator | Motorized valves with position feedback | Designed for integrating actuator; not natural fit for proportional valve |
| PID_Temp | Continuous, split heating/cooling | Temperature control | Heating/cooling split not applicable to hydraulic position |
PID_3STEP can be pressed into service by wiring its UP/DN outputs to external latching relays and reconstructing the analog current, but this adds hardware complexity and degrades loop linearity. The reference implementation below uses PID_Compact with a bipolar output range of -100.0% to +100.0% and a custom SCALE_X mapping onto the SM 1232 4-20 mA channel with 12 mA null.
4. Input Scaling with NORM_X for Position Feedback
The position feedback device — typically a magnetostrictive sensor, LVDT, or linear encoder with 4-20 mA or 0-10 V output — is read by an SM 1231 analog input module. The raw 16-bit word is normalized to a 0.0-1.0 REAL and then scaled to engineering units (mm or % of stroke). TIA Portal's NORM_X and SCALE_X instructions replace the legacy FC105 (SCALE) and FC106 (UNSCALE) from the S7-300/400 era and have identical semantics.
// Position feedback scaling: raw 4-20 mA on SM 1231 AI -> 0.0-100.0 mm
#pv_norm := NORM_X(
VALUE := %IW64, // SM 1231 channel 0 raw word
MIN := 0, // 0 LSB = 4 mA (broken wire below 4 mA)
MAX := 27648); // 27648 LSB = 20 mA
#pv_eng := SCALE_X(
VALUE := #pv_norm,
MIN := 0.0, // 4 mA = 0 mm (mechanical end-of-stroke)
MAX := 100.0); // 20 mA = 100 mm (other end-of-stroke)
For 0-10 V feedback, the SM 1231 raw range is the same (0-27648 LSB maps to 0-10 V). For a 0-10 V sensor with a 0-50 mm stroke, replace the SCALE_X limits with 0.0 and 50.0.
| Module | Resolution | Conversion time | Voltage ranges | Current ranges |
|---|---|---|---|---|
| SM 1231 AI 4 x 13 bit | 13 bit + sign | 625 µs / channel | ±10 V, 0-10 V | 0-20 mA, 4-20 mA |
| SM 1231 AI 8 x 13 bit | 13 bit + sign | 625 µs / channel | ±10 V, 0-10 V | 0-20 mA, 4-20 mA |
| SM 1231 AI 4 x 16 bit | 16 bit + sign | 100 µs / channel | ±10 V, 0-10 V, ±5 V, ±2.5 V | 0-20 mA, 4-20 mA, ±20 mA |
5. Output Scaling with SCALE_X for the Valve Command
PID_Compact's MV (Output) is a REAL in the configured output range, typically -100.0 to +100.0% for a bipolar valve. The SM 1232 analog output expects a 16-bit word that represents 4-20 mA. The conversion is:
Current (mA) = 12 + (MV / 100) × 8
Equivalently, the LSB value to write to %QW is:
Raw = 13824 + (MV_percent × 110.6)
Where 13824 LSB is 12 mA on a 4-20 mA SM 1232 channel and 110.6 LSB equals 1% of the full ±100% range (since 8 mA × 27648 / 20 mA = 11059.2 LSB, divided by 100 = 110.6 LSB/%). The SCL implementation clamps to the module's valid 0-27648 range and applies the polarity.
// Map -100.0..+100.0% MV to 4-20 mA with 12 mA null
#mv_percent := LIMIT(-100.0, #pid_compact.Output, 100.0);
#raw_out := REAL_TO_INT(13824.0 + #mv_percent * 110.6);
#raw_out := LIMIT(0, #raw_out, 27648);
%QW80 := INT_TO_WORD(#raw_out); // SM 1232 AQ channel 0
6. Implementing the 12 mA Null and Deadband
The valve's natural overlap (typically ±0.5-2% of full-scale current) means that a small command around 12 mA produces zero net flow but still draws current and dissipates heat in the solenoid. If the controller tries to drive the error to zero and the feedback resolution places the PV at the edge of the deadband, the integrator winds up against the null and the valve chatters at a frequency determined by the sample time and the integrator gain. The fix is a programmed deadband that holds the MV at zero (12 mA) and freezes integration while the error is inside the band.
| Valve type | Typical deadband (% of full scale) | Comments |
|---|---|---|
| Direct-operated, low-flow (< 10 L/min) | 1.0 - 2.0 | Larger overlap; more stiction |
| Pilot-operated, medium flow (10-100 L/min) | 0.5 - 1.0 | Standard industrial proportional |
| Servo-proportional with on-board driver | 0.1 - 0.5 | Better spool machining, lower overlap |
| High-response servo valve | 0.05 - 0.2 | Two-stage, low overlap |
Two implementation paths exist on the S7-1200:
- Use PID_Compact's built-in deadband parameter. In the configuration editor, set "Dead band width" to the desired value in % of input range. The block holds the output at zero and pauses integration while the absolute error is inside the band. This is the cleanest path and does not require external code.
- Implement the deadband in user code. Compute the error externally, zero it inside the band, and feed the modified error to PID_Compact. This allows asymmetric deadbands and direction-dependent behavior but adds complexity.
// Option 2: external deadband with integrator hold flag
#error_eng := #setpoint_curve[#index] - #pv_eng;
IF ABS(#error_eng) < 0.5 THEN
#error_to_pid := 0.0;
#integrator_hold := TRUE; // signal to PID_Compact via a custom instance
ELSE
#error_to_pid := #error_eng;
#integrator_hold := FALSE;
END_IF;
7. PID Tuning Parameters and Anti-Windup
Hydraulic position control with a proportional valve responds well to PI control with the following starting values for first commissioning:
| Parameter | Starting value | Adjustment direction if loop oscillates | Adjustment direction if response is sluggish |
|---|---|---|---|
| Proportional gain Kp | 1.0 (dimensionless) | Halve Kp | Increase Kp in 25% steps |
| Integral time Ti | 500 ms | Increase Ti by 50% | Decrease Ti by 25% |
| Derivative time Td | 0 (disabled) | Leave at 0 | Leave at 0 |
| Deadband | 0.5% of stroke | Increase to 1% | Decrease to 0.3% |
| MV limits | ±100.0% | — | — |
Anti-windup is integrated into PID_Compact: when the MV saturates at the configured limits, the integrator is held at the saturating value rather than allowed to accumulate. Confirm the "Controller structure > Anti-windup" option is enabled in the configuration editor; the default is enabled.
8. Cycle Time and OB Selection
The OB cycle time of the S7-1200 determines the effective sample period of the controller. If PID_Compact is called from OB1, the sample time is the OB1 period, which for a CPU 1214C running a moderate program is typically 5-15 ms. For deterministic sample periods, call the PID block from a cyclic interrupt OB (OB30 through OB38). The configuration editor's "Sample time" parameter should match the OB period; if it does not, the block internally decimates the call rate and performance is hard to predict.
| System bandwidth | Sample time | OB selection |
|---|---|---|
| Low-speed (cycle > 5 s) | 50-100 ms | OB1 with sample time match |
| Medium (cycle 1-5 s) | 10-50 ms | OB35 (default 100 ms) or OB30 (configurable) |
| High (cycle 0.1-1 s) | 1-10 ms | OB30 with 1-10 ms period |
| Servo (cycle < 0.1 s) | 0.5-1 ms | Consider S7-1500 or motion control library |
9. Complete SCL Implementation
The function block below is a complete reference implementation: 100-point curve, fixed-time advance, NORM_X / SCALE_X scaling, deadband, and PID_Compact as the core controller. The block is intended to be called from a cyclic interrupt OB and reads/writes the analog I/O directly via process image addresses.
FUNCTION_BLOCK "FB_CylinderPositionControl"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR
// Configuration inputs
CurvePoints : ARRAY[1..100] OF REAL; // 0.0-100.0 setpoint curve
CurveIndex : INT; // current curve index (1-100)
UpdateTime : TIME := T#100ms; // curve point update interval
Deadband : REAL := 0.5; // % of full scale
StrokeMin : REAL := 0.0; // engineering units min
StrokeMax : REAL := 100.0; // engineering units max
EnableCurve : BOOL; // run/hold the curve
// I/O addresses
RawAI_Addr : WORD; // %IW64 position feedback
RawAO_Addr : WORD; // %QW80 valve command
// Internal state
PIDCompact : PID_Compact; // TIA Portal PID block
CurveTimer : IEC_TIMER;
PV_Norm : REAL;
PV_Eng : REAL;
SP_Current : REAL;
Error : REAL;
MV_Percent : REAL;
MV_Raw : INT;
CycleActive : BOOL;
END_VAR
BEGIN
// 1. Read and scale position feedback (4-20 mA -> engineering units)
#PV_Norm := NORM_X(VALUE := #RawAI_Addr, MIN := 0, MAX := 27648);
#PV_Eng := SCALE_X(VALUE := #PV_Norm, MIN := #StrokeMin, MAX := #StrokeMax);
// 2. Advance the curve index on a fixed time base
#CurveTimer(IN := #EnableCurve AND NOT #CycleActive, PT := #UpdateTime);
IF #CurveTimer.Q THEN
#CycleActive := TRUE;
IF #CurveIndex < 100 THEN
#CurveIndex := #CurveIndex + 1;
END_IF;
END_IF;
#SP_Current := #CurvePoints[#CurveIndex];
// 3. Compute error and apply programmed deadband
#Error := #SP_Current - #PV_Eng;
IF ABS(#Error) < #Deadband THEN
#Error := 0.0;
END_IF;
// 4. Call PID_Compact with scaled setpoint and feedback
// (PID_Compact internally holds MV at zero inside its own deadband.)
#PIDCompact(
Setpoint := #SP_Current,
Input := #PV_Eng,
Input_PER := 0, // not used; we feed Input
ManualEnable := FALSE,
ManualValue := 0.0,
Reset := FALSE);
// 5. Convert -100..+100% MV to 4-20 mA raw with 12 mA null
#MV_Percent := LIMIT(-100.0, #PIDCompact.Output, 100.0);
#MV_Raw := REAL_TO_INT(13824.0 + #MV_Percent * 110.6);
#MV_Raw := LIMIT(0, #MV_Raw, 27648);
#RawAO_Addr := INT_TO_WORD(#MV_Raw);
// 6. Publish diagnostics for HMI trending
"DB_CurveDiag".SP := #SP_Current;
"DB_CurveDiag".PV := #PV_Eng;
"DB_CurveDiag".MV := #MV_Percent;
"DB_CurveDiag".Error := #Error;
"DB_CurveDiag".Index := #CurveIndex;
END_FUNCTION_BLOCK
10. Commissioning Procedure
- Validate wiring and analog I/O. Force the SM 1232 to 13824 LSB (12.0 mA) with the program in stop or via a watch table. Clamp the valve solenoid lead and verify 12.00 mA ±0.05 mA. Move the cylinder to full retract by hand and read %IW64; verify it is at the expected raw value for that position. Repeat for full extend. Adjust the SCALE_X MIN/MAX if the engineering range is not exactly 0-100.
- Verify curve direction. Force the output to +20% above null (13824 + 2212 = 16036 LSB, ~14.4 mA). The cylinder must move in the direction the mechanical drawing defines as "extend." If reversed, invert the sign in the SCALE_X formula (replace + with -). Do not rewire the valve solenoids.
- Open-loop step test. Place PID_Compact in manual mode (ManualEnable = TRUE) and step ManualValue from 0% to +20% in 5% increments, holding each step for 2 seconds. Plot the resulting cylinder velocity versus MV%. The curve should be approximately linear in the 5-20% MV region. A strong nonlinearity near 0% indicates valve overlap and confirms that a programmed deadband is required.
- Close the loop with conservative gains. Set Kp = 0.5, Ti = 2000 ms, Td = 0. Switch to automatic mode. Apply a 5% setpoint step and verify stable, non-oscillatory response. If the loop oscillates, halve Kp.
- Run a full curve following test. Trigger the curve generator and observe position error in the HMI trending view. Aim for steady-state error below 1% of stroke and overshoot below 2% on the curve corners.
- Tune for production. Increase Kp in 25% steps until the first sign of oscillation, then back off 30%. Reduce Ti in 20% steps until corner overshoot exceeds 2%, then back off 50%. Re-verify the full curve.
- Document the final settings. Record the final Kp, Ti, sample time, deadband width, MV limits, and the HMI trend data showing the final performance. Attach the trend data to the program as a commissioning record.
11. Verification and Performance Checks
Acceptable quantitative performance for a hydraulic cylinder position loop driven by a proportional valve depends on the application. The table below lists common acceptance criteria.
| Metric | General industrial | High-precision | Test rig / motion profile |
|---|---|---|---|
| Steady-state error | < 1% of stroke | < 0.1% of stroke | < 0.05% of stroke |
| Settling time (5% step, 2% band) | < 1 s | < 200 ms | < 100 ms |
| Overshoot (setpoint step) | < 5% | < 1% | < 0.5% |
| Corner tracking error (curve follow) | < 2% of stroke | < 0.5% of stroke | < 0.2% of stroke |
| Valve current at null (no motion commanded) | 11.95 - 12.05 mA | 11.99 - 12.01 mA | 12.00 mA ±0.5% |
To verify steady-state error, hold the setpoint constant and read PV over 5 seconds; the standard deviation of the error signal is the steady-state error metric. To verify corner tracking, run the full 100-point curve and compute the integral of absolute error (IAE); the curve-following IAE should be less than 0.5% × stroke × duration for a well-tuned loop.
12. Troubleshooting Matrix
| Symptom | Likely cause | Corrective action |
|---|---|---|
| Valve chatters at null, solenoid hot | Integrator windup against valve overlap | Enable deadband 0.5-1%; confirm anti-windup is on; reduce Kp |
| Large steady-state error | Pure-P control, no integral action | Reduce Ti; confirm action direction (reverse vs. direct) |
| Cylinder overshoots setpoint | Ti too short; loop over-corrects | Increase Ti by 50%; reduce Kp by 25% |
| Slow response, no oscillation | Kp too low; sample time too long | Increase Kp in 25% steps; reduce OB period to 1-10 ms |
| Position drifts when MV is at null | Load-induced drift; anti-windup disabled | Verify PID_Compact is in automatic mode; check Ti value; enable anti-windup |
| Output saturated at ±100% persistently | Setpoint outside physical range; load too high | Clamp setpoint to valid range; reduce load or raise supply pressure |
| Output_PER value does not match expected mA | Output_PER used directly with wrong scaling | Use Output (REAL) and apply SCALE_X for bipolar mapping |
| Tracking error grows with velocity | Missing feedforward from curve slope | Add a velocity feedforward term from curve interpolation; consider gain scheduling by direction |
| Loop oscillates at fixed frequency independent of Kp | Mechanical resonance excited by sample rate | Increase sample time to break the resonance alias; add input filtering on PV |
| PV reads -32768 or 32767 (overflow) | Open input wire; sensor out of range | Check wiring; check SM 1231 diagnostics in TIA Portal online view |
13. Safety and Diagnostic Considerations
Hydraulic systems are unforgiving. A proportional valve stuck at full command can drive a cylinder to a mechanical end-of-stroke with sufficient force to damage tooling or injure personnel. The PLC program must include at least the following fault paths:
- PV sanity check: if the position feedback is out of the valid range (e.g., raw < 0 or > 27648 indicating broken wire) or the rate of change exceeds a physical limit, drive the MV to 0.0 (12 mA null) and raise a fault.
- MV watchdog: if the absolute MV remains > 80% for more than 2 seconds without PV movement, raise a fault — this indicates a blocked valve, broken hose, or mechanical jam.
- Curve completion timeout: if the cylinder does not reach within 1% of the final setpoint within 2x the expected time, raise a fault and freeze the curve index.
- Emergency stop: the E-stop chain must hard-wire the valve enable signal to drop the valve to 12 mA (null) regardless of PLC output state. Do not rely on software to override a hardware fault.
Wire these checks into the cyclic interrupt OB so they run at the controller sample rate, not at the OB1 rate. The fault outputs should appear in an HMI alarm log and as colored indicator tiles on the operator screen.
14. Curve Interpolation and Smoothing
A 100-point curve with a fixed sample interval produces a staircase setpoint. The cylinder follows the staircase, and the loop's correction at each step adds a transient. If the curve has sharp corners, the loop will overshoot at the corner. Two options reduce this:
- Linear interpolation between curve points. At each PID sample, interpolate the setpoint between CurvePoints[i] and CurvePoints[i+1] based on the fractional advance within the point interval. This requires the curve timer to track sub-point time.
- S-curve acceleration shaping. Apply a third-order polynomial ramp to the setpoint so that the velocity is continuous at the curve points. This eliminates the velocity discontinuity that drives overshoot.
For a 100-point curve sampled at 100 ms intervals, the bandwidth of the setpoint is 10 Hz. If the loop's closed-loop bandwidth is at least 5x higher (50 Hz, sample time < 3 ms), linear interpolation is sufficient. If not, the loop cannot track the curve and the setpoint must be smoothed.
15. Reference Documentation
- Siemens Industry Online Support — main technical documentation portal for S7-1200, TIA Portal, and PID instruction manuals.
- S7-1200 Programmable Controller System Manual — covers SM 1231/SM 1232 analog module specifications, wiring, and diagnostic addresses.
- TIA Portal "PID Control with PID_Compact" function manual — block diagram, configuration parameters, error codes, and tuning guidance.
- TIA Portal "Basic Functions" reference — NORM_X, SCALE_X, LIMIT, IEC_TIMER instruction semantics and overflow behavior.
FAQ
Is PID_3STEP the right block for a proportional valve?
No. PID_3STEP is designed for motorized (integrating) valves with two boolean UP/DN output signals. For an analog proportional valve driven by a 4-20 mA signal, use PID_Compact and scale the continuous MV to the analog output. You can implement PID_3STEP by mapping its two output bits to external latching hardware, but this adds complexity and degrades loop linearity.
How do I map a -100 to +100% MV to a 4-20 mA signal with a 12 mA null?
Use the formula Raw = 13824 + MV_percent × 110.6, where 13824 is the LSB value for 12 mA on a 4-20 mA SM 1232 channel and 110.6 LSB equals 1% of the ±100% MV range. Apply LIMIT(0, raw, 27648) to clamp to the module's valid output range.
Why does the cylinder oscillate around the setpoint even with conservative Kp?
Most oscillation in hydraulic position loops comes from valve overlap combined with integrator windup, not from P gain alone. Set a programmed deadband of 0.5-2% of full scale in the PID_Compact configuration, and verify that anti-windup is enabled. If oscillation persists, halve Kp and double Ti.
What sample time should I use for the PID loop on the S7-1200?
Match the OB cycle to the loop's closed-loop bandwidth: 10-50 ms for typical industrial cylinders, 1-10 ms for high-response cylinders, and 50-100 ms for soft, low-speed systems. Call PID_Compact from a cyclic interrupt OB (OB30-OB38) to enforce a fixed sample period rather than the variable OB1 period.
Can I use NORM_X and SCALE_X in place of FC105 and FC106 on the S7-1200?
Yes. NORM_X and SCALE_X are the S7-1200/1500 native equivalents of FC105 (SCALE) and FC106 (UNSCALE). They have identical semantics (linear normalization of an integer into 0.0-1.0 and inverse scaling to engineering units) and are documented in the TIA Portal Basic Functions reference. Use them for both feedback input scaling and valve output scaling to keep the program consistent.
Do I need a derivative term for a hydraulic position loop?
Generally no. Hydraulic plants have sufficient damping and a derivative term amplifies position-sensor noise and excites valve-spool resonance. A PI controller with proper deadband and anti-windup is the standard implementation. If derivative is required for high-precision tracking, set Td to a small fraction of Ti (typically Td < 0.1 × Ti) and enable derivative filtering to limit high-frequency gain.