1
/**********************************************************************************************
2
* Arduino PID Library - Version 1.2.1
3
* by Brett Beauregard <br3ttb@gmail.com> brettbeauregard.com
5
* This Library is licensed under the MIT License
6
**********************************************************************************************/
16
/*Constructor (...)*********************************************************
17
* The parameters specified here are those for for which we can't set up
18
* reliable defaults, so we need to have the user set them.
19
***************************************************************************/
20
PID::PID(double* Input, double* Output, double* Setpoint,
21
double Kp, double Ki, double Kd, int POn, int ControllerDirection)
25
mySetpoint = Setpoint;
28
PID::SetOutputLimits(0, 255); //default output limit corresponds to
29
//the arduino pwm limits
31
SampleTime = 100; //default Controller Sample Time is 0.1 seconds
33
PID::SetControllerDirection(ControllerDirection);
34
PID::SetTunings(Kp, Ki, Kd, POn);
36
lastTime = millis()-SampleTime;
39
/*Constructor (...)*********************************************************
40
* To allow backwards compatability for v1.1, or for people that just want
41
* to use Proportional on Error without explicitly saying so
42
***************************************************************************/
44
PID::PID(double* Input, double* Output, double* Setpoint,
45
double Kp, double Ki, double Kd, int ControllerDirection)
46
:PID::PID(Input, Output, Setpoint, Kp, Ki, Kd, P_ON_E, ControllerDirection)
52
/* Compute() **********************************************************************
53
* This, as they say, is where the magic happens. this function should be called
54
* every time "void loop()" executes. the function will decide for itself whether a new
55
* pid Output needs to be computed. returns true when the output is computed,
56
* false when nothing has been done.
57
**********************************************************************************/
60
if(!inAuto) return false;
61
unsigned long now = millis();
62
unsigned long timeChange = (now - lastTime);
63
if(timeChange>=SampleTime)
65
/*Compute all the working error variables*/
66
double input = *myInput;
67
double error = *mySetpoint - input;
68
double dInput = (input - lastInput);
69
outputSum+= (ki * error);
71
/*Add Proportional on Measurement, if P_ON_M is specified*/
72
if(!pOnE) outputSum-= kp * dInput;
74
if(outputSum > outMax) outputSum= outMax;
75
else if(outputSum < outMin) outputSum= outMin;
77
/*Add Proportional on Error, if P_ON_E is specified*/
79
if(pOnE) output = kp * error;
82
/*Compute Rest of PID Output*/
83
output += outputSum - kd * dInput;
85
if(output > outMax) output = outMax;
86
else if(output < outMin) output = outMin;
89
/*Remember some variables for next time*/
97
/* SetTunings(...)*************************************************************
98
* This function allows the controller's dynamic performance to be adjusted.
99
* it's called automatically from the constructor, but tunings can also
100
* be adjusted on the fly during normal operation
101
******************************************************************************/
102
void PID::SetTunings(double Kp, double Ki, double Kd, int POn)
104
if (Kp<0 || Ki<0 || Kd<0) return;
107
pOnE = POn == P_ON_E;
109
dispKp = Kp; dispKi = Ki; dispKd = Kd;
111
double SampleTimeInSec = ((double)SampleTime)/1000;
113
ki = Ki * SampleTimeInSec;
114
kd = Kd / SampleTimeInSec;
116
if(controllerDirection ==REVERSE)
124
/* SetTunings(...)*************************************************************
125
* Set Tunings using the last-rembered POn setting
126
******************************************************************************/
127
void PID::SetTunings(double Kp, double Ki, double Kd){
128
SetTunings(Kp, Ki, Kd, pOn);
131
/* SetSampleTime(...) *********************************************************
132
* sets the period, in Milliseconds, at which the calculation is performed
133
******************************************************************************/
134
void PID::SetSampleTime(int NewSampleTime)
136
if (NewSampleTime > 0)
138
double ratio = (double)NewSampleTime
139
/ (double)SampleTime;
142
SampleTime = (unsigned long)NewSampleTime;
146
/* SetOutputLimits(...)****************************************************
147
* This function will be used far more often than SetInputLimits. while
148
* the input to the controller will generally be in the 0-1023 range (which is
149
* the default already,) the output will be a little different. maybe they'll
150
* be doing a time window and will need 0-8000 or something. or maybe they'll
151
* want to clamp it from 0-125. who knows. at any rate, that can all be done
153
**************************************************************************/
154
void PID::SetOutputLimits(double Min, double Max)
156
if(Min >= Max) return;
162
if(*myOutput > outMax) *myOutput = outMax;
163
else if(*myOutput < outMin) *myOutput = outMin;
165
if(outputSum > outMax) outputSum= outMax;
166
else if(outputSum < outMin) outputSum= outMin;
170
/* SetMode(...)****************************************************************
171
* Allows the controller Mode to be set to manual (0) or Automatic (non-zero)
172
* when the transition from manual to auto occurs, the controller is
173
* automatically initialized
174
******************************************************************************/
175
void PID::SetMode(uint8_t Mode)
177
bool newAuto = (Mode == AUTOMATIC);
178
if(newAuto && !inAuto)
179
{ /*we just went from manual to auto*/
185
/* Initialize()****************************************************************
186
* does all the things that need to happen to ensure a bumpless transfer
187
* from manual to automatic mode.
188
******************************************************************************/
189
void PID::Initialize()
191
outputSum = *myOutput;
192
lastInput = *myInput;
193
if(outputSum > outMax) outputSum = outMax;
194
else if(outputSum < outMin) outputSum = outMin;
197
/* SetControllerDirection(...)*************************************************
198
* The PID will either be connected to a DIRECT acting process (+Output leads
199
* to +Input) or a REVERSE acting process(+Output leads to -Input.) we need to
200
* know which one, because otherwise we may increase the output when we should
201
* be decreasing. This is called from the constructor.
202
******************************************************************************/
203
void PID::SetControllerDirection(int Direction)
205
if(inAuto && Direction !=controllerDirection)
211
controllerDirection = Direction;
214
/* Status Funcions*************************************************************
215
* Just because you set the Kp=-1 doesn't mean it actually happened. these
216
* functions query the internal state of the PID. they're here for display
217
* purposes. this are the functions the PID Front-end uses for example
218
******************************************************************************/
219
double PID::GetKp(){ return dispKp; }
220
double PID::GetKi(){ return dispKi;}
221
double PID::GetKd(){ return dispKd;}
222
int PID::GetMode(){ return inAuto ? AUTOMATIC : MANUAL;}
223
int PID::GetDirection(){ return controllerDirection;}