Thermostat PI - XSPA2474KW - 21.09.2021
Hello,
is it possible to create a thermostat PI (e.g. MTN6212-04XX) with Wiser?
I don't mean to have an MTN6212-04XX in the installation and just to visualize through Wiser.
In fact, I need to replace the MTN6212-04XX with a script.
Thanks for your help!
RE: Thermostat PI - admin - 22.09.2021
This might be helpful: https://openrb.com/example-pid-thermostat-with-lm2/
RE: Thermostat PI - XSPA2474KW - 22.09.2021
In this link mentions that: There is a PID function already added by default in Logic Machine -> Scripts -> Tools menu.
I have Wiser and not Logic Machine and there isn't by default in Wiser.
RE: Thermostat PI - admin - 22.09.2021
The example is somewhat outdated. You need to create a user library named pid and copy the code there.
Then load the library in your resident script:
Code: -- init pid algorithm
if not p then
require('user.pid')
p = PID:init({
current = '1/1/1',
setpoint = '1/1/2',
output = '1/1/3'
})
end
-- run algorithm
p:run()
RE: Thermostat PI - XSPA2474KW - 22.09.2021
I will check it.
Thanks for the help.
Appreciated.
RE: Thermostat PI - XSPA2474KW - 24.09.2021
Can you please tell me what should I write to the residential script?
Thanks in advance.
RE: Thermostat PI - admin - 24.09.2021
See my previous post. The code there is for the resident script. Set the script sleep interval to at least 10 seconds or more. This controls how often the algorithm runs. Change group addresses as needed.
RE: Thermostat PI - XSPA2474KW - 19.10.2023
Hello
I have added in residential the following:
Code: -- init pid algorithm
if not p then
p = PID:init({
current = '32/2/16',
setpoint = '32/2/17',
output = '32/2/18'
})
end
-- run algorithm
p:run()
and in the user library the following
Code: PID = {
-- default params
defaults = {
-- invert algorithm, used for cooling
inverted = false,
-- 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 PID:setoutput()
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
self:setoutput()
-- save previous value
self.previous = current
return self.output
end
but is not working.
I have also this error below in the "error log" window
User library PID:133: attempt to perform arithmetic on field 'previous' (a nil value)
stack traceback:
User library PID:133: in function 'compute'
User library PID:110: in function 'run'
RE: Thermostat PI - admin - 20.10.2023
Check that 32/2/16 exists and has correct data type. Try restarting the script by performing disable/enable.
|