Advertisement
fames

controller

Dec 22nd, 2024
18
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.32 KB | None | 0 0
  1. ControllerObj = {}
  2.  
  3. require("lib")
  4.  
  5. function ControllerObj:new()
  6.     local obj = obj or {}
  7.     setmetatable(obj, {__index = self})
  8.  
  9.     obj.isEnabled = false
  10.  
  11.     obj.p = 1.0         -- proportional gain
  12.     obj.tn = 1.0        -- integral reset time
  13.     obj.d = 0.0         -- derivative
  14.     obj.dFilter = 0     -- derivative filter time (in cylces)
  15.     obj.dError = false  -- use error for derivative. if false, use value
  16.  
  17.     obj.sp = 10.0       -- setpoint
  18.     obj.pv = 0.0
  19.  
  20.     obj.intMax = 100.0  -- integral max
  21.     obj.intMin = 0.0    -- integral min
  22.  
  23.     obj.outMax = 100.0  -- output max
  24.     obj.outMin = 0.0    -- output min
  25.  
  26.     obj.error = 0.0     -- gain
  27.  
  28.     obj.errorLast = 0.0 -- last error
  29.     obj.errorList = {}
  30.  
  31.     obj.dCalcLast = 0.0 -- last value used for derivative calculation
  32.     obj.dCalcList = {}  -- smoothing buffer
  33.     obj.dCalcSum = 0.0  --
  34.  
  35.     obj.int = 0.0       -- integral
  36.     obj.deriv = 0       -- derivative
  37.     obj.cv = 0          -- output
  38.  
  39.     obj.tLast = os.epoch("utc")
  40.     obj.firstCall = true
  41.  
  42.     return obj
  43. end
  44.  
  45. function ControllerObj:update(pv)
  46.     -- time delta calc so the integral is more accurate and the controller doesnt fluctuate with bad server tickrates
  47.     -- os.epoch("utc") is used because its far more accurate than os.time
  48.     local tNow = os.epoch("utc")
  49.     local tDelta = (tNow - self.tLast) / 1000
  50.     if tDelta <= 0 or tDelta >= 10 then
  51.         tDelta = 1
  52.     end
  53.  
  54.     self.pv = pv
  55.  
  56.     -- immediately exit if the controller is disabled
  57.     if not self.isEnabled then
  58.         return 0.0
  59.     end
  60.  
  61.     -- gain
  62.     self.error = (self.sp - self.pv) * self.p
  63.  
  64.     -- integral
  65.     if self.tn <= 0 then
  66.         self.int = 0.0
  67.     elseif self.cv < self.outMax and self.cv > self.outMin then -- anti windup
  68.         if self.int + self.error + self.deriv >= self.outMax then
  69.             self.int = self.outMax - (self.error + self.deriv)
  70.         else
  71.             self.int = ((self.error / self.tn) * tDelta) + self.int
  72.         end
  73.     end
  74.  
  75.     if self.int <= self.intMin then self.int = self.intMin end
  76.     if self.int >= self.intMax then self.int = self.intMax end
  77.  
  78.     -- derivative
  79.  
  80.     local dVal = 0.0
  81.  
  82.     if self.dError then
  83.         dVal = self.error   -- error derivative
  84.     else
  85.         dVal = -(self.pv*self.p) -- value RoC derivative
  86.     end
  87.  
  88.     if self.d >= 0 then
  89.         if self.dFilter > 0 then
  90.             self.dCalcSum = smooth(self.dCalcList, dVal, self.dFilter)
  91.  
  92.             self.deriv = ((self.dCalcSum - self.dCalcLast) * self.d)*tDelta
  93.             self.dCalcLast = self.dCalcSum
  94.         else
  95.             self.dCalcSum = 0.0
  96.             self.deriv = ((dVal - self.dCalcLast) * self.d)*tDelta
  97.             self.dCalcLast = dVal
  98.         end
  99.     else
  100.         self.deriv = 0
  101.     end
  102.  
  103.     self.tLast = os.epoch("utc")
  104.  
  105.     -- output
  106.     self.cv = self.error + self.int + self.deriv
  107.     if self.cv <= self.outMin then self.cv = self.outMin end
  108.     if self.cv >= self.outMax then self.cv = self.outMax end
  109.  
  110.     if self.firstCall and self.cv >= self.outMax then self.int = 0 end
  111.  
  112.     self.firstCall = false
  113.     return self.cv
  114. end
  115.  
  116. function ControllerObj:setEnabled(bool)
  117.     self.isEnabled = bool or false
  118.     if not self.isEnabled then
  119.         self:reset()
  120.     end
  121. end
  122.  
  123.  
  124. function ControllerObj:setGain(gain)
  125.     self.p = gain
  126. end
  127.  
  128. function ControllerObj:setResetTime(time)
  129.     self.tn = time
  130. end
  131.  
  132. function ControllerObj:setDerivative(deriv)
  133.     self.d = deriv
  134. end
  135.  
  136. function ControllerObj:setDerivativeMode(bool)
  137.     self.dError = bool
  138. end
  139.  
  140. function ControllerObj:setDerivativeFilter(cycles)
  141.     self.dFilter = cycles
  142. end
  143.  
  144. function ControllerObj:setSetpoint(sp)
  145.     self.sp = sp
  146. end
  147.  
  148. function ControllerObj:setIntegralMax(max)
  149.     self.intMax = max
  150. end
  151.  
  152. function ControllerObj:setIntegralMin(min)
  153.     self.intMin = min
  154. end
  155.  
  156. function ControllerObj:setOutputMax(max)
  157.     self.outMax = max
  158. end
  159.  
  160. function ControllerObj:setOutputMin(min)
  161.     self.outMin = min
  162. end
  163.  
  164. function ControllerObj:reset()  -- reset the controller values to 0
  165.     self.error = 0.0
  166.     self.int = 0.0
  167.     self.deriv = 0.0
  168.     self.cv = 0.0
  169.     self.errorList = {}
  170.     self.firstCall = false
  171. end
  172.  
  173. function ControllerObj:getPV()
  174.     return self.pv
  175. end
  176.  
  177. function ControllerObj:getCV()
  178.     return self.cv
  179. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement