A flexible, hardware‑agnostic PID controller library for Arduino with multi‑instance support, anti‑windup protection, derivative filtering, and an optional autotuning add‑on.
#include <easyPID.h>
PIDController pid(2.0, 0.5, 0.1, 0, 255);
void setup() {
pid.begin();
}
void loop() {
float output = pid.update(setpoint, measurement);
applyOutput(output);
}easyPID is designed for real‑world embedded control applications where multiple independent control loops, timing flexibility, and robust behavior are required.
- Multiple independent PID instances (no global state)
- Flexible timing: automatic
millis()‑based updates or user‑supplieddt - Built‑in anti‑windup protection
- Optional derivative filtering for noisy signals
- Full internal state introspection for debugging and tuning
- Optional relay‑based autotuner (opt‑in)
- Lightweight and AVR‑friendly
- Multi‑instance friendly – Create multiple independent PID controllers
- Flexible timing modes – Automatic timing via
millis()or manual time‑delta input - Hardware‑agnostic – No assumptions about sensors, actuators, or pins
- AVR‑friendly – Designed to run efficiently on Arduino Uno‑class boards
- Practical implementation – Derived from a real embedded control project and generalized for reuse
- Anti‑windup protection – Prevent integral saturation using selectable modes
- Derivative filtering – Reduce noise sensitivity using optional low‑pass filtering
- Runtime tuning – Adjust PID gains while the system is running
- Output limiting – Clamp controller output to safe bounds
- Control direction – Support for DIRECT and REVERSE acting systems
- State introspection – Access error, P/I/D terms, and last output for debugging
The autotuner is provided as an optional module and is only included when explicitly requested:
#include <PIDTuner.h>The autotuner implements a relay / limit-cycle method (Åström–Hägglund):
-
Applies bang-bang (relay) control around the setpoint
-
Induces sustained oscillations in the system
-
Measures oscillation amplitude and period
-
Computes:
- Ultimate gain (Ku)
- Ultimate period (Pu)
-
Applies classical tuning rules to compute PID gains
- Ziegler–Nichols – Classic, aggressive response
- Tyreus–Luyben – Reduced overshoot, better for lag-dominant systems
- Pessen Integral Rule – Faster response with moderate overshoot
- No Overshoot – Conservative tuning for sensitive systems
#include <easyPID.h>
#include <PIDTuner.h>
PIDController pid(1.0, 0.0, 0.0, 0, 255);
PIDTuner tuner(pid);
void setup() {
pid.begin();
tuner.start(setpoint, relayAmplitude); // noiseBand is optional
}
void loop() {
if (!tuner.isComplete()) {
// Apply relay output during tuning
float output = tuner.update(measurement);
applyOutput(output);
} else {
float kp, ki, kd;
tuner.getTunings(kp, ki, kd, TUNING_ZIEGLER_NICHOLS);
pid.setTunings(kp, ki, kd);
// Run normal PID control
float output = pid.update(setpoint, measurement);
applyOutput(output);
}
}The autotuner intentionally induces oscillations around the setpoint.
Ensure your system can safely tolerate these oscillations before enabling autotuning.
Once published, install via:
Arduino IDE → Library Manager → Search for “easyPID”
arduino-cli lib install easyPID-
Download or clone this repository
-
Copy the
easyPIDfolder into your Arduinolibrariesdirectory:- Windows:
Documents/Arduino/libraries/ - macOS:
~/Documents/Arduino/libraries/ - Linux:
~/Arduino/libraries/
- Windows:
-
Restart the Arduino IDE
#include <easyPID.h>
PIDController pid(2.0, 0.5, 0.1, 0, 255);
void setup() {
pid.begin();
}
void loop() {
float output = pid.update(setpoint, measurement);
applyOutput(output);
}setpointis the desired target valuemeasurementis the current process valueoutputis the computed control signal
#include <easyPID.h>
#include <PIDTuner.h>
PIDController pid(1.0, 0.0, 0.0, 0, 255);
PIDTuner tuner(pid);
void setup() {
pid.begin();
tuner.start(setpoint, relayAmplitude);
}
void loop() {
if (!tuner.isComplete()) {
float output = tuner.update(measurement);
applyOutput(output);
} else {
float kp, ki, kd;
tuner.getTunings(kp, ki, kd);
pid.setTunings(kp, ki, kd);
float output = pid.update(setpoint, measurement);
applyOutput(output);
}
}The autotuner is intended as a starting point for tuning and may require refinement depending on the system dynamics.
The library includes the following examples:
- BasicPID – Single PID controller with a simulated first‑order process
- MultiLoopPID – Two independent PID loops running concurrently
- AutoTunePID – Demonstration of the optional autotuning workflow
Access them via:
Arduino IDE → File → Examples → easyPID
| Feature | easyPID | Typical Arduino PID Libraries |
|---|---|---|
| Multiple instances | ✅ Yes | |
| Timing flexibility | ✅ Auto + manual | |
| Anti‑windup | ✅ Built‑in | ❌ Often missing |
| Derivative filtering | ✅ Optional | ❌ Rare |
| State introspection | ✅ Full access | |
| Autotuning | ✅ Optional add‑on | ❌ Separate library |
A practical tuning guide is available at:
docs/tuning_guide.md
It covers:
- Understanding Kp, Ki, and Kd
- When to use anti‑windup and filtering
- Step‑by‑step tuning strategies
- Common pitfalls in embedded PID control
easyPID can be used for a wide range of control problems, including:
- Temperature regulation
- Motor speed control
- Position control
- Pan‑tilt and X‑Y systems
- Multi‑zone control setups
- Robotics and automation projects
- Arduino IDE 1.6 or newer
- Tested on AVR‑based boards (Arduino Uno, Nano)
- Expected to work on most Arduino‑compatible platforms
MIT License – see LICENSE for details.
Rami Kronbi
See CHANGELOG.md for release notes and version history.
Contributions, bug reports, and suggestions are welcome via GitHub issues and pull requests.