https://github.com/lily-osp/autotunepid
The AutoTunePID library is an easy-to-use library for Arduino IDE that provides a powerful PID (Proportional, Integral, Derivative) controller with built-in auto-tuning capabilities.
https://github.com/lily-osp/autotunepid
arduino-library automation control-systems pid-control pid-tuning
Last synced: 11 months ago
JSON representation
The AutoTunePID library is an easy-to-use library for Arduino IDE that provides a powerful PID (Proportional, Integral, Derivative) controller with built-in auto-tuning capabilities.
- Host: GitHub
- URL: https://github.com/lily-osp/autotunepid
- Owner: lily-osp
- Created: 2024-12-12T07:20:35.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-05-10T10:54:45.000Z (about 1 year ago)
- Last Synced: 2025-05-10T11:30:37.558Z (about 1 year ago)
- Topics: arduino-library, automation, control-systems, pid-control, pid-tuning
- Language: C++
- Homepage:
- Size: 151 KB
- Stars: 3
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: Readme.md
Awesome Lists containing this project
README
# AutoTunePID Library
A robust, feature-rich PID control library for Arduino that implements advanced auto-tuning algorithms, signal filtering, anti-windup, and operational modes for flexible control.
---
## Features
- **Comprehensive PID Control**
- Real-time PID calculations with configurable update intervals.
- Constrained output range to ensure system safety.
- Support for both auto-tuning and manual parameter configuration.
- **Multiple Auto-Tuning Methods**:
- **Ziegler-Nichols**: Determines ultimate gain (Ku) and oscillation period (Tu) using observed output extremes.
- **Cohen-Coon**: Fine-tunes Ku and Tu with alternative multipliers for better initial performance.
- **IMC (Internal Model Control)**: Balances system robustness and responsiveness using a lambda tuning parameter.
- **Tyreus-Luyben**: Provides robust tuning with minimal overshoot, ideal for systems requiring stability.
- **Lambda Tuning (CLD)**: Optimizes systems with significant dead time using process time constant (T) and dead time (L).
- **Operational Modes**:
- **Normal**: Standard PID operation.
- **Reverse**: Reverses the error calculation for cooling systems.
- **Hold**: Stops all calculations to save resources.
- **Preserve**: Minimal calculations to keep the system responsive.
- **Tune**: Performs auto-tuning to determine `Tu` and `Ku`.
- **Auto**: Automatically selects the best operational mode based on system behavior.
- **Oscillation Modes**:
- **Normal**: Full oscillation (`MaxOutput - MinOutput`).
- **Half**: Half oscillation (`1/2 MaxOutput - 1/2 MinOutput`).
- **Mild**: Mild oscillation (`1/4 MaxOutput - 1/4 MinOutput`).
- **Signal Filtering**:
- Configurable input and output signal filters using exponential moving averages.
- Adjustable alpha values for filter responsiveness (range: 0.01–1.0).
- **Anti-Windup**:
- Prevents integral windup by constraining the integral term when the output is saturated.
- Configurable threshold for anti-windup behavior.
- **Safety and Reliability**:
- Output values are constrained within specified bounds.
- Fixed interval updates ensure stability.
- Protected filter parameters to prevent invalid configurations.
---
## Installation
1. Download the library as a ZIP file.
2. In the Arduino IDE, go to **Sketch > Include Library > Add .ZIP Library**.
3. Select the downloaded ZIP file.
4. Restart the Arduino IDE.
---
## Quick Start
```cpp
#include
// Initialize PID controller with output range and tuning method
AutoTunePID pid(0, 255, TuningMethod::ZieglerNichols);
void setup() {
pid.setSetpoint(100.0); // Target setpoint
pid.enableInputFilter(0.1); // Optional input filtering
pid.enableAntiWindup(true, 0.8); // Enable anti-windup with 80% threshold
pid.setOscillationMode(OscillationMode::Normal); // Set oscillation mode to Normal
pid.setOperationalMode(OperationalMode::Tune); // Set operational mode to Tune
}
void loop() {
float input = analogRead(A0); // Read input
pid.update(input); // Update the PID controller
analogWrite(PWM_PIN, pid.getOutput()); // Write output
}
```
---
## API Reference
### Core Functions
#### Initialization
```cpp
AutoTunePID(float minOutput, float maxOutput, TuningMethod method = TuningMethod::ZieglerNichols);
```
- `minOutput`: Lower bound for controller output.
- `maxOutput`: Upper bound for controller output.
- `method`: Auto-tuning method selection (default: Ziegler-Nichols).
#### Control Configuration
```cpp
void setSetpoint(float setpoint); // Set the desired setpoint
void setTuningMethod(TuningMethod method); // Change the tuning method
void setManualGains(float kp, float ki, float kd); // Set manual PID gains
```
#### Signal Filtering
```cpp
void enableInputFilter(float alpha); // Enable input filtering (alpha range: 0.01-1.0)
void enableOutputFilter(float alpha); // Enable output filtering (alpha range: 0.01-1.0)
```
#### Anti-Windup
```cpp
void enableAntiWindup(bool enable, float threshold = 0.8f); // Enable/disable anti-windup with optional threshold
```
#### Operational Modes
```cpp
void setOperationalMode(OperationalMode mode); // Set the operational mode
```
#### Oscillation Modes
```cpp
void setOscillationMode(OscillationMode mode); // Set the oscillation mode for auto-tuning
void setOscillationSteps(int steps); // Set the number of oscillation steps for auto-tuning
```
#### Runtime Operations
```cpp
void update(float currentInput); // Update at minimum 100ms intervals
float getOutput(); // Get the current output value
```
#### Parameter Access
```cpp
float getKp(); // Get the proportional gain (Kp)
float getKi(); // Get the integral gain (Ki)
float getKd(); // Get the derivative gain (Kd)
float getKu(); // Get the ultimate gain (Ku)
float getTu(); // Get the oscillation period (Tu)
float getSetpoint(); // Get the current setpoint
```
---
## Advanced Auto-Tuning Methods
The library implements five distinct auto-tuning algorithms:
1. **Ziegler-Nichols**:
- Oscillates the system to determine Ku and Tu based on output extremes.
- Calculates PID gains:
- $ K_p = 0.6 \cdot Ku $
- $ K_i = \frac{1.2 \cdot K_p}{Tu} $
- $ K_d = 0.075 \cdot K_p \cdot Tu $
2. **Cohen-Coon**:
- Alternative multipliers provide better transient response.
- Gains are calculated as:
- $ K_p = 0.8 \cdot Ku $
- $ K_i = \frac{K_p}{0.8 \cdot Tu} $
- $ K_d = 0.194 \cdot K_p \cdot Tu $
3. **IMC (Internal Model Control)**:
- Incorporates a smoothing factor ('λ') to adjust response speed:
- $ K_p = 0.4 \cdot Ku $
- $ K_i = \frac{K_p}{2 \cdot \lambda} $
- $ K_d = 0.5 \cdot K_p \cdot \lambda $
4. **Tyreus-Luyben**:
- Provides robust tuning with minimal overshoot:
- $ K_p = 0.45 \cdot Ku $
- $ K_i = \frac{K_p}{2.2 \cdot Tu} $
- $ K_d = 0.0 $ (No derivative term)
5. **Lambda Tuning (CLD)**:
- Optimizes systems with significant dead time:
- $ K_p = \frac{T}{K(\lambda + L)} $
- $ K_i = \frac{K_p}{T} = \frac{1}{K(\lambda + L)} $
- $ K_d = K_p \cdot 0.5L = \frac{0.5L \cdot T}{K(\lambda + L)} $
---
## Signal Filtering
Filters smooth inputs and outputs using an exponential moving average:
- $\text{filteredValue} = (\alpha \cdot \text{input}) + ((1 - \alpha) \cdot \text{filteredValue})$
- $ \alpha $: Responsiveness of the filter (range: 0.01–1.0).
---
## Example Applications
### 1. Ziegler-Nichols Example: Temperature Control
```cpp
#include
AutoTunePID tempController(0, 255, TuningMethod::ZieglerNichols);
void setup() {
tempController.setSetpoint(75.0); // Target temperature
tempController.enableInputFilter(0.1); // Enable input filtering
tempController.enableAntiWindup(true, 0.8); // Enable anti-windup
tempController.setOscillationMode(OscillationMode::Normal); // Set oscillation mode to Normal
tempController.setOperationalMode(OperationalMode::Tune); // Set operational mode to Tune
}
void loop() {
float temp = readTemperature(); // Read temperature sensor
tempController.update(temp); // Update PID controller
analogWrite(HEATER_PIN, tempController.getOutput()); // Control heater
delay(100);
}
```
### 2. Cohen-Coon Example: Motor Speed Control
```cpp
#include
AutoTunePID motorController(0, 255, TuningMethod::CohenCoon);
void setup() {
motorController.setSetpoint(1500); // Target RPM
motorController.enableInputFilter(0.2); // Enable input filtering
motorController.enableAntiWindup(true, 0.7); // Enable anti-windup
motorController.setOscillationMode(OscillationMode::Half); // Set oscillation mode to Half
motorController.setOperationalMode(OperationalMode::Tune); // Set operational mode to Tune
}
void loop() {
float rpm = readEncoderSpeed(); // Read motor speed
motorController.update(rpm); // Update PID controller
analogWrite(MOTOR_PIN, motorController.getOutput()); // Control motor
delay(100);
}
```
### 3. IMC Example: Pressure Control
```cpp
#include
AutoTunePID pressureController(0, 255, TuningMethod::IMC);
void setup() {
pressureController.setSetpoint(100.0); // Target pressure
pressureController.enableInputFilter(0.1); // Enable input filtering
pressureController.enableAntiWindup(true, 0.8); // Enable anti-windup
pressureController.setOscillationMode(OscillationMode::Normal); // Set oscillation mode to Normal
pressureController.setOperationalMode(OperationalMode::Tune); // Set operational mode to Tune
}
void loop() {
float pressure = readPressureSensor(); // Read pressure sensor
pressureController.update(pressure); // Update PID controller
analogWrite(PUMP_PIN, pressureController.getOutput()); // Control pump
delay(100);
}
```
### 4. Tyreus-Luyben Example: Chemical Reactor Temperature Control
```cpp
#include
AutoTunePID reactorController(0, 255, TuningMethod::TyreusLuyben);
void setup() {
reactorController.setSetpoint(80.0); // Target reactor temperature
reactorController.enableInputFilter(0.1); // Enable input filtering
reactorController.enableAntiWindup(true, 0.8); // Enable anti-windup
reactorController.setOscillationMode(OscillationMode::Half); // Set oscillation mode to Half
reactorController.setOperationalMode(OperationalMode::Tune); // Set operational mode to Tune
}
void loop() {
float temp = readReactorTemperature(); // Read reactor temperature
reactorController.update(temp); // Update PID controller
analogWrite(HEATER_PIN, reactorController.getOutput()); // Control heater
delay(100);
}
```
### 5. Lambda Tuning Example: Flow Control
```cpp
#include
AutoTunePID flowController(0, 255, TuningMethod::LambdaTuning);
void setup() {
flowController.setSetpoint(50.0); // Target flow rate
flowController.enableInputFilter(0.15); // Enable input filtering
flowController.enableAntiWindup(true, 0.9); // Enable anti-windup
flowController.setOscillationMode(OscillationMode::Mild); // Set oscillation mode to Mild
flowController.setOperationalMode(OperationalMode::Tune); // Set operational mode to Tune
}
void loop() {
float flowRate = readFlowSensor(); // Read flow sensor
flowController.update(flowRate); // Update PID controller
analogWrite(VALVE_PIN, flowController.getOutput()); // Control valve
delay(100);
}
```
---
## Performance Considerations
- Update interval fixed at 100ms for stability.
- Filter alpha values impact system responsiveness.
- Auto-tuning duration configurable (default: 5 seconds).
- Memory footprint optimized (~40 bytes per instance).
---
## Detailed Explanation
- For more details about the algorithms used in the library, read [here](docs/explanation.md).
- For more details about the library usage, read [here](docs/usage.md).
- For more details about manual tuning, read [here](docs/manual.md).
- And For those who seek the Flowchart and the state diagram of the library u can see here:
- [Flowchart](docs/flowchart.mermaid)
- [State diagram](docs/state-diagram.mermaid)
---
## Contributing
Contributions are welcome! Please follow these steps:
1. Fork the repository.
2. Create a feature branch.
3. Submit a pull request.
---
## License
This project is licensed under the MIT License. See [LICENSE](LICENSE) file for details.
---
## Support
For bug reports and feature requests, please use the [GitHub issue tracker](https://github.com/lily-osp/AutoTunePID/issues).
For technical questions, contact: azzar.mr.zs@gmail.com
---