This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

PID Thermostat - cooling mode
#1
I have a LM2 and I try to use the PID script:
http://openrb.com/example-pid-thermostat-with-lm2/
In heating mode it's work great but in cooling mode it's not working ( the value output =0)
Can you tell me what I need to do?
Reply
#2
Try setting inverted = true on line 5.
Reply
#3
(29.06.2016, 07:19)admin Wrote: Try setting inverted = true on line 5.

Thks. I try this but the value output it's still =0.
Reply
#4
Just did a quick simulation and it work correctly for cooling. Have you changed any of the gain values or any other parameters like min/max? Enabling inverted mode just sets all gains to be negative.
Reply
#5
I changed only the value for line 5, inverted=true. I still got the valuea output=0 (you can see in the picture attached).

The resident script that I use is this:

-- init pid algorithm

if not p then
  p = PID:init({
      inverted=true,
current = '10/1/3',
setpoint = '10/1/0',
output = '10/1/2'
      
})
end

-- run algorithm
p:run()

The script that I use is this:

PID = {
      -- default params
      defaults = {
        -- invert algorithm, used for cooling
    inverted = true,
        -- minimum output value
        min = 0,
        -- maximum output value
        max = 100,
        -- proportional gain
        kp = 1,
        -- integral gain
        ki = 1,
        -- derivative gain
        kd = 1,
      }
    }
     
    -- PID init, returns new PID object
    function PID:init(params)
      local n = setmetatable({}, { __index = PID })
      local k, v
     
      -- set user parameters
      n.params = params
     
      -- copy parameters that are set by user
      for k, v in pairs(PID.defaults) do
        if n.params[ k ] == nil then
          n.params[ k ] = v
        end
      end
     
      -- reverse gains in inverted mode
      if n.params.inverted then
        n.params.kp = -n.params.kp
        n.params.ki = -n.params.ki
        n.params.kd = -n.params.kd
      end
     
      return n
    end
     
    -- resets algorithm on init or a switch back from manual mode
    function PID:reset()
      -- previous value
      self.previous = grp.getvalue(self.params.current)
      -- reset iterm
      self.iterm = 0
      -- last running time
      self.lasttime = os.time()
     
      -- clamp iterm
      self:clampiterm()
    end
     
    -- clamps iterm value
    function PID:clampiterm()
      self.iterm = math.max(self.iterm, self.params.min)
      self.iterm = math.min(self.iterm, self.params.max)
    end
     
    -- clamp and set new output value
    function PIDConfusedetoutput()
      local t, object, value
     
      self.output = math.max(self.output, self.params.min)
      self.output = math.min(self.output, self.params.max)
     
      value = math.floor(self.output)
      local t = type(self.params.output)
     
      -- write to output if object is set
      if t == 'string' or t == 'table' then
        if t == 'string' then
          self.params.output = { self.params.output }
        end
     
        for _, output in ipairs(self.params.output) do
          grp.write(output, value, dt.scale)
        end
      end
    end
     
    -- algorithm step, returns nil when disabled or no action is required, output value otherwise
    function PID:run()
      local result
     
      -- get manual mode status
      local manual = self.params.manual and grp.getvalue(self.params.manual) or false
     
      -- in manual mode, do nothing
      if manual then
        self.running = false
      -- not in manual, check if reset is required after switching on
      elseif not self.running then
        self:reset()
        self.running = true
      end
     
      -- compute new value if not in manual mode
      if self.running then
        -- get time between previous and current call
        local now = os.time()
        self.deltatime = now - self.lasttime
        self.lasttime = now
     
        -- run if previous call was at least 1 second ago
        if self.deltatime > 0 then
          result = self:compute()
        end
      end
     
      return result
    end
     
    -- computes new output value
    function PID:compute()
      local current, setpoint, deltasc, deltain, output
     
      -- get input values
      current = grp.getvalue(self.params.current)
      setpoint = grp.getvalue(self.params.setpoint)
     
      -- delta between setpoint and current
      deltasc = setpoint - current
     
      -- calculate new iterm
      self.iterm = self.iterm + self.params.ki * self.deltatime * deltasc
      self:clampiterm()
     
      -- delta between current and previous value
      deltain = current - self.previous
     
      -- calculate output value
      self.output = self.params.kp * deltasc + self.iterm
      self.output = self.output - self.params.kd / self.deltatime * deltain
     
      -- write to output
      selfConfusedetoutput()
     
      -- save previous value
      self.previous = current
     
      return self.output
    end

Attached Files Thumbnail(s)
   
Reply
#6
The same script is working correctly on my device. What sleep interval do you have set for PID resident script. Is there anything in the Error log tab?
Reply
#7
Sleep interval (seconds)=10
I have some errors in Error log Tab ( attached).

Attached Files Thumbnail(s)
   
Reply
#8
Looks like your PID user library has some errors, maybe you have deleted some code by accident?
Reply
#9
The code is the same with this: http://openrb.com/example-pid-thermostat...desyntax_1

I don't know if I need to copy this:

Usage
p = PID:init(parameters)
p:run()

I deleted all empty spaces and now it's working!
Reply


Forum Jump: