control//feedback control//PID controller//PID implementation

A PID implementation turns the continuous formula into a few lines that a processor runs at a fixed interval: read the measurement, compute the three terms, limit and write the output, wait for the next tick. Getting those lines right matters as much as the tuning. A fixed sample time, a filtered derivative on the measurement, anti-windup and bumpless switching between manual and automatic are what separate a controller that works on the bench from one that works in a plant.


A PID implementation turns the continuous formula into a few lines that a processor runs at a fixed interval: read the measurement, compute the three terms, limit and write the output, wait for the next tick. Getting those lines right matters as much as the tuning. A fixed sample time, a filtered derivative on the measurement, anti-windup and bumpless switching between manual and automatic are what separate a controller that works on the bench from one that works in a plant.

uk=Kpek+Ik+Dk,Ik=Ik−1+Ki Δt ek,Dk=αDk−1−(1−α) Kd yk−yk−1Δtu_k=K_pe_k+I_k+D_k,\qquad I_k=I_{k-1}+K_i\,\Delta t\,e_k,\qquad D_k=\alpha D_{k-1}-(1-\alpha)\,K_d\,\frac{y_k-y_{k-1}}{\Delta t}uk​=Kp​ek​+Ik​+Dk​,Ik​=Ik−1​+Ki​Δtek​,Dk​=αDk−1​−(1−α)Kd​Δtyk​−yk−1​​

This is the positional form: each sample computes the whole output. The integral is a running sum, the derivative a filtered difference of measurements (with α\alphaα between 0 and 1 setting the filter), and uku_kuk​ is limited to the actuator's range before it is written, with the sum held while the output is at a limit.

The sample time is fixed and short. The terms assume a constant Δt\Delta tΔt, so a loop that runs whenever the processor happens to be free has an integral and a derivative that change with the processor's load. A common rule of thumb is to sample roughly ten to twenty times faster than the closed loop's bandwidth; in a PLC the PID block is usually called from a cyclic interrupt with its own period rather than from the main program cycle.

The velocity form computes the change of the output, Δuk\Delta u_kΔuk​, and adds it to the previous output. Limiting the output then stops the integral by itself, and switching from manual to automatic is bumpless. Rockwell's PIDE (Enhanced PID) instruction for Logix controllers works this way; its older PID instruction uses the positional form.

Industrial PLCs ship PID as a configured block rather than code. Siemens' S7-1200 and S7-1500 offer the PID_Compact technology object, with anti-windup and automatic pretuning and fine tuning, plus PID_3Step for motor-driven valves and PID_Temp for heating and cooling. The normative library of IEC 61131-3 defines no PID; the blocks come from vendors and from libraries such as OSCAT.

Outside PLCs, the Arduino PID Library by Brett Beauregard (PID_v1) is the usual embedded reference, and its author's blog series Improving the Beginner's PID adds the fixes one at a time: sample time, derivative kick, on-the-fly tuning changes, windup. In robotics, ros2_control's pid_controller is built on the Pid class of control_toolbox, with conditional integration or back-calculation as anti-windup.

Design tools are a separate shelf. MATLAB's Control System Toolbox has pid objects, pidtune and the PID Tuner app, and Simulink the PID Controller block with clamping or back-calculation anti-windup; in Python, the control package (python-control) and scipy.signal simulate plants and loops and compute margins, though neither ships a ready runtime controller.

?Why does the code keep the integral term already multiplied by KiK_iKi​?

Because the gains change while the loop runs. If the code keeps ∑e\sum e∑e and multiplies by KiK_iKi​ at output time, a new KiK_iKi​ rescales the whole history at once and the output jumps; if it keeps IkI_kIk​, already multiplied, a new gain only affects errors from then on. Beauregard's series calls this the on-the-fly tuning fix.