Skip to content

Commit 399b33c

Browse files
committed
Update
- Update tuning methods - Update plotter function - Update documentation, Wiki and examples
1 parent 4d6d76c commit 399b33c

10 files changed

Lines changed: 197 additions & 168 deletions

File tree

README.md

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ This is an open loop PID autotuner using a novel s-curve inflection point test m
66

77
This tuning method determines the process gain, dead time, time constant and more by doing a shortened step test that ends just after the [inflection point](http://en.wikipedia.org/wiki/Inflection_point) has been reached. From here, the apparent maximum PV (input) is mathematically determined and the controller's tuning parameters are calculated. Test duration is typically only ½Tau.
88

9-
- See [**WiKi**](https://github.com/Dlloydev/sTune/wiki) for test results and more.
9+
See [**WiKi**](https://github.com/Dlloydev/sTune/wiki) for test results and more:
10+
11+
- [Get_All_Tunings](https://github.com/Dlloydev/sTune/wiki/Get_All_Tunings)
12+
- [plotter function reference](https://github.com/Dlloydev/sTune/wiki/plotter-function-reference)
13+
- [printPidTuner function reference](https://github.com/Dlloydev/sTune/wiki/printPidTuner-function-reference)
14+
- ***TODO**: digital ON/OFF (relay) temperature control*
1015

1116
#### Inflection Point Discovery
1217

@@ -57,7 +62,7 @@ The slope of the tangent line is checked at every sample. When the sign of the c
5762
pvMax = pvIp + slopeIp * kexp; // where kexp = 4.3004 = (1 / exp(-1)) / (1 - exp(-1))
5863
```
5964

60-
- The process gain `Ku` and time constant `Tu` are determined and the selected tuning rule's constants are used to determine `Kp, Ki and Kd`. Also, `controllability` and other details are provided (see comments in `sTune.cpp`).
65+
- The process gain `Ku` and time constant `Tu` are determined and the selected tuning rule's constants are used to determine `Kp, Ki, Kd, Ti and Td`. Also, `controllability` and other details are provided (see comments in `sTune.cpp`).
6166
- In the user's sketch, the PID controller is set to automatic, the tuning parameters are applied the PID controller is run.
6267

6368
### Functions
@@ -71,20 +76,20 @@ sTune(float *input, float *output, TuningRule tuningRule, Action action, SerialM
7176
- `input` and `output` are pointers to the variables holding these values.
7277
- `tuningRule` provides selection of 10 various tuning rules as described in the table below.
7378
- `action` provides choices for controller action (direct or reverse) and whether to perform a fast inflection point test (IP) or a full 5 time constant test (5T). Choices are `directIP`, `direct5T`, `reverseIP` and `reverse5T`.
74-
- `serialMode` provides 6 choices for serial output as described in the table below.
75-
76-
| Open Loop Tuning Methods | Description |
77-
| ------------------------ | ------------------------------------------------------------ |
78-
| `ZN_PID` | Open loop Ziegler-Nichols method with ¼ decay ratio |
79-
| `ZN_Half_PID` | Same as `ZN_PID` but with all constants cut in half |
80-
| `Damped_PID` | Can solve marginal stability issues |
81-
| `NoOvershoot_PID` | Uses C-H-R method (set point tracking) with 0% overshoot |
82-
| `CohenCoon_PID` | Open loop method approximates closed loop response with a ¼ decay ratio |
83-
| `ZN_PI` | Open loop Ziegler-Nichols method with ¼ decay ratio |
84-
| `ZN_Half_PI` | Same as `ZN_PID` but with all constants cut in half |
85-
| `Damped_PI` | Can solve marginal stability issues |
86-
| `NoOvershoot_PI` | Uses C-H-R method (set point tracking) with 0% overshoot |
87-
| `CohenCoon_PI` | Open loop method approximates closed loop response with a ¼ decay ratio |
79+
- `serialMode` provides 6 choices for serial output.
80+
81+
| Open Loop Tuning Methods | Autotune Plot (using PWM output) | Description |
82+
| ------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
83+
| `ZN_PID` | [![Click to enlarge](https://user-images.githubusercontent.com/63488701/149276354-fcec7626-4f0a-4ce2-a8a2-078745a84dcd.png)](https://user-images.githubusercontent.com/63488701/149275791-a46f353a-3215-486c-a9ce-d96183897272.PNG) | Open Loop Ziegler-Nichols method with ¼ decay ratio |
84+
| `DampedOsc_PID` | [![Click to enlarge](https://user-images.githubusercontent.com/63488701/149277219-48534317-cf0f-44f0-a5be-12653b2f6e0c.png)](https://user-images.githubusercontent.com/63488701/149275509-68d12ba6-269a-4ce1-b8a7-36037518c49b.PNG) | Damped Oscillation method can solve marginal stability issues |
85+
| `NoOvershoot_PID` | [![Click to enlarge](https://user-images.githubusercontent.com/63488701/149277649-7bdf4a72-4de6-41b2-9825-628d4d742423.png)](https://user-images.githubusercontent.com/63488701/149275728-4fca57f0-c975-4350-ab45-56d50b7c2cdf.PNG) | No Overshoot uses the C-H-R method (set point tracking) with 0% overshoot |
86+
| `CohenCoon_PID` | [![Click to enlarge](https://user-images.githubusercontent.com/63488701/149278074-6a01584e-0c9b-44bf-b595-f436f653f220.png)](https://user-images.githubusercontent.com/63488701/149275398-69586823-0267-4834-8183-d383713f2d27.PNG) | Open loop Cohen Coon method approximates closed loop response with a ¼ decay ratio |
87+
| `Mixed_PID` | [![Click to enlarge](https://user-images.githubusercontent.com/63488701/149278272-5057825c-5d92-4e69-9790-c90fd5235eaf.png)](https://user-images.githubusercontent.com/63488701/149275646-7aa0d8c9-397e-4bc5-8110-85b54a951c4f.PNG) | Mixed method averages the gains for `ZN_PID`, `DampedOsc_PID`, `NoOvershoot_PID` and `CohenCoon_PID` |
88+
| `ZN_PI` | | Open Loop Ziegler-Nichols method with ¼ decay ratio |
89+
| `DampedOsc_PI` | | Damped Oscillation method can solve marginal stability issues |
90+
| `NoOvershoot_PI` | | No Overshoot uses the C-H-R method (set point tracking) with 0% overshoot |
91+
| `CohenCoon_PI` | | Open loop Cohen Coon method approximates closed loop response with a ¼ decay ratio |
92+
| `Mixed_PI` | | Mixed method averages the gains for `ZN_PI`, `DampedOsc_PI`, `NoOvershoot_PI` and `CohenCoon_PI` |
8893

8994
| Serial Mode | Description |
9095
| --------------- | ------------------------------------------------------------ |
@@ -99,16 +104,16 @@ sTune(float *input, float *output, TuningRule tuningRule, Action action, SerialM
99104

100105
```c++
101106
sTune tuner = sTune(&Input, &Output, tuner.ZN_PID, tuner.directIP, tuner.printALL);
102-
/* ZN_PID directIP serialOFF
103-
ZN_Half_PID direct5T printALL
104-
Damped_PID reverseIP printSUMMARY
105-
NoOvershoot_PID reverse5T printDEBUG
106-
CohenCoon_PID printPIDTUNER
107-
ZN_PI serialPLOTTER
108-
ZN_Half_PI
109-
Damped_PI
107+
/* ZN_PID directIP serialOFF
108+
DampedOsc_PID direct5T printALL
109+
NoOvershoot_PID reverseIP printSUMMARY
110+
CohenCoon_PID reverse5T printDEBUG
111+
Mixed_PID
112+
ZN_PI
113+
DampedOsc_PI
110114
NoOvershoot_PI
111115
CohenCoon_PI
116+
Mixed_PI
112117
*/
113118
```
114119

@@ -132,18 +137,19 @@ void SetTuningMethod(TuningMethod TuningMethod);
132137
#### Query Functions
133138

134139
```c++
135-
float GetKp(); // proportional gain
136-
float GetKi(); // integral gain
137-
float GetKd(); // derivative gain
138-
float GetProcessGain(); // process gain
139-
float GetDeadTime(); // process dead time (seconds)
140-
float GetTau(); // process time constant (seconds)
141-
float GetTimeIntegral(); // process time integral (seconds)
142-
float GetTimeDerivative(); // process time derivative (seconds)
140+
float GetKp(); // proportional gain
141+
float GetKi(); // integral gain
142+
float GetKd(); // derivative gain
143+
float GetTi(); // integral time
144+
float GetTd(); // derivative time
145+
float GetProcessGain(); // process gain
146+
float GetDeadTime(); // process dead time (seconds)
147+
float GetTau(); // process time constant (seconds)
143148
uint8_t GetControllerAction();
144149
uint8_t GetSerialMode();
145-
uint8_t GetTuningRule();
150+
uint8_t GetTuningMethod();
146151
void GetAutoTunings(float * kp, float * ki, float * kd);
152+
147153
```
148154
149155
#### Controllability of the process

examples/Autotune_PID_v1/Autotune_PID_v1.ino

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,17 @@ float input = 0, output = 0, kp = 0, ki = 0, kd = 0; // tuner
2929

3030
PID myPID(&Input, &Output, &Setpoint, 0, 0, 0, DIRECT);
3131

32-
sTune tuner = sTune(&input, &output, tuner.ZN_PID, tuner.directIP, tuner.printALL);
33-
/* ZN_PID directIP serialOFF
34-
ZN_Half_PID direct5T printALL
35-
Damped_PID reverseIP printSUMMARY
36-
NoOvershoot_PID reverse5T printDEBUG
37-
CohenCoon_PID printPIDTUNER
38-
ZN_PI serialPLOTTER
39-
ZN_Half_PI
40-
Damped_PI
32+
sTune tuner = sTune(&Input, &Output, tuner.Mixed_PID, tuner.directIP, tuner.printALL);
33+
/* ZN_PID directIP serialOFF
34+
DampedOsc_PID direct5T printALL
35+
NoOvershoot_PID reverseIP printSUMMARY
36+
CohenCoon_PID reverse5T printDEBUG
37+
Mixed_PID
38+
ZN_PI
39+
DampedOsc_PI
4140
NoOvershoot_PI
4241
CohenCoon_PI
42+
Mixed_PI
4343
*/
4444
void setup() {
4545
analogReference(EXTERNAL); // AVR
@@ -58,8 +58,9 @@ void loop() {
5858

5959
case tuner.tunings: // active just once when sTune is done
6060
tuner.GetAutoTunings(&kp, &ki, &kd); // sketch variables updated by sTune
61-
myPID.SetMode(AUTOMATIC); // the PID is turned on (automatic)
6261
myPID.SetSampleTime((testTimeSec * 1000) / samples); // PID sample rate
62+
Output = 0; // required before switching PID to Automatic
63+
myPID.SetMode(AUTOMATIC); // the PID is turned on (automatic)
6364
myPID.SetTunings(kp, ki, kd); // update PID with the new tunings
6465
break;
6566

examples/Autotune_Plotter/Autotune_Plotter.ino

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,17 @@ QuickPID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd,
3232
myPID.iAwMode::iAwClamp,
3333
myPID.Action::direct);
3434

35-
sTune tuner = sTune(&Input, &Output, tuner.ZN_PID, tuner.directIP, tuner.serialPLOTTER);
36-
/* ZN_PID directIP serialOFF
37-
ZN_Half_PID direct5T printALL
38-
Damped_PID reverseIP printSUMMARY
39-
NoOvershoot_PID reverse5T printDEBUG
40-
CohenCoon_PID printPIDTUNER
41-
ZN_PI serialPLOTTER
42-
ZN_Half_PI
43-
Damped_PI
35+
sTune tuner = sTune(&Input, &Output, tuner.Mixed_PID, tuner.directIP, tuner.printALL);
36+
/* ZN_PID directIP serialOFF
37+
DampedOsc_PID direct5T printALL
38+
NoOvershoot_PID reverseIP printSUMMARY
39+
CohenCoon_PID reverse5T printDEBUG
40+
Mixed_PID
41+
ZN_PI
42+
DampedOsc_PI
4443
NoOvershoot_PI
4544
CohenCoon_PI
45+
Mixed_PI
4646
*/
4747
void setup() {
4848
analogReference(EXTERNAL); // AVR
@@ -60,16 +60,17 @@ void loop() {
6060

6161
case tuner.tunings: // active just once when sTune is done
6262
tuner.GetAutoTunings(&Kp, &Ki, &Kd); // sketch variables updated by sTune
63+
myPID.SetSampleTimeUs((testTimeSec * 1000000) / samples); // PID sample rate (same as sTune)
64+
Output = 0; // required before switching PID to Automatic
6365
myPID.SetMode(myPID.Control::automatic); // the PID is turned on (automatic)
64-
myPID.SetSampleTimeUs((testTimeSec * 1000000) / samples); // PID sample rate
6566
myPID.SetTunings(Kp, Ki, Kd); // update PID with the new tunings
6667
break;
6768

6869
case tuner.runPid: // this case runs once per sample period after case "tunings"
6970
Input = (analogRead(inputPin) / mvResolution) - bias;
7071
myPID.Compute();
7172
analogWrite(outputPin, Output);
72-
tuner.plotter(Setpoint, 10); // plots every 10th sample
73+
tuner.plotter(Setpoint, 0.5, 6, 1); // plot output scaled 0.5, plot every 6th sample, plot averaged input
7374
break;
7475
}
7576
// put your main code here, to run repeatedly

examples/Autotune_QuickPID/Autotune_QuickPID.ino

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,17 +32,17 @@ QuickPID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd,
3232
myPID.iAwMode::iAwClamp,
3333
myPID.Action::direct);
3434

35-
sTune tuner = sTune(&Input, &Output, tuner.ZN_PID, tuner.directIP, tuner.printALL);
36-
/* ZN_PID directIP serialOFF
37-
ZN_Half_PID direct5T printALL
38-
Damped_PID reverseIP printSUMMARY
39-
NoOvershoot_PID reverse5T printDEBUG
40-
CohenCoon_PID printPIDTUNER
41-
ZN_PI serialPLOTTER
42-
ZN_Half_PI
43-
Damped_PI
35+
sTune tuner = sTune(&Input, &Output, tuner.Mixed_PID, tuner.directIP, tuner.printALL);
36+
/* ZN_PID directIP serialOFF
37+
DampedOsc_PID direct5T printALL
38+
NoOvershoot_PID reverseIP printSUMMARY
39+
CohenCoon_PID reverse5T printDEBUG
40+
Mixed_PID
41+
ZN_PI
42+
DampedOsc_PI
4443
NoOvershoot_PI
4544
CohenCoon_PI
45+
Mixed_PI
4646
*/
4747
void setup() {
4848
analogReference(EXTERNAL); // AVR
@@ -60,8 +60,9 @@ void loop() {
6060

6161
case tuner.tunings: // active just once when sTune is done
6262
tuner.GetAutoTunings(&Kp, &Ki, &Kd); // sketch variables updated by sTune
63+
myPID.SetSampleTimeUs((testTimeSec * 1000000) / samples); // PID sample rate (same as sTune)
64+
Output = 0; // required before switching PID to Automatic
6365
myPID.SetMode(myPID.Control::automatic); // the PID is turned on (automatic)
64-
myPID.SetSampleTimeUs((testTimeSec * 1000000) / samples); // PID sample rate
6566
myPID.SetTunings(Kp, Ki, Kd); // update PID with the new tunings
6667
break;
6768

0 commit comments

Comments
 (0)