-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpid.go
62 lines (50 loc) · 1.59 KB
/
pid.go
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
package pctl
// PID is a Proportional, Integral, Derivative controller.
//
// Use IErrMax for anti windup
//
// PID requires approximately 16 clocks per update.
type PID struct {
// P is the proportional gain, unitless
P float64
// I is the integral gain, units of reciprocal seconds
I float64
// D is the derivative gain, units of seconds
D float64
// DT is the inter-update time in seconds. If DT == 0 and I != 0 || D != 0,
// output behavior is undefined.
DT float64
// IErrMax is the cap to the integral error term
// if zero, it is ignored
IErrMax float64
// Setpt is the setpoint, in process units
Setpt float64
// prevErr holds the error on the previous iteration
prevErr float64
// integralErr is the accumulated error
integralErr float64
}
// Update runs the loop once and returns the new output value.
// If the value is not used, or is desired again before the
// next update, it can be retrieved with pid.Output().
// if the input is desired, it can be retrieved with pid.Input().
func (pid *PID) Update(input float64) float64 {
err := pid.Setpt - input
pid.integralErr += err * pid.DT
if pid.IErrMax != 0 && pid.integralErr > pid.IErrMax {
pid.integralErr = pid.IErrMax
}
derivative := (err - pid.prevErr) / pid.DT
output := pid.P*err + pid.I*pid.integralErr + pid.D*derivative
pid.prevErr = err
return output
}
// IErr is the integral error. You will only need to query this
// if you need to debug or tune the loop
func (pid *PID) IErr() float64 {
return pid.integralErr
}
// IntegralReset zeros the integral error
func (pid *PID) IntegralReset() {
pid.integralErr = 0
}