Skip to content

Commit 5cefbae

Browse files
committed
Version 1.2
-Added capability for Proportional On Measurement -Changed license from GPLv3 to MIT
1 parent 5adeed5 commit 5cefbae

File tree

6 files changed

+135
-58
lines changed

6 files changed

+135
-58
lines changed

PID_v1.cpp

+77-48
Original file line numberDiff line numberDiff line change
@@ -14,36 +14,47 @@
1414
#include <PID_v1.h>
1515

1616
/*Constructor (...)*********************************************************
17-
* The parameters specified here are those for for which we can't set up
17+
* The parameters specified here are those for for which we can't set up
1818
* reliable defaults, so we need to have the user set them.
1919
***************************************************************************/
2020
PID::PID(double* Input, double* Output, double* Setpoint,
21-
double Kp, double Ki, double Kd, int ControllerDirection)
21+
double Kp, double Ki, double Kd, int POn, int ControllerDirection)
2222
{
23-
2423
myOutput = Output;
2524
myInput = Input;
2625
mySetpoint = Setpoint;
27-
inAuto = false;
28-
29-
PID::SetOutputLimits(0, 255); //default output limit corresponds to
26+
inAuto = false;
27+
28+
PID::SetOutputLimits(0, 255); //default output limit corresponds to
3029
//the arduino pwm limits
3130

3231
SampleTime = 100; //default Controller Sample Time is 0.1 seconds
3332

3433
PID::SetControllerDirection(ControllerDirection);
35-
PID::SetTunings(Kp, Ki, Kd);
34+
PID::SetTunings(Kp, Ki, Kd, POn);
3635

37-
lastTime = millis()-SampleTime;
36+
lastTime = millis()-SampleTime;
3837
}
39-
40-
38+
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+
***************************************************************************/
43+
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)
47+
{
48+
49+
}
50+
51+
4152
/* Compute() **********************************************************************
4253
* This, as they say, is where the magic happens. this function should be called
4354
* every time "void loop()" executes. the function will decide for itself whether a new
4455
* pid Output needs to be computed. returns true when the output is computed,
4556
* false when nothing has been done.
46-
**********************************************************************************/
57+
**********************************************************************************/
4758
bool PID::Compute()
4859
{
4960
if(!inAuto) return false;
@@ -52,55 +63,73 @@ bool PID::Compute()
5263
if(timeChange>=SampleTime)
5364
{
5465
/*Compute all the working error variables*/
55-
double input = *myInput;
66+
double input = *myInput;
5667
double error = *mySetpoint - input;
57-
ITerm+= (ki * error);
58-
if(ITerm > outMax) ITerm= outMax;
59-
else if(ITerm < outMin) ITerm= outMin;
6068
double dInput = (input - lastInput);
61-
62-
/*Compute PID Output*/
63-
double output = kp * error + ITerm- kd * dInput;
64-
65-
if(output > outMax) output = outMax;
69+
outputSum+= (ki * error);
70+
71+
/*Add Proportional on Measurement, if P_ON_M is specified*/
72+
if(!pOnE) outputSum-= kp * dInput;
73+
74+
if(outputSum > outMax) outputSum= outMax;
75+
else if(outputSum < outMin) outputSum= outMin;
76+
77+
/*Add Proportional on Error, if P_ON_E is specified*/
78+
double output;
79+
if(pOnE) output = kp * error;
80+
else output = 0;
81+
82+
/*Compute Rest of PID Output*/
83+
output += outputSum - kd * dInput;
84+
85+
if(output > outMax) output = outMax;
6686
else if(output < outMin) output = outMin;
67-
*myOutput = output;
68-
87+
*myOutput = output;
88+
6989
/*Remember some variables for next time*/
7090
lastInput = input;
7191
lastTime = now;
72-
return true;
92+
return true;
7393
}
7494
else return false;
7595
}
7696

77-
7897
/* SetTunings(...)*************************************************************
79-
* This function allows the controller's dynamic performance to be adjusted.
98+
* This function allows the controller's dynamic performance to be adjusted.
8099
* it's called automatically from the constructor, but tunings can also
81100
* be adjusted on the fly during normal operation
82-
******************************************************************************/
83-
void PID::SetTunings(double Kp, double Ki, double Kd)
101+
******************************************************************************/
102+
void PID::SetTunings(double Kp, double Ki, double Kd, int POn)
84103
{
85104
if (Kp<0 || Ki<0 || Kd<0) return;
86-
105+
106+
pOn = POn;
107+
pOnE = POn == P_ON_E;
108+
87109
dispKp = Kp; dispKi = Ki; dispKd = Kd;
88-
89-
double SampleTimeInSec = ((double)SampleTime)/1000;
110+
111+
double SampleTimeInSec = ((double)SampleTime)/1000;
90112
kp = Kp;
91113
ki = Ki * SampleTimeInSec;
92114
kd = Kd / SampleTimeInSec;
93-
115+
94116
if(controllerDirection ==REVERSE)
95117
{
96118
kp = (0 - kp);
97119
ki = (0 - ki);
98120
kd = (0 - kd);
99121
}
100122
}
101-
123+
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);
129+
}
130+
102131
/* SetSampleTime(...) *********************************************************
103-
* sets the period, in Milliseconds, at which the calculation is performed
132+
* sets the period, in Milliseconds, at which the calculation is performed
104133
******************************************************************************/
105134
void PID::SetSampleTime(int NewSampleTime)
106135
{
@@ -113,7 +142,7 @@ void PID::SetSampleTime(int NewSampleTime)
113142
SampleTime = (unsigned long)NewSampleTime;
114143
}
115144
}
116-
145+
117146
/* SetOutputLimits(...)****************************************************
118147
* This function will be used far more often than SetInputLimits. while
119148
* the input to the controller will generally be in the 0-1023 range (which is
@@ -127,22 +156,22 @@ void PID::SetOutputLimits(double Min, double Max)
127156
if(Min >= Max) return;
128157
outMin = Min;
129158
outMax = Max;
130-
159+
131160
if(inAuto)
132161
{
133162
if(*myOutput > outMax) *myOutput = outMax;
134163
else if(*myOutput < outMin) *myOutput = outMin;
135-
136-
if(ITerm > outMax) ITerm= outMax;
137-
else if(ITerm < outMin) ITerm= outMin;
164+
165+
if(outputSum > outMax) outputSum= outMax;
166+
else if(outputSum < outMin) outputSum= outMin;
138167
}
139168
}
140169

141170
/* SetMode(...)****************************************************************
142171
* Allows the controller Mode to be set to manual (0) or Automatic (non-zero)
143172
* when the transition from manual to auto occurs, the controller is
144173
* automatically initialized
145-
******************************************************************************/
174+
******************************************************************************/
146175
void PID::SetMode(int Mode)
147176
{
148177
bool newAuto = (Mode == AUTOMATIC);
@@ -152,21 +181,21 @@ void PID::SetMode(int Mode)
152181
}
153182
inAuto = newAuto;
154183
}
155-
184+
156185
/* Initialize()****************************************************************
157186
* does all the things that need to happen to ensure a bumpless transfer
158187
* from manual to automatic mode.
159-
******************************************************************************/
188+
******************************************************************************/
160189
void PID::Initialize()
161190
{
162-
ITerm = *myOutput;
191+
outputSum = *myOutput;
163192
lastInput = *myInput;
164-
if(ITerm > outMax) ITerm = outMax;
165-
else if(ITerm < outMin) ITerm = outMin;
193+
if(outputSum > outMax) outputSum = outMax;
194+
else if(outputSum < outMin) outputSum = outMin;
166195
}
167196

168197
/* SetControllerDirection(...)*************************************************
169-
* The PID will either be connected to a DIRECT acting process (+Output leads
198+
* The PID will either be connected to a DIRECT acting process (+Output leads
170199
* to +Input) or a REVERSE acting process(+Output leads to -Input.) we need to
171200
* know which one, because otherwise we may increase the output when we should
172201
* be decreasing. This is called from the constructor.
@@ -175,16 +204,16 @@ void PID::SetControllerDirection(int Direction)
175204
{
176205
if(inAuto && Direction !=controllerDirection)
177206
{
178-
kp = (0 - kp);
207+
kp = (0 - kp);
179208
ki = (0 - ki);
180209
kd = (0 - kd);
181-
}
210+
}
182211
controllerDirection = Direction;
183212
}
184213

185214
/* Status Funcions*************************************************************
186215
* Just because you set the Kp=-1 doesn't mean it actually happened. these
187-
* functions query the internal state of the PID. they're here for display
216+
* functions query the internal state of the PID. they're here for display
188217
* purposes. this are the functions the PID Front-end uses for example
189218
******************************************************************************/
190219
double PID::GetKp(){ return dispKp; }

PID_v1.h

+16-6
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,14 @@ class PID
1313
#define MANUAL 0
1414
#define DIRECT 0
1515
#define REVERSE 1
16+
#define P_ON_M 0
17+
#define P_ON_E 1
1618

1719
//commonly used functions **************************************************************************
20+
PID(double*, double*, double*, // * constructor. links the PID to the Input, Output, and
21+
double, double, double, int, int);// Setpoint. Initial tuning parameters are also set here.
22+
// (overload for specifying proportional mode)
23+
1824
PID(double*, double*, double*, // * constructor. links the PID to the Input, Output, and
1925
double, double, double, int); // Setpoint. Initial tuning parameters are also set here
2026

@@ -25,16 +31,19 @@ class PID
2531
// calculation frequency can be set using SetMode
2632
// SetSampleTime respectively
2733

28-
void SetOutputLimits(double, double); //clamps the output to a specific range. 0-255 by default, but
29-
//it's likely the user will want to change this depending on
30-
//the application
34+
void SetOutputLimits(double, double); // * clamps the output to a specific range. 0-255 by default, but
35+
// it's likely the user will want to change this depending on
36+
// the application
3137

3238

3339

3440
//available but not commonly used functions ********************************************************
3541
void SetTunings(double, double, // * While most users will set the tunings once in the
36-
double); // constructor, this function gives the user the option
42+
double); // constructor, this function gives the user the option
3743
// of changing tunings during runtime for Adaptive control
44+
void SetTunings(double, double, // * overload for specifying proportional mode
45+
double, int);
46+
3847
void SetControllerDirection(int); // * Sets the Direction, or "Action" of the controller. DIRECT
3948
// means the output will increase when error is positive. REVERSE
4049
// means the opposite. it's very unlikely that this will be needed
@@ -63,18 +72,19 @@ class PID
6372
double kd; // * (D)erivative Tuning Parameter
6473

6574
int controllerDirection;
75+
int pOn;
6676

6777
double *myInput; // * Pointers to the Input, Output, and Setpoint variables
6878
double *myOutput; // This creates a hard link between the variables and the
6979
double *mySetpoint; // PID, freeing the user from having to constantly tell us
7080
// what these values are. with pointers we'll just know.
7181

7282
unsigned long lastTime;
73-
double ITerm, lastInput;
83+
double outputSum, lastInput;
7484

7585
unsigned long SampleTime;
7686
double outMin, outMax;
77-
bool inAuto;
87+
bool inAuto, pOnE;
7888
};
7989
#endif
8090

README.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
***************************************************************
2-
* Arduino PID Library - Version 1.1.1
2+
* Arduino PID Library - Version 1.2.0
33
* by Brett Beauregard <[email protected]> brettbeauregard.com
44
*
5-
* This Library is licensed under a GPLv3 License
5+
* This Library is licensed under the MIT License
66
***************************************************************
77

88
- For an ultra-detailed explanation of why the code is the way it is, please visit:

examples/PID_PonM/PID_PonM.ino

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/********************************************************
2+
* PID Proportional on measurement Example
3+
* Setting the PID to use Proportional on measurement will
4+
* make the output move more smoothly when the setpoint
5+
* is changed. In addition, it can eliminate overshoot
6+
* in certain processes like sous-vides.
7+
********************************************************/
8+
9+
#include <PID_v1.h>
10+
11+
//Define Variables we'll be connecting to
12+
double Setpoint, Input, Output;
13+
14+
//Specify the links and initial tuning parameters
15+
PID myPID(&Input, &Output, &Setpoint,2,5,1,P_ON_M, DIRECT); //P_ON_M specifies that Proportional on Measurement be used
16+
//P_ON_E (Proportional on Error) is the default behavior
17+
18+
void setup()
19+
{
20+
//initialize the variables we're linked to
21+
Input = analogRead(0);
22+
Setpoint = 100;
23+
24+
//turn the PID on
25+
myPID.SetMode(AUTOMATIC);
26+
}
27+
28+
void loop()
29+
{
30+
Input = analogRead(0);
31+
myPID.Compute();
32+
analogWrite(3,Output);
33+
}
34+
35+
36+

keywords.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,6 @@ GetDirection KEYWORD2
3131
AUTOMATIC LITERAL1
3232
MANUAL LITERAL1
3333
DIRECT LITERAL1
34-
REVERSE LITERAL1
34+
REVERSE LITERAL1
35+
P_ON_E LITERAL1
36+
P_ON_M LITERAL1

library.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=PID
2-
version=1.1.1
2+
version=1.2.0
33
author=Brett Beauregard
44
maintainer=Brett Beauregard
55
sentence=PID controller

0 commit comments

Comments
 (0)