11
11
#include " WProgram.h"
12
12
#endif
13
13
14
- #include < PID_v1 .h>
14
+ #include < PID_v1_Motor .h>
15
15
16
16
/* 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
18
18
* reliable defaults, so we need to have the user set them.
19
19
***************************************************************************/
20
20
PID::PID (double * Input, double * Output, double * Setpoint,
21
21
double Kp, double Ki, double Kd, int ControllerDirection)
22
22
{
23
-
23
+
24
24
myOutput = Output;
25
25
myInput = Input;
26
26
mySetpoint = Setpoint;
27
27
inAuto = false ;
28
-
29
- PID::SetOutputLimits (0 , 255 ); // default output limit corresponds to
28
+
29
+ PID::SetOutputLimits (0 , 255 ); // default output limit corresponds to
30
30
// the arduino pwm limits
31
+ PID::SetMotorMinimum (0 );
31
32
32
33
SampleTime = 100 ; // default Controller Sample Time is 0.1 seconds
33
34
34
35
PID::SetControllerDirection (ControllerDirection);
35
36
PID::SetTunings (Kp, Ki, Kd);
36
37
37
- lastTime = millis ()-SampleTime;
38
+ lastTime = millis ()-SampleTime;
38
39
}
39
-
40
-
40
+
41
+
41
42
/* Compute() **********************************************************************
42
43
* This, as they say, is where the magic happens. this function should be called
43
44
* every time "void loop()" executes. the function will decide for itself whether a new
44
45
* pid Output needs to be computed. returns true when the output is computed,
45
46
* false when nothing has been done.
46
- **********************************************************************************/
47
+ **********************************************************************************/
47
48
bool PID::Compute ()
48
49
{
49
50
if (!inAuto) return false ;
@@ -58,14 +59,18 @@ bool PID::Compute()
58
59
if (ITerm > outMax) ITerm= outMax;
59
60
else if (ITerm < outMin) ITerm= outMin;
60
61
double dInput = (input - lastInput);
61
-
62
+
62
63
/* Compute PID Output*/
63
64
double output = kp * error + ITerm- kd * dInput;
64
-
65
+
65
66
if (output > outMax) output = outMax;
66
67
else if (output < outMin) output = outMin;
68
+ else if ((*myOutput < output) && (output < motorMin)){
69
+ output = motorMin;
70
+ ITerm = motorMin;
71
+ }
67
72
*myOutput = output;
68
-
73
+
69
74
/* Remember some variables for next time*/
70
75
lastInput = input;
71
76
lastTime = now;
@@ -76,31 +81,31 @@ bool PID::Compute()
76
81
77
82
78
83
/* SetTunings(...)*************************************************************
79
- * This function allows the controller's dynamic performance to be adjusted.
84
+ * This function allows the controller's dynamic performance to be adjusted.
80
85
* it's called automatically from the constructor, but tunings can also
81
86
* be adjusted on the fly during normal operation
82
- ******************************************************************************/
87
+ ******************************************************************************/
83
88
void PID::SetTunings (double Kp, double Ki, double Kd)
84
89
{
85
90
if (Kp<0 || Ki<0 || Kd<0 ) return ;
86
-
91
+
87
92
dispKp = Kp; dispKi = Ki; dispKd = Kd;
88
-
89
- double SampleTimeInSec = ((double )SampleTime)/1000 ;
93
+
94
+ double SampleTimeInSec = ((double )SampleTime)/1000 ;
90
95
kp = Kp;
91
96
ki = Ki * SampleTimeInSec;
92
97
kd = Kd / SampleTimeInSec;
93
-
98
+
94
99
if (controllerDirection ==REVERSE)
95
100
{
96
101
kp = (0 - kp);
97
102
ki = (0 - ki);
98
103
kd = (0 - kd);
99
104
}
100
105
}
101
-
106
+
102
107
/* SetSampleTime(...) *********************************************************
103
- * sets the period, in Milliseconds, at which the calculation is performed
108
+ * sets the period, in Milliseconds, at which the calculation is performed
104
109
******************************************************************************/
105
110
void PID::SetSampleTime (int NewSampleTime)
106
111
{
@@ -113,7 +118,7 @@ void PID::SetSampleTime(int NewSampleTime)
113
118
SampleTime = (unsigned long )NewSampleTime;
114
119
}
115
120
}
116
-
121
+
117
122
/* SetOutputLimits(...)****************************************************
118
123
* This function will be used far more often than SetInputLimits. while
119
124
* the input to the controller will generally be in the 0-1023 range (which is
@@ -127,22 +132,29 @@ void PID::SetOutputLimits(double Min, double Max)
127
132
if (Min >= Max) return ;
128
133
outMin = Min;
129
134
outMax = Max;
130
-
135
+
131
136
if (inAuto)
132
137
{
133
138
if (*myOutput > outMax) *myOutput = outMax;
134
139
else if (*myOutput < outMin) *myOutput = outMin;
135
-
140
+
136
141
if (ITerm > outMax) ITerm= outMax;
137
142
else if (ITerm < outMin) ITerm= outMin;
138
143
}
139
144
}
140
145
146
+
147
+ void PID::SetMotorMinimum (double MinMotorOutput)
148
+ {
149
+ motorMin = MinMotorOutput;
150
+ }
151
+
152
+
141
153
/* SetMode(...)****************************************************************
142
154
* Allows the controller Mode to be set to manual (0) or Automatic (non-zero)
143
155
* when the transition from manual to auto occurs, the controller is
144
156
* automatically initialized
145
- ******************************************************************************/
157
+ ******************************************************************************/
146
158
void PID::SetMode (int Mode)
147
159
{
148
160
bool newAuto = (Mode == AUTOMATIC);
@@ -152,11 +164,11 @@ void PID::SetMode(int Mode)
152
164
}
153
165
inAuto = newAuto;
154
166
}
155
-
167
+
156
168
/* Initialize()****************************************************************
157
169
* does all the things that need to happen to ensure a bumpless transfer
158
170
* from manual to automatic mode.
159
- ******************************************************************************/
171
+ ******************************************************************************/
160
172
void PID::Initialize ()
161
173
{
162
174
ITerm = *myOutput;
@@ -166,7 +178,7 @@ void PID::Initialize()
166
178
}
167
179
168
180
/* SetControllerDirection(...)*************************************************
169
- * The PID will either be connected to a DIRECT acting process (+Output leads
181
+ * The PID will either be connected to a DIRECT acting process (+Output leads
170
182
* to +Input) or a REVERSE acting process(+Output leads to -Input.) we need to
171
183
* know which one, because otherwise we may increase the output when we should
172
184
* be decreasing. This is called from the constructor.
@@ -178,18 +190,17 @@ void PID::SetControllerDirection(int Direction)
178
190
kp = (0 - kp);
179
191
ki = (0 - ki);
180
192
kd = (0 - kd);
181
- }
193
+ }
182
194
controllerDirection = Direction;
183
195
}
184
196
185
197
/* Status Funcions*************************************************************
186
198
* 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
199
+ * functions query the internal state of the PID. they're here for display
188
200
* purposes. this are the functions the PID Front-end uses for example
189
201
******************************************************************************/
190
202
double PID::GetKp (){ return dispKp; }
191
203
double PID::GetKi (){ return dispKi;}
192
204
double PID::GetKd (){ return dispKd;}
193
205
int PID::GetMode (){ return inAuto ? AUTOMATIC : MANUAL;}
194
206
int PID::GetDirection (){ return controllerDirection;}
195
-
0 commit comments