Advertisement
Gazer29

PIDController

Feb 15th, 2021
186
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.63 KB | None | 0 0
  1. --[[
  2.  
  3. PID Controller for Lua
  4. Adapted from http://www.computercraft.info/forums2/index.php?/topic/27755-porting-a-pid-controller-to-lua/
  5. Which was ported from https://github.com/br3ttb/Arduino-PID-Library/
  6.  
  7. --]]
  8.  
  9. local function millis()
  10. return os.clock() * 1000
  11. end
  12.  
  13. PID = {
  14. dispKp = 0.0,
  15. dispKi = 0.0,
  16. dispKd = 0.0,
  17.  
  18. kp = 0.0,
  19. ki = 0.0,
  20. kd = 0.0,
  21.  
  22. controllerDirection = 0,
  23.  
  24. myInput = 0.0,
  25. myOutput = 0.0,
  26. mySetpoint = 0.0,
  27.  
  28. lastTime = 0,
  29. ITerm = 0.0,
  30. lastInput = 0.0,
  31.  
  32. SampleTime = 0,
  33. outMin = 0.0,
  34. outMax = 0.0,
  35. inAuto = true
  36. }
  37.  
  38. -- Constants used by the library
  39. PID.LIBRARY_VERSION = "1.1.1"
  40.  
  41. PID.AUTOMATIC = 1
  42. PID.MANUAL = 0
  43. PID.DIRECT = 0
  44. PID.REVERSE = 1
  45.  
  46. -- Common Functions
  47.  
  48. function PID:SetInput(Input)
  49. self.myInput = Input
  50. end
  51.  
  52. function PID:SetPoint(Setpoint)
  53. self.mySetpoint = Setpoint
  54. end
  55.  
  56. function PID:SetOutput(Output)
  57. self.myOutput = Output
  58. end
  59.  
  60. function PID:SetIterm(Iterm)
  61. self.ITerm = Iterm
  62. end
  63.  
  64.  
  65. function PID:new(Kp, Ki, Kd, ControllerDirection)
  66. local obj = {}
  67. setmetatable(obj, self)
  68. self.__index = self
  69.  
  70. self.kp = Kp
  71. self.ki = Ki
  72. self.kd = Kd
  73.  
  74. self.inAuto = false
  75.  
  76. self:SetOutputLimits(0, 255)
  77.  
  78. self.SampleTime = 10
  79. self:SetControllerDirection(ControllerDirection)
  80.  
  81. self:SetTunings(Kp, Ki, Kd)
  82. self.lastTime = millis() - self.SampleTime
  83. return obj
  84.  
  85. end
  86.  
  87. function PID:SetMode(Mode)
  88. local newAuto = (Mode == PID.AUTOMATIC)
  89. if newAuto == not self.inAuto then
  90. self:Initialize()
  91. end
  92. self.inAuto = newAuto
  93. end
  94.  
  95. function PID:Compute()
  96. if not self.inAuto then return false end
  97. local now = millis()
  98. local timeChange = now - self.lastTime
  99. if timeChange >= self.SampleTime then
  100. local input = self.myInput
  101. local errVal = self.mySetpoint - input
  102.  
  103. -- print("ki: ", self.ki)
  104. -- print("kp: ", self.kp)
  105. -- print("kd: ", self.kd)
  106. -- print("er: ", errVal)
  107. -- print("Max: ", self.outMax)
  108. -- print("Min: ", self.outMin)
  109. self.ITerm = self.ITerm + (self.ki * errVal)
  110. -- print("iterm: ", self.ITerm)
  111. if self.ITerm > self.outMax then self.ITerm = self.outMax end
  112. if self.ITerm < self.outMin then self.ITerm = self.outMin
  113. end
  114.  
  115. local dInput = input - self.lastInput
  116. -- print("Last input:", self.lastInput)
  117. local output = self.kp * errVal + self.ITerm - self.kd * dInput
  118. -- print("Out: ", output)
  119. -- output = output
  120.  
  121. if output >= self.outMax then output = self.outMax
  122. elseif output <= self.outMin then output = self.outMin
  123. end
  124. -- print("Out: ", output)
  125.  
  126. self.myOutput = output
  127. -- print(self.outMax)
  128. self.lastInput = input
  129. self.lastTime = now
  130.  
  131. return true
  132. else
  133. return false
  134. end
  135. end
  136.  
  137. function PID:SetOutputLimits(Min, Max)
  138. if Min >= Max then return end
  139. self.outMin = Min
  140. self.outMax = Max
  141.  
  142. if self.inAuto then
  143. if self.myOutput > self.outMax then self.myOutput = self.outMax
  144. elseif self.myOutput < self.outMin then self.myOutput = self.outMin
  145. end
  146.  
  147. if self.ITerm > self.outMax then self.ITerm = self.outMax
  148. elseif self.ITerm < self.outMin then self.ITerm = self.outMin
  149. end
  150. end
  151. end
  152.  
  153. -- Less common, but publicly available
  154. function PID:SetTunings(Kp, Ki, Kd)
  155. if Kp < 0 or Ki < 0 or Kd < 0 then return end
  156.  
  157. self.dispKp = Kp
  158. self.dispKi = Ki
  159. self.dispKd = Kd
  160.  
  161. local SampleTimeInSec = self.SampleTime / 1000.0
  162.  
  163. self.kp = Kp
  164. self.ki = Ki * SampleTimeInSec
  165. self.kd = Kd / SampleTimeInSec
  166.  
  167. if self.ControllerDirection == PID.REVERSE then
  168. self.kp = 0 - self.kp
  169. self.ki = 0 - self.ki
  170. self.kd = 0 - self.kd
  171. end
  172. end
  173.  
  174. function PID:SetControllerDirection(Direction)
  175. if self.inAuto and Direction ~= self.controllerDirection then
  176. self.kp = 0 - self.kp
  177. self.ki = 0 - self.ki
  178. self.kd = 0 - self.kd
  179. end
  180.  
  181. self.controllerDirection = Direction
  182. end
  183.  
  184. function PID:SetSampleTime(NewSampleTime)
  185. if NewSampleTime > 0 then
  186. ratio = NewSampleTime / self.SampleTime
  187.  
  188. self.ki = self.ki * ratio
  189. self.kd = self.kd / ratio
  190.  
  191. self.SampleTime = NewSampleTime
  192. end
  193. end
  194.  
  195. -- Display functionality
  196. function PID:GetKp()
  197. return self.dispKp
  198. end
  199.  
  200. function PID:GetKi()
  201. return self.dispKi
  202. end
  203.  
  204. function PID:GetKd()
  205. return self.dispKd
  206. end
  207.  
  208. function PID:GetOutput()
  209. return self.myOutput
  210. end
  211.  
  212. function PID:GetMode()
  213. if self.inAuto then
  214. return PID.AUTOMATIC
  215. else
  216. return PID.MANUAL
  217. end
  218. end
  219.  
  220. function PID:GetDirection()
  221. return self.controllerDirection
  222. end
  223.  
  224. -- Private functions
  225. function PID:Initialize()
  226. self.ITerm = self.myOutput
  227. self.lastInput = self.myInput
  228.  
  229. if self.ITerm > self.outMax then
  230. self.ITerm = self.outMax
  231. elseif self.ITerm < self.outMin then
  232. self.ITerm = self.outMin
  233. end
  234. end
  235.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement