2
2
/**
3
3
* Small, easy to use PID implementation with advanced controller capability.<br>
4
4
* Minimal usage:<br>
5
- * setPID (p,i,d); <br>
5
+ * MiniPID pid = new MiniPID (p,i,d); <br>
6
6
* ...looping code...{ <br>
7
- * output=getOutput(sensorvalue,target); <br>
7
+ * output= pid. getOutput(sensorvalue,target); <br>
8
8
* }
9
9
*
10
10
* @see http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-direction/improving-the-beginners-pid-introduction
@@ -43,10 +43,27 @@ public class MiniPID{
43
43
//**********************************
44
44
// Constructor functions
45
45
//**********************************
46
+
47
+ /**
48
+ * Create a MiniPID class object.
49
+ * See setP, setI, setD methods for more detailed parameters.
50
+ * @param p Proportional gain. Large if large difference between setpoint and target.
51
+ * @param i Integral gain. Becomes large if setpoint cannot reach target quickly.
52
+ * @param d Derivative gain. Responds quickly to large changes in error. Small values prevents P and I terms from causing overshoot.
53
+ */
46
54
public MiniPID (double p , double i , double d ){
47
55
P =p ; I =i ; D =d ;
48
56
checkSigns ();
49
57
}
58
+
59
+ /**
60
+ * Create a MiniPID class object.
61
+ * See setP, setI, setD, setF methods for more detailed parameters.
62
+ * @param p Proportional gain. Large if large difference between setpoint and target.
63
+ * @param i Integral gain. Becomes large if setpoint cannot reach target quickly.
64
+ * @param d Derivative gain. Responds quickly to large changes in error. Small values prevents P and I terms from causing overshoot.
65
+ * @param f Feed-forward gain. Open loop "best guess" for the output should be. Only useful if setpoint represents a rate.
66
+ */
50
67
public MiniPID (double p , double i , double d , double f ){
51
68
P =p ; I =i ; D =d ; F =f ;
52
69
checkSigns ();
@@ -57,7 +74,7 @@ public MiniPID(double p, double i, double d, double f){
57
74
//**********************************
58
75
/**
59
76
* Configure the Proportional gain parameter. <br>
60
- * This responds quicly to changes in setpoint, and provides most of the initial driving force
77
+ * This responds quickly to changes in setpoint, and provides most of the initial driving force
61
78
* to make corrections. <br>
62
79
* Some systems can be used with only a P gain, and many can be operated with only PI.<br>
63
80
* For position based controllers, this is the first parameter to tune, with I second. <br>
@@ -95,37 +112,68 @@ public void setI(double i){
95
112
// output change due to the I term constant during the transition.
96
113
}
97
114
115
+ /**
116
+ * Changes the D parameter <br>
117
+ * This has two primary effects:
118
+ * <list>
119
+ * <li> Adds a "startup kick" and speeds up system response during setpoint changes
120
+ * <li> Adds "drag" and slows the system when moving toward the target
121
+ * </list>
122
+ * A small D value can be useful for both improving response times, and preventing overshoot.
123
+ * However, in many systems a large D value will cause significant instability, particularly
124
+ * for large setpoint changes.
125
+ * <br>
126
+ * Affects output through <b>output += -D*(current_input_value - last_input_value)</b>
127
+ *
128
+ * @param d New gain value for the Derivative term
129
+ */
98
130
public void setD (double d ){
99
131
D =d ;
100
132
checkSigns ();
101
133
}
102
134
103
135
/**
104
136
* Configure the FeedForward parameter. <br>
105
- * This is excellent for Velocity , rate, and other continuous control modes where you can
137
+ * This is excellent for velocity , rate, and other continuous control modes where you can
106
138
* expect a rough output value based solely on the setpoint.<br>
107
- * Should not be used in "position" based control modes.
139
+ * Should not be used in "position" based control modes.<br>
140
+ * Affects output according to <b>output+=F*Setpoint</b>. Note, that a F-only system is actually open loop.
108
141
*
109
- * @param f Feed forward gain. Affects output according to <b>output+=F*Setpoint</b>;
142
+ * @param f Feed forward gain.
110
143
*/
111
144
public void setF (double f ){
112
145
F =f ;
113
146
checkSigns ();
114
- }
147
+ }
115
148
116
149
/**
117
- * Create a new PID object.
150
+ * Configure the PID object.
151
+ * See setP, setI, setD methods for more detailed parameters.
118
152
* @param p Proportional gain. Large if large difference between setpoint and target.
119
153
* @param i Integral gain. Becomes large if setpoint cannot reach target quickly.
120
154
* @param d Derivative gain. Responds quickly to large changes in error. Small values prevents P and I terms from causing overshoot.
121
155
*/
122
156
public void setPID (double p , double i , double d ){
123
- P =p ;I =i ;D =d ;
157
+ P =p ;D =d ;
158
+ //Note: the I term has additional calculations, so we need to use it's
159
+ //specific method for setting it.
160
+ setI (i );
124
161
checkSigns ();
125
162
}
126
163
164
+ /**
165
+ * Configure the PID object.
166
+ * See setP, setI, setD, setF methods for more detailed parameters.
167
+ * @param p Proportional gain. Large if large difference between setpoint and target.
168
+ * @param i Integral gain. Becomes large if setpoint cannot reach target quickly.
169
+ * @param d Derivative gain. Responds quickly to large changes in error. Small values prevents P and I terms from causing overshoot.
170
+ * @param f Feed-forward gain. Open loop "best guess" for the output should be. Only useful if setpoint represents a rate.
171
+ */
127
172
public void setPID (double p , double i , double d ,double f ){
128
- P =p ;I =i ;D =d ;F =f ;
173
+ P =p ;D =d ;F =f ;
174
+ //Note: the I term has additional calculations, so we need to use it's
175
+ //specific method for setting it.
176
+ setI (i );
129
177
checkSigns ();
130
178
}
131
179
@@ -145,16 +193,19 @@ public void setMaxIOutput(double maximum){
145
193
}
146
194
147
195
/**
148
- * Specify a maximum output. If a single parameter is specified, the minimum is
149
- * set to (-maximum).
150
- * @param output
196
+ * Specify a maximum output range. <br>
197
+ * When one input is specified, output range is configured to
198
+ * <b>[-output, output]</b>
199
+ * @param output
151
200
*/
152
201
public void setOutputLimits (double output ){
153
202
setOutputLimits (-output ,output );
154
203
}
155
204
156
205
/**
157
206
* Specify a maximum output.
207
+ * When two inputs specified, output range is configured to
208
+ * <b>[minimum, maximum]</b>
158
209
* @param minimum possible output value
159
210
* @param maximum possible output value
160
211
*/
@@ -182,19 +233,21 @@ public void setDirection(boolean reversed){
182
233
//**********************************
183
234
184
235
/**
185
- * Set the target for the PID calculations
236
+ * Configure setpoint for the PID calculations<br>
237
+ * This represents the target for the PID system's, such as a
238
+ * position, velocity, or angle. <br>
239
+ * @see MiniPID#getOutput(actual) <br>
186
240
* @param setpoint
187
241
*/
188
242
public void setSetpoint (double setpoint ){
189
243
this .setpoint =setpoint ;
190
- }
244
+ }
191
245
192
246
/**
193
- * Calculate the PID value needed to hit the target setpoint.
194
- * Automatically re-calculates the output at each call.
195
- * @param actual The monitored value
196
- * @param target The target value
197
- * @return calculated output value for driving the actual to the target
247
+ * Calculate the output value for the current PID cycle.<br>
248
+ * @param actual The monitored value, typically as a sensor input.
249
+ * @param setpoint The target value for the system
250
+ * @return calculated output value for driving the system
198
251
*/
199
252
public double getOutput (double actual , double setpoint ){
200
253
double output ;
@@ -287,32 +340,49 @@ else if(maxIOutput!=0){
287
340
}
288
341
289
342
/**
290
- * Calculates the PID value using the last provided setpoint and actual valuess
291
- * @return calculated output value for driving the actual to the target
343
+ * Calculate the output value for the current PID cycle.<br>
344
+ * In no-parameter mode, this uses the last sensor value,
345
+ * and last setpoint value. <br>
346
+ * Not typically useful, and use of parameter modes is suggested. <br>
347
+ * @return calculated output value for driving the system
292
348
*/
293
349
public double getOutput (){
294
350
return getOutput (lastActual ,setpoint );
295
351
}
296
352
297
353
/**
298
- * @param actual
299
- * @return calculated output value for driving the actual to the target
354
+ * Calculate the output value for the current PID cycle.<br>
355
+ * In one parameter mode, the last configured setpoint will be used.<br>
356
+ * @see MiniPID#setSetpoint()
357
+ * @param actual The monitored value, typically as a sensor input.
358
+ * @param setpoint The target value for the system
359
+ * @return calculated output value for driving the system
300
360
*/
301
361
public double getOutput (double actual ){
302
362
return getOutput (actual ,setpoint );
303
363
}
304
364
305
365
/**
306
- * Resets the controller. This erases the I term buildup, and removes D gain on the next loop.
366
+ * Resets the controller. This erases the I term buildup, and removes
367
+ * D gain on the next loop.<br>
368
+ * This should be used any time the PID is disabled or inactive for extended
369
+ * duration, and the controlled portion of the system may have changed due to
370
+ * external forces.
307
371
*/
308
372
public void reset (){
309
373
firstRun =true ;
310
374
errorSum =0 ;
311
375
}
312
376
313
377
/**
314
- * Set the maximum rate the output can increase per cycle.
315
- * @param rate
378
+ * Set the maximum rate the output can increase per cycle.<br>
379
+ * This can prevent sharp jumps in output when changing setpoints or
380
+ * enabling a PID system, which might cause stress on physical or electrical
381
+ * systems. <br>
382
+ * Can be very useful for fast-reacting control loops, such as ones
383
+ * with large P or D values and feed-forward systems.
384
+ *
385
+ * @param rate, with units being the same as the output
316
386
*/
317
387
public void setOutputRampRate (double rate ){
318
388
outputRampRate =rate ;
@@ -323,17 +393,21 @@ public void setOutputRampRate(double rate){
323
393
* <br>Can simplify tuning by helping tuning over a small range applies to a much larger range.
324
394
* <br>This limits the reactivity of P term, and restricts impact of large D term
325
395
* during large setpoint adjustments. Increases lag and I term if range is too small.
326
- * @param range
396
+ * @param range, with units being the same as the expected sensor range.
327
397
*/
328
398
public void setSetpointRange (double range ){
329
399
setpointRange =range ;
330
400
}
331
401
332
402
/**
333
403
* Set a filter on the output to reduce sharp oscillations. <br>
334
- * 0.1 is likely a sane starting value. Larger values P and D oscillations, but force larger I values.
335
- * Uses an exponential rolling sum filter, according to a simple <br>
336
- * <pre>output*(1-strength)*sum(0..n){output*strength^n}</pre>
404
+ * 0.1 is likely a sane starting value. Larger values use historical data
405
+ * more heavily, with low values weigh newer data. 0 will disable, filtering, and use
406
+ * only the most recent value. <br>
407
+ * Increasing the filter strength will P and D oscillations, but force larger I
408
+ * values and increase I term overshoot.<br>
409
+ * Uses an exponential wieghted rolling sum filter, according to a simple <br>
410
+ * <pre>output*(1-strength)*sum(0..n){output*strength^n}</pre> algorithm.
337
411
* @param output valid between [0..1), meaning [current output only.. historical output only)
338
412
*/
339
413
public void setOutputFilter (double strength ){
@@ -364,9 +438,13 @@ private double constrain(double value, double min, double max){
364
438
* @param value to test
365
439
* @param min Minimum value of range
366
440
* @param max Maximum value of range
367
- * @return
441
+ * @return true if value is within range, false otherwise
368
442
*/
369
443
private boolean bounded (double value , double min , double max ){
444
+ // Note, this is an inclusive range. This is so tests like
445
+ // `bounded(constrain(0,0,1),0,1)` will return false.
446
+ // This is more helpful for determining edge-case behaviour
447
+ // than <= is.
370
448
return (min <value ) && (value <max );
371
449
}
372
450
0 commit comments