Knowledge Base

PI Control – the PID alternative

PID control is hard.  We’ve got a tutorial that I don’t understand, but there is something much simpler that’s drop dead easy to implement in SPLat or any other programming language.

PI control is the way.  When we’ve got some time I’ll draw some pictures and explain more about it, but our customers have used this for things as diverse as hot air temperature regulation and concrete truck barrel speed control.  It works and isn’t hard to get running quickly.

Here’s a graph collected from the hot air blower.  In this instance:

  • Kc = 12
  • Ti = 100
  • Limit = 70

Colour explanation:

  • Green = Temperature requested by the user
  • Red = Measured temperature
  • Pale Blue = The drive (%) sent to the heater.  The heater control is not fully proportional, it only has 8 steps, about 12.5% each.
  • Gray = The “reset” value – note it clips at 70 to prevent “wind-up”.

For your own use, you’ll have to mess around tuning the kfKc and kfTi values, but it’s nowhere near as hard as doing a PID.


;algorithm constants
kfKc fEQU 12.0
kfTi fEQU 100.0
kfLimit fEQU 70.0 ;prevent windup

;runtime values
fTarget defFLOAT ;target value
fMeasured defFLOAT ;current measured value
fOutput defFLOAT ;current value to output

;algorithm vars
fReset defFLOAT
fError defFLOAT


;===============================================================================
;DESCRIPTION:
; This subroutine is called on a regular tick interval to calculate the next
; output value.
;PARAMETERS:
; -> Nil
;RETURNS:
; <- Nil
;===============================================================================
subDoPIAlgorithm:
; Error = Setpoint - Measured
fRecallQ fTarget ;get the target value
fRecallW fMeasured ;get the actual value
fSub ;calc Target - Actual
fStore fError

; Reset = Reset + Kc/Ti * Error
fLoadQ kfKc
fMul
fWtoQ
fLoadW kfTi
fDiv
fRecallQ fReset
fAdd
fLoadQ kfLimit ;limit integral to..
fGoIfWltQ _THChkResetLow
fSwap
_THChkResetLow
fLoadQ 0.0
fGoIfWgtQ _THSaveReset
fSwap ;..prevent "wind-up"
_THSaveReset
fStore fReset

; Output = Kc * Error + Reset
fLoadW kfKc
fRecallQ fError
fMul
fRecallQ fReset
fAdd

; limit output to 0 - 100%
fLoadQ 0.0
fGoIfWgeQ _THTestMax
fSwap
_THTestMax
fLoadQ 100.0
fGoIfWleQ _THDoDrive
fSwap

_THDoDrive
fStore fOutput
Return