← Back to Blog

PID Controller in PLC: Complete Implementation Guide

August 6, 2026·14 min read·Tutorial

PID control is the backbone of industrial process automation. Whether you are regulating temperature in a heat exchanger, maintaining pressure in a vessel, or controlling flow through a pipeline, PID is almost certainly the algorithm doing the heavy lifting. This guide walks you through implementing a PID controller in a PLC from first principles, with complete Structured Text code and practical tuning advice.

What Is PID Control?

PID stands for Proportional-Integral-Derivative. It is a feedback control algorithm that continuously calculates an error value (the difference between a desired setpoint and a measured process variable) and applies a correction based on three distinct terms.

Proportional (P) Term

The proportional term produces an output that is directly proportional to the current error. If the temperature is 10 degrees below setpoint, the P term drives the heater harder than if it were only 2 degrees below. The gain constant Kp determines how aggressively the controller responds. A high Kp reacts strongly but risks oscillation; a low Kp responds sluggishly but remains stable.

Integral (I) Term

The integral term accumulates error over time. Even if the proportional term has reduced the error to a small steady-state offset, the integral term continues to build until that offset is eliminated. The gain constant Ki controls how quickly the accumulated error influences the output. This term eliminates steady-state error but can cause overshoot if tuned too aggressively.

Derivative (D) Term

The derivative term responds to the rate of change of the error. If the process variable is approaching the setpoint rapidly, the D term applies a braking force to prevent overshoot. The gain constant Kd determines this damping effect. In noisy industrial environments, the derivative term is often filtered or reduced because it amplifies high-frequency noise.

When You Need PID

PID control is appropriate whenever you need to maintain a process variable at a specific setpoint with minimal overshoot and fast response. Common applications include:

  • Temperature control - furnaces, ovens, HVAC systems, injection molding
  • Pressure regulation - compressor discharge, reactor vessels, hydraulic systems
  • Flow control - chemical dosing, water treatment, fuel delivery
  • Level control - tank filling, boiler drum level, reservoir management
  • Speed/position control - motor drives, conveyor speed, servo positioning

Simple on/off control creates oscillation around the setpoint. PID provides smooth, precise regulation by modulating the output continuously rather than switching between fully on and fully off.

The PID Equation

The standard PID algorithm in discrete (sampled) form suitable for PLC implementation is:

Output = Kp * error + Ki * integral + Kd * derivative

Where:
  error      = Setpoint - ProcessVariable
  integral   = integral + error * dt
  derivative = (error - previous_error) / dt
  dt         = scan cycle time (seconds)

The output is typically clamped between 0% and 100% (or the appropriate actuator range) and the integral term is bounded to prevent windup. This is the positional form of the PID algorithm, which calculates the absolute output value each scan.

Implementation in Structured Text

Below is a complete, production-ready PID function block written in IEC 61131-3 Structured Text. It includes anti-windup protection, output clamping, and derivative filtering.

FUNCTION_BLOCK FB_PID
VAR_INPUT
    Setpoint     : REAL;    (* Desired process value *)
    ProcessVar   : REAL;    (* Measured process value *)
    Kp           : REAL;    (* Proportional gain *)
    Ki           : REAL;    (* Integral gain *)
    Kd           : REAL;    (* Derivative gain *)
    dt           : REAL;    (* Sample time in seconds *)
    OutMin       : REAL;    (* Minimum output limit *)
    OutMax       : REAL;    (* Maximum output limit *)
    ManualMode   : BOOL;    (* TRUE = manual override *)
    ManualOutput : REAL;    (* Output value in manual mode *)
    Reset        : BOOL;    (* Reset integral and output *)
END_VAR

VAR_OUTPUT
    Output       : REAL;    (* Controller output *)
    Error        : REAL;    (* Current error *)
END_VAR

VAR
    integral     : REAL := 0.0;
    prevError    : REAL := 0.0;
    derivative   : REAL := 0.0;
    pTerm        : REAL;
    iTerm        : REAL;
    dTerm        : REAL;
    rawOutput    : REAL;
END_VAR

(* Main PID calculation *)
IF Reset THEN
    integral  := 0.0;
    prevError := 0.0;
    Output    := 0.0;
    RETURN;
END_IF;

IF ManualMode THEN
    Output    := ManualOutput;
    integral  := ManualOutput / Ki;  (* Bumpless transfer *)
    prevError := Setpoint - ProcessVar;
    RETURN;
END_IF;

(* Calculate error *)
Error := Setpoint - ProcessVar;

(* Proportional term *)
pTerm := Kp * Error;

(* Integral term with anti-windup *)
integral := integral + (Error * dt);
iTerm := Ki * integral;

(* Derivative term on error *)
derivative := (Error - prevError) / dt;
dTerm := Kd * derivative;

(* Sum all terms *)
rawOutput := pTerm + iTerm + dTerm;

(* Clamp output *)
IF rawOutput > OutMax THEN
    Output := OutMax;
    (* Anti-windup: prevent integral from growing further *)
    IF Error > 0.0 THEN
        integral := integral - (Error * dt);
    END_IF;
ELSIF rawOutput < OutMin THEN
    Output := OutMin;
    (* Anti-windup: prevent integral from going more negative *)
    IF Error < 0.0 THEN
        integral := integral - (Error * dt);
    END_IF;
ELSE
    Output := rawOutput;
END_IF;

(* Store error for next scan *)
prevError := Error;

To use this function block, instantiate it in your main program and call it every scan cycle with consistent timing. Connect the output to your analog output or actuator command.

PROGRAM Main
VAR
    TempPID : FB_PID;
    TempSensor : REAL;   (* From analog input *)
    HeaterCmd  : REAL;   (* To analog output, 0-100% *)
END_VAR

TempPID(
    Setpoint     := 75.0,       (* 75 degrees C target *)
    ProcessVar   := TempSensor,
    Kp           := 2.0,
    Ki           := 0.5,
    Kd           := 0.1,
    dt           := 0.1,        (* 100ms scan cycle *)
    OutMin       := 0.0,
    OutMax       := 100.0,
    ManualMode   := FALSE,
    ManualOutput := 0.0,
    Reset        := FALSE
);

HeaterCmd := TempPID.Output;

Implementation in Function Block Diagram

In a Function Block Diagram (FBD) environment, the PID controller is represented as a graphical block with input pins on the left and output pins on the right. You wire the setpoint and process variable signals into the block, configure the gain parameters, and connect the output to your actuator.

The typical FBD approach involves three stages connected in parallel: a proportional gain block, an integrator block with a limiter, and a differentiator block with a low-pass filter. Their outputs feed into a summation block, followed by an output limiter. Most PLC programming environments provide a built-in PID function block that encapsulates all of this internally, so you simply drag it onto your sheet and connect the wires.

The advantage of FBD for PID is visual clarity. Engineers can trace signal flow, verify connections, and see the relationship between process inputs and actuator outputs at a glance. It is particularly effective for systems with multiple PID loops where cascade or feedforward structures are used.

Tuning Your PID Controller

Ziegler-Nichols Method

The Ziegler-Nichols ultimate gain method is a classical approach for finding initial PID parameters:

  • Set Ki and Kd to zero. Increase Kp until the system oscillates with a constant amplitude. This value is the ultimate gain Ku.
  • Measure the oscillation period Tu (seconds per cycle).
  • Apply the Ziegler-Nichols formulas: Kp = 0.6 * Ku, Ki = 2 * Kp / Tu, Kd = Kp * Tu / 8.

These values provide a starting point that typically produces a quarter-decay response. Further manual adjustment is almost always necessary for production use.

Manual Trial and Error

For many applications, a structured manual approach works well:

  • Start with Ki = 0 and Kd = 0. Increase Kp until the response is reasonably fast but begins to oscillate.
  • Reduce Kp by 20-30%, then slowly increase Ki to eliminate steady-state error.
  • If overshoot is excessive, add a small amount of Kd to dampen it.
  • Fine-tune by observing step responses and disturbance rejection.

Common Mistakes

Integral Windup

If the output saturates (hits its limit) while the error persists, the integral term continues to accumulate. When the error finally reverses, the controller must unwind this accumulated value before the output responds, causing massive overshoot. The solution is anti-windup clamping, as implemented in the code above: stop accumulating the integral when the output is saturated.

Derivative Kick

When the setpoint changes abruptly, the error jumps instantaneously, producing a large derivative spike that can slam the actuator. The fix is to compute the derivative on the process variable alone (not the error): derivative = -(ProcessVar - prevProcessVar) / dt. This eliminates the spike on setpoint changes while still providing damping for disturbances.

Inconsistent Sample Time

The PID algorithm assumes a fixed sample interval. If your PLC task is not configured with a fixed cycle time, or if your scan time varies due to other processing loads, the integral and derivative calculations become inaccurate. Always run your PID in a cyclic task with a guaranteed fixed period. Typical values range from 10ms for fast servo loops to 1000ms for slow thermal processes.

Simulating PID in Plaxio

Plaxio is a modern PLC IDE that lets you write, simulate, and test PID controllers without physical hardware. You can create the FB_PID function block in Structured Text, wire it into a test program, and run the simulation to observe the controller response in real time.

To simulate a process plant, create a simple first-order transfer function in a separate function block that models your process (for example, a thermal mass with a time constant). Connect the PID output to the process model input, and feed the model output back as the process variable. This closed-loop simulation lets you tune your PID parameters and verify stability before deploying to real hardware.

Plaxio supports both Structured Text and Function Block Diagram, so you can implement your PID in whichever language suits your workflow. The built-in variable monitor lets you plot setpoint, process variable, and output on a trend chart to visualize controller performance during tuning.

Get Started

PID control is a fundamental skill for any controls engineer, and implementing it yourself (rather than relying on opaque vendor-specific blocks) gives you complete understanding and flexibility. With the Structured Text code above, you have a production-ready PID function block that handles anti-windup, manual mode with bumpless transfer, and output clamping.

Download Plaxio to start building and simulating PID controllers in a modern, intuitive environment. Write your logic in Structured Text or Function Block Diagram, test it in simulation, and deploy with confidence.

Ready to implement PID control?

Plaxio gives you a modern PLC development environment with built-in simulation, Structured Text, and Function Block Diagram support.

Download Plaxio