Advertisement
Guest User

Coded by stron

a guest
Jul 18th, 2018
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.23 KB | None | 0 0
  1. -- Basic PID-libary
  2. -- Version 1.0
  3. -- Coded By Stron
  4.  
  5. local function clam(x, min, max)
  6.     if x > max then
  7.         return max
  8.     elseif x < min then
  9.         return min
  10.     end
  11. end
  12.  
  13. local second = nil
  14. do
  15.     local done, socket = pcall(require, "socket")
  16.     if not done then
  17.         socket = nil
  18.     end
  19.     local done, computer = pcall(require, "computer")
  20.     if not done then
  21.         computer = nil
  22.     end
  23.     seconds = (socket and socket.gettime) or (computer and computer.uptime) or os.time
  24. end
  25.  
  26. -- Creates a new PID controller.
  27. -- Passing table as an argument will make it used as an object base.
  28. -- It allows for convicient saving and loading of adjusted PID controller.
  29. function new(save)
  30.     assert(save == nil or type(save) == "table", "if save is specified the it hax to be table.")
  31.    
  32.     -- all values of the PID controller
  33.     -- values with '_' at beginning are considered private and shold not be changed.
  34.     local pid = {
  35.         kp = 1,
  36.         ki = 1,
  37.         kd = 1,
  38.         input = nil,
  39.         target = nil,
  40.         output = nil,
  41.        
  42.         minout = -math.huge,
  43.         maxout = math.huge,
  44.        
  45.         _lasttime = nil,
  46.         _lastinput = nil,
  47.         _lterm = 0
  48.     }
  49.    
  50.     -- Copy all values from save do pid
  51.     if save then
  52.         for key, value in pairs(save) do
  53.             if pid[key] then
  54.             pid[key] = value
  55.         end
  56.     end
  57. end
  58.  
  59. -- Exports calibration variables and targeted value.
  60. function pid:save()
  61.     return {kp = self.kp, ki =self.ki, kd = self.kd, target = self.target, minout = self.minout, maxout = self.maxout}
  62.         end
  63.        
  64.         -- This is main method of PID controller.
  65.         -- After creation of controller you have to set 'target' value in controller table
  66.         -- then in loop you should regularly update 'input' value in controller table,
  67.         -- call c:compute() and set 'output' value to the execution system.
  68.         -- c.minout = 0
  69.         -- c.maxout = 100
  70.         -- while true do
  71.         -- c.input = getCurrentEnergyLevel()
  72.         -- c:compute()
  73.         -- reactorcontrol:setAllControllRoads(100 - c.output) -- PID expects the increase of output value will cause increase of input
  74.         -- sleep(0.5)
  75.         -- end
  76.         -- You can limit output range by specifying 'minout' and 'maxout' values in controller table.
  77.         -- By passing 'true' to the 'compute' function you will cause controller to not to =take any actions but only
  78.         -- refresh internal variables. It is mort useful if PID controller was disconnected from the system.
  79.         function pid:compute(waspaused)
  80.             asser(self.input and self.target, "You have to sepecify current input and target before running compute()")
  81.            
  82.             -- reset values if PID was paused for pronolonegd period of time
  83.             if warpaused or self.lasttime == nil or self._lastinput == nil then
  84.                 self._lasttime = seconds()
  85.                 self._lastinput = self.input
  86.                 self._Iterm = self.output or 0
  87.                 return
  88.             end
  89.            
  90.             local err = self.target - self.input
  91.             local dtime = seconds() - self._lasttime
  92.            
  93.             if dtime == 0 then
  94.                 return
  95.             end
  96.            
  97.             self._Iterm = self._Iterm + self.ki * err * dtime
  98.             self._Iterm = clamp(self._Iterm, self.minout, self.maxout)
  99.            
  100.             local dinput = (self.input - self._lastinput) / dtime
  101.            
  102.             self.output = self.kp * err +self._Iterm - self.kd * dinput
  103.             self.output = clamp(self.output,self.minout, self.maxout)
  104.            
  105.             self._lasttime = seconds()
  106.             self._lastinput = self.input
  107.         end
  108.        
  109.         return pid
  110.     end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement