Skip to content

Commit d43d07f

Browse files
committed
New version 2.01, faster PID algorithms
1 parent f3227e0 commit d43d07f

File tree

5 files changed

+52
-71
lines changed

5 files changed

+52
-71
lines changed

QuickPID.cpp

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
#include "QuickPID.h"
1616

17-
1817
/* Constructor ********************************************************************
1918
The parameters specified here are those for for which we can't set up
2019
reliable defaults, so we need to have the user set them.
@@ -63,39 +62,26 @@ bool QuickPID::Compute()
6362
{
6463
/*Compute all the working error variables*/
6564
int16_t input = *myInput;
66-
error = (*mySetpoint - input);
67-
int32_t dInput = (int32_t)input - (int32_t)lastInput;
68-
69-
/* outputSum+= (ki * error); */
70-
if (ki < 31) outputSum += FX_INT(FX_MUL(FL_FX(ki), INT_FX(error)));
71-
else outputSum += FX_INT(FX_MUL(FL__FX(ki), INT_FX(error)));
65+
int16_t dInput = input - lastInput;
66+
error = *mySetpoint - input;
7267

73-
/*Add Proportional on Measurement, if P_ON_M is specified*/
74-
/* outputSum -= kp * dInput; */
68+
/*Working error, Proportional on Measurement and Remaining PID output*/
7569
if (!pOnE) {
76-
if (kp < 31) outputSum -= FX_INT(FX_MUL(FL_FX(kp), INT_FX(dInput)));
77-
else outputSum -= FX_INT(FX_MUL(FL__FX(kp), INT_FX(dInput)));
70+
if (ki < 31) outputSum += FX_INT(FX_MUL(FL_FX(ki), INT_FX(error)));
71+
else outputSum += (ki * error);
72+
if (kpd < 31) outputSum -= FX_INT(FX_MUL(FL_FX(kpd), INT_FX(dInput)));
73+
else outputSum -= (kpd * dInput);
7874
}
79-
80-
if (outputSum > outMax) outputSum = outMax;
81-
else if (outputSum < outMin) outputSum = outMin;
82-
83-
/*Add Proportional on Error, if P_ON_E is specified*/
84-
/* if (pOnE) output = (kp * (float)error); */
85-
uint16_t output;
75+
/*Working error, Proportional on Error and remaining PID output*/
8676
if (pOnE) {
87-
if (kp < 31) output = FX_INT(FX_MUL(FL_FX(kp), INT_FX(error)));
88-
else output = FX_INT(FX_MUL(FL__FX(kp), INT_FX(error)));
77+
if (kpi < 31) outputSum += FX_INT(FX_MUL(FL_FX(kpi), INT_FX(error)));
78+
else outputSum += (kpi * error);
79+
if (kd < 31) outputSum -= FX_INT(FX_MUL(FL_FX(kd), INT_FX(dInput)));
80+
else outputSum -= (kd * dInput);
8981
}
90-
else output = 0;
91-
92-
/*Compute Rest of PID output*/
93-
/* output += outputSum - (kd * dInput); */
94-
output += outputSum - FX_INT(FX_MUL(FL_FX(kd), INT_FX(dInput)));
95-
96-
if (output > outMax) output = outMax;
97-
else if (output < outMin) output = outMin;
98-
*myOutput = output;
82+
if (outputSum > outMax) outputSum = outMax;
83+
if (outputSum < outMin) outputSum = outMin;
84+
*myOutput = outputSum;
9985

10086
/*Remember some variables for next time*/
10187
lastInput = input;
@@ -118,10 +104,12 @@ void QuickPID::SetTunings(float Kp, float Ki, float Kd, bool POn)
118104
pOnE = POn == P_ON_E;
119105
dispKp = Kp; dispKi = Ki; dispKd = Kd;
120106

121-
float SampleTimeSec = ((float)SampleTimeUs) / 1000000;
107+
float SampleTimeSec = (float)SampleTimeUs / 1000000;
122108
kp = Kp;
123109
ki = Ki * SampleTimeSec;
124110
kd = Kd / SampleTimeSec;
111+
kpd = kp + kd;
112+
kpi = kp + ki;
125113

126114
if (controllerDirection == REVERSE)
127115
{
@@ -146,11 +134,10 @@ void QuickPID::SetSampleTimeUs(uint32_t NewSampleTimeUs)
146134
if (NewSampleTimeUs > 0)
147135
{
148136
float ratio = (float)NewSampleTimeUs / (float)SampleTimeUs;
149-
150137
ki *= ratio;
151138
kd /= ratio;
152139

153-
SampleTimeUs = (uint32_t)NewSampleTimeUs;
140+
SampleTimeUs = NewSampleTimeUs;
154141
}
155142
}
156143

QuickPID.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,11 @@ class QuickPID
1414
#define P_ON_M 0
1515
#define P_ON_E 1
1616

17-
// s23.8 fixed point defines
18-
#define FL__FX(a) (int64_t)(a*256.0) // float to fixed point
17+
// fixed point defines
1918
#define FL_FX(a) (int32_t)(a*256.0) // float to fixed point
2019
#define FX_FL(a) (float)(a/256.0) // fixed point to float
2120
#define INT_FX(a) (a<<8) // integer to fixed point
2221
#define FX_INT(a) (int32_t)(a>>8) // fixed point to integer
23-
#define FX_ADD(a,b) (a+b) // fixed point add
24-
#define FX_SUB(a,b) (a-b) // fixed point subtract
2522
#define FX_MUL(a,b) ((a*b)>>8) // fixed point multiply
2623
#define FX_DIV(a,b) ((a/b)<<8) // fixed point divide
2724

@@ -82,6 +79,8 @@ class QuickPID
8279
float kp; // (P)roportional Tuning Parameter
8380
float ki; // (I)ntegral Tuning Parameter
8481
float kd; // (D)erivative Tuning Parameter
82+
float kpd = kp + kd;
83+
float kpi = kp + ki;
8584

8685
bool controllerDirection;
8786
bool pOn;

README.md

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,39 @@
11
# QuickPID
22

3-
The API follows the [ArduinoPID](https://github.com/br3ttb/Arduino-PID-Library) library, however there have been some significant updates as follows:
3+
This API (version 2.01) follows the [ArduinoPID](https://github.com/br3ttb/Arduino-PID-Library) library, however there have been some significant updates as follows:
44

55
- Library named as **QuickPID** and can run concurrently with Arduino **PID**
6-
- Fixed-point calculations are used in `Compute()` to improve performance
7-
- `analogReadFast()` added to provide further performance improvement
8-
- `GetError()`added for diagnostics
6+
- Reorganized and more efficient PID algorithms
7+
- Fast fixed-point calculations for smaller coefficients, floating point calculations for larger coefficients
8+
- Faster analog read function
9+
- `GetError()`function added for diagnostics
910

1011
### Performance
1112

12-
PID performance varies depending on how many coefficients are used. When a coefficient is zero, less calculation is done. The controller was benchmarked using an Arduino UNO. QuickPID was benchmarked using analogReadFast() code.
13-
14-
| P_ON_M Compute | Kp | Ki | Kd | Step Time (µS) |
15-
| :-------------------------------------------- | ---- | ---- | ---- | -------------- |
16-
| QuickPID | 2.0 | 5.0 | 0.0 | 88 |
17-
| Arduino PID | 2.0 | 5.0 | 0.0 | 104 |
18-
| **P_ON_M analogRead, Compute, analogWrite** | | | | |
19-
| QuickPID | 2.0 | 5.0 | 0.2 | 164 |
20-
| Arduino PID | 2.0 | 5.0 | 0.2 | 224 |
21-
22-
### Execution Frequency
23-
24-
A future version will provide further performance improvements by pre-calculating (scaling) the terms and providing direct timer with ISR support.
13+
| Compute | Kp | Ki | Kd | Step Time (µS) |
14+
| :----------------------------------- | ---- | ---- | ---- | -------------- |
15+
| QuickPID | 2.0 | 15.0 | 0.05 | 72 |
16+
| Arduino PID | 2.0 | 15.0 | 0.05 | 104 |
17+
| **analogRead, Compute, analogWrite** | | | | |
18+
| QuickPID | 2.0 | 5.0 | 0.2 | 132 |
19+
| Arduino PID | 2.0 | 5.0 | 0.2 | 224 |
2520

2621
### Variables
2722

2823

29-
| Variable | Arduino PID | QuickPID | Data Type | Resolution | Bits Used | Min | Max |
30-
| ------------ | ----------- | ---------------- | ------------ | ---------- | --------- | ----- | ---------- |
31-
| Setpoint | double | int16_t | Binary | 1 | 10 | 0 | 1023 |
32-
| Input | double | int16_t | Binary | 1 | 10 | 0 | 1023 |
33-
| Output | double | uint8_t | Binary | 1 | 8 | 0 | 255 |
34-
| Kp | double | int32_t, int64_t | s23.8, s55.8 | 0.00390625 | 10.8 | <-1m | >1m |
35-
| Ki | double | int32_t, int64_t | s23.8, s55.8 | 0.00390625 | 10.8 | <-1m | >1m |
36-
| Kd | double | int32_t | s23.8 | 0.00390625 | 5.8 | -32 | 31.984375 |
37-
| ratio | double | int32_t | s23.8 | 0.00390625 | 5.8 | -32 | 31.984375 |
38-
| SampleTimeUs | double | uint32_t | Binary | 1 | 32 | 0 | 4294967295 |
39-
| outputSum | double | int16_t | Binary | 1 | 10 | 0 | 1023 |
40-
| error | double | int32_t | Binary | 1 | s10 | -1023 | 1023 |
41-
| dInput | double | int32_t | Binary | 1 | s10 | -1023 | 1023 |
24+
| Variable | Arduino PID | QuickPID | Data Type | Resolution | Bits Used | Min | Max |
25+
| ------------ | ----------- | -------------- | ------------ | -------------------- | --------- | ----------- | ----------- |
26+
| Setpoint | double | int16_t | Binary | 1 | 10 | 0 | 1023 |
27+
| Input | double | int16_t | Binary | 1 | 10 | 0 | 1023 |
28+
| Output | double | uint8_t | Binary | 1 | 8 | 0 | 255 |
29+
| Kp | double | int32_t, float | s23.8, float | 6-7 digits precision | 4 bytes | | |
30+
| Ki | double | int32_t, float | s23.8, float | 6-7 digits precision | 4 bytes | | |
31+
| Kd | double | int32_t, float | s23.8, float | 6-7 digits precision | 4 bytes | | |
32+
| ratio | double | float | float | 6-7 digits precision | 4 bytes | | |
33+
| SampleTimeUs | double | uint32_t | Binary | 1 | 32 | 0 | 4294967295 |
34+
| outputSum | double | int16_t | Binary | 1 | 8 | 0 (limit) | 255 (limit) |
35+
| error | double | int32_t | Binary | 1 | 32 | -2147483648 | 2147483647 |
36+
| dInput | double | int32_t | Binary | 1 | 32 | -2147483648 | 2147483647 |
4237

4338
### Original README
4439

examples/QuickPID_Self_Test/QuickPID_Self_Test.ino

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ uint32_t before, after;
1919
uint16_t cnt = 0;
2020

2121
//Specify the initial tuning parameters
22-
float Kp = 2.0, Ki = 5.0, Kd = 0.0;
22+
float Kp = 2.0, Ki = 15.0, Kd = 0.05;
2323

2424
QuickPID myQuickPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
2525

@@ -53,13 +53,13 @@ void loop()
5353
Serial.println(",");
5454
}
5555

56-
Input = myQuickPID.analogReadFast(PIN_INPUT);
5756
before = micros();
57+
Input = myQuickPID.analogReadFast(PIN_INPUT);
5858
myQuickPID.Compute();
59-
after = micros();
6059
analogWrite(PIN_OUTPUT, Output);
60+
after = micros();
6161

62-
delay(110);
62+
delay(50);
6363
cnt++;
6464
if (cnt == 100) {
6565
analogWrite(PIN_OUTPUT, 0);

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=QuickPID
2-
version=2.0.0
2+
version=2.0.1
33
author=dlloydev
44
maintainer=dlloydev
55
sentence=QuickPID controller

0 commit comments

Comments
 (0)