1
0
Fork 0
cpu_ctrl/pid/pid.go

127 lines
3.0 KiB
Go

package pid
import (
"time"
)
type controller struct {
Kp float64
Ki float64
Kd float64
lastTime time.Time
SetPoint float64
SampleTime time.Duration
WindupGuard float64
Output float64
pTerm float64
iTerm float64
dTerm float64
lastError float64
}
/*
PID Controller
*/
type Controller interface {
GetKp() float64
GetKi() float64
GetKd() float64
GetSetPoint() float64
GetSampleTime() time.Duration
GetWindupGuard() float64
GetOutput() float64
SetKp(float64)
SetKi(float64)
SetKd(float64)
SetSetPoint(float64)
SetSampleTime(time.Duration)
SetWindupGuard(float64)
SetOutput(float64)
Clear()
Update(float64) float64
}
/*
create PID Controller
*/
func New(proportionalGain float64, integralGain float64, derivativeGain float64) Controller {
return &controller{
Kp: proportionalGain,
Ki: integralGain,
Kd: derivativeGain,
WindupGuard: 20.0,
lastTime: time.Now(),
}
}
/*
Clears PID computations and coefficients
*/
func (c *controller) Clear() {
c.SetPoint = 0.0
c.pTerm = 0.0
c.iTerm = 0.0
c.dTerm = 0.0
c.lastError = 0.0
c.WindupGuard = 20.0
c.Output = 0.0
}
/*
Calculates PID value for given reference feedback
.. math::
u(t) = K_p e(t) + K_i \int_{0}^{t} e(t)dt + K_d {de}/{dt}
.. figure:: images/pid_1.png
:align: center
Test PID with Kp=1.2, Ki=1, Kd=0.001 (test_pid.py)
*/
func (c *controller) Update(feedbackValue float64) float64 {
var (
errorValue = c.SetPoint - feedbackValue
currentTime = time.Now()
deltaTime, deltaError = currentTime.Sub(c.lastTime), errorValue - c.lastError
)
if deltaTime >= c.SampleTime {
c.pTerm = c.Kp * errorValue
c.iTerm += errorValue * deltaTime.Seconds()
if c.iTerm < -c.WindupGuard {
c.iTerm = -c.WindupGuard
} else if c.iTerm > c.WindupGuard {
c.iTerm = c.WindupGuard
}
c.dTerm = 0.0
if deltaTime.Seconds() > 0.0 {
c.dTerm = deltaError / deltaTime.Seconds()
}
c.lastTime = currentTime
c.lastError = errorValue
c.Output = c.pTerm + (c.Ki * c.iTerm) + (c.Kd * c.dTerm)
}
return c.Output
}
func (c *controller) GetKp() float64 { return c.Kp }
func (c *controller) GetKi() float64 { return c.Ki }
func (c *controller) GetKd() float64 { return c.Kd }
func (c *controller) GetSetPoint() float64 { return c.SetPoint }
func (c *controller) GetSampleTime() time.Duration { return c.SampleTime }
func (c *controller) GetWindupGuard() float64 { return c.WindupGuard }
func (c *controller) GetOutput() float64 { return c.Output }
func (c *controller) SetKp(v float64) { c.Kp = v }
func (c *controller) SetKi(v float64) { c.Ki = v }
func (c *controller) SetKd(v float64) { c.Kd = v }
func (c *controller) SetSetPoint(v float64) { c.SetPoint = v }
func (c *controller) SetSampleTime(v time.Duration) { c.SampleTime = v }
func (c *controller) SetWindupGuard(v float64) { c.WindupGuard = v }
func (c *controller) SetOutput(v float64) { c.Output = v }