-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathPID.cpp
121 lines (96 loc) · 3.07 KB
/
PID.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
PID.cpp - Library for implementing a PID control loop. Used to ensure engines don't overshoot when reaching target roll/pitch.
Created by Myles Grant <[email protected]>
Based on: http://www.arduino.cc/playground/Main/BarebonesPIDForEspresso#pid
See also: https://github.com/grantmd/QuadCopter
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "WProgram.h"
#include "PID.h"
PID::PID(){
iState = 0;
last = 0;
pgain = 0;
igain = 0;
dgain = 0;
}
PID::PID(float p, float i, float d){
PID();
pgain = p;
igain = i;
dgain = d;
}
// get the P gain
float PID::getP(){
return pgain;
}
// get the I gain
float PID::getI(){
return igain;
}
// get the D gain
float PID::getD(){
return dgain;
}
// set the P gain and store it to eeprom
void PID::setP(float p){
pgain = p;
//writeFloat(p, pgainAddress);
}
// set the I gain and store it to eeprom
void PID::setI(float i){
igain = i;
//writeFloat(i, igainAddress);
}
// set the D gain and store it to eeprom
void PID::setD(float d){
dgain = d;
//writeFloat(d, dgainAddress);
}
float PID::updatePID(float target, float cur, float deltaTime){
// these local variables can be factored out if memory is an issue,
// but they make it more readable
float error;
float windupGuard;
// determine how badly we are doing
error = target - cur;
// the pTerm is the view from now, the pgain judges
// how much we care about error at this instant.
pTerm = pgain * error;
// iState keeps changing over time; it's
// overall "performance" over time, or accumulated error
iState += error * deltaTime;
// to prevent the iTerm getting huge despite lots of
// error, we use a "windup guard"
// (this happens when the machine is first turned on and
// it cant help be cold despite its best efforts)
// not necessary, but this makes windup guard values
// relative to the current iGain
windupGuard = WINDUP_GUARD_GAIN / igain;
if (iState > windupGuard)
iState = windupGuard;
else if (iState < -windupGuard)
iState = -windupGuard;
iTerm = igain * iState;
// the dTerm, the difference between the temperature now
// and our last reading, indicated the "speed,"
// how quickly the temp is changing. (aka. Differential)
dTerm = (dgain * (cur - last)) / deltaTime;
// now that we've use lastTemp, put the current temp in
// our pocket until for the next round
last = cur;
// the magic feedback bit
return pTerm + iTerm - dTerm;
}
void PID::resetError(){
iState = 0;
}