Posts: 212
Threads: 61
Joined: May 2018
Reputation:
4
Hello, has anybody got any good ideas on how to make a peak load limiter based on current KW usage or kwh? Scalable to varius amount of loads to be controlled.
Posts: 940
Threads: 161
Joined: Jul 2015
Reputation:
33
I think firstly you should create a list of your controllable loads with their power and priority.
Done is better than perfect
Posts: 1760
Threads: 6
Joined: Jul 2015
Reputation:
117
Hi,
I created this a while ago, maybe it could help you in your task.
Code: -- Set adresses
address_max = '1/1/2'
address_hyst = '1/1/3'
address_relais1 = '1/1/4'
address_relais2 = '1/1/5'
address_relais3 = '1/1/6'
address_relais4 = '1/1/7'
-- Get measured power
power = event.getvalue()
-- Get limit value
max = grp.getvalue(address_max)
-- Get Hysteresis
hyst = grp.getvalue(address_hyst)
-- Calculate floor value
hyst_floor = math.floor((max - hyst) + 0.5)
-- Check if chanels need to be turned on
if power < hyst_floor then
-- get current state of relais 4
current_state_relais4 = grp.getvalue(address_relais4)
if current_state_relais4 == false then
grp.write(address_relais4, true)
-- exit script and after that cascade to chanel 3
return
end
-- get current state of relais 3
current_state_relais3 = grp.getvalue(address_relais3)
if current_state_relais3 == false then
grp.write(address_relais3, true)
-- exit script and after that cascade to chanel 2
return
end
-- get current state of relais 2
current_state_relais2 = grp.getvalue(address_relais2)
if current_state_relais2 == false then
grp.write(address_relais2, true)
-- exit script and after that cascade to chanel 1
return
end
-- get current state of relais 1
current_state_relais1 = grp.getvalue(address_relais1)
if current_state_relais1 == false then
grp.write(address_relais1, true)
-- exit script
return
end
end
-- Check if chanel 1 need to be turned off, after that cascade to chanel 2, then cascade to chanel 3 etcetera
if power > max then
-- get current state of relais 1
current_state_relais1 = grp.getvalue(address_relais1)
if current_state_relais1 == true then
grp.write(address_relais1, false)
else
-- get current state of relais 2
current_state_relais2 = grp.getvalue(address_relais2)
if current_state_relais2 == true then
grp.write(address_relais2, false)
else
-- get current state of relais 3
current_state_relais3 = grp.getvalue(address_relais3)
if current_state_relais3 == true then
grp.write(address_relais3, false)
else
-- get current state of relais 4
current_state_relais4 = grp.getvalue(address_relais4)
if current_state_relais4 == true then
grp.write(address_relais4, false)
end
end
end
end
end
BR,
Erwin
Posts: 212
Threads: 61
Joined: May 2018
Reputation:
4
(07.12.2018, 21:19)Erwin van der Zwart Wrote: Hi,
I created this a while ago, maybe it could help you in your task.
Code: -- Set adresses
address_max = '1/1/2'
address_hyst = '1/1/3'
address_relais1 = '1/1/4'
address_relais2 = '1/1/5'
address_relais3 = '1/1/6'
address_relais4 = '1/1/7'
-- Get measured power
power = event.getvalue()
-- Get limit value
max = grp.getvalue(address_max)
-- Get Hysteresis
hyst = grp.getvalue(address_hyst)
-- Calculate floor value
hyst_floor = math.floor((max - hyst) + 0.5)
-- Check if chanels need to be turned on
if power < hyst_floor then
-- get current state of relais 4
current_state_relais4 = grp.getvalue(address_relais4)
if current_state_relais4 == false then
grp.write(address_relais4, true)
-- exit script and after that cascade to chanel 3
return
end
-- get current state of relais 3
current_state_relais3 = grp.getvalue(address_relais3)
if current_state_relais3 == false then
grp.write(address_relais3, true)
-- exit script and after that cascade to chanel 2
return
end
-- get current state of relais 2
current_state_relais2 = grp.getvalue(address_relais2)
if current_state_relais2 == false then
grp.write(address_relais2, true)
-- exit script and after that cascade to chanel 1
return
end
-- get current state of relais 1
current_state_relais1 = grp.getvalue(address_relais1)
if current_state_relais1 == false then
grp.write(address_relais1, true)
-- exit script
return
end
end
-- Check if chanel 1 need to be turned off, after that cascade to chanel 2, then cascade to chanel 3 etcetera
if power > max then
-- get current state of relais 1
current_state_relais1 = grp.getvalue(address_relais1)
if current_state_relais1 == true then
grp.write(address_relais1, false)
else
-- get current state of relais 2
current_state_relais2 = grp.getvalue(address_relais2)
if current_state_relais2 == true then
grp.write(address_relais2, false)
else
-- get current state of relais 3
current_state_relais3 = grp.getvalue(address_relais3)
if current_state_relais3 == true then
grp.write(address_relais3, false)
else
-- get current state of relais 4
current_state_relais4 = grp.getvalue(address_relais4)
if current_state_relais4 == true then
grp.write(address_relais4, false)
end
end
end
end
end
BR,
Erwin
Thanks Erwin, this looks like it could work good as a startingpoint.
I'm new to LM5 and scripting, so trial and error will be nessesary, it's great to have some place to start.
Posts: 1760
Threads: 6
Joined: Jul 2015
Reputation:
117
Hi,
I also created something for EV chargers that the max output power is set by the number of active loaders and available power.
I could share that so you can see how that works, it’s a bit more complex.
BR,
Erwin
Posts: 212
Threads: 61
Joined: May 2018
Reputation:
4
Sure, do share. Anything helps.
Posts: 400
Threads: 88
Joined: Jul 2016
Reputation:
3
(07.12.2018, 21:19)Erwin van der Zwart Wrote: Hi,
I created this a while ago, maybe it could help you in your task.
Code: -- Set adresses
address_max = '1/1/2'
address_hyst = '1/1/3'
address_relais1 = '1/1/4'
address_relais2 = '1/1/5'
address_relais3 = '1/1/6'
address_relais4 = '1/1/7'
-- Get measured power
power = event.getvalue()
-- Get limit value
max = grp.getvalue(address_max)
-- Get Hysteresis
hyst = grp.getvalue(address_hyst)
-- Calculate floor value
hyst_floor = math.floor((max - hyst) + 0.5)
-- Check if chanels need to be turned on
if power < hyst_floor then
-- get current state of relais 4
current_state_relais4 = grp.getvalue(address_relais4)
if current_state_relais4 == false then
grp.write(address_relais4, true)
-- exit script and after that cascade to chanel 3
return
end
-- get current state of relais 3
current_state_relais3 = grp.getvalue(address_relais3)
if current_state_relais3 == false then
grp.write(address_relais3, true)
-- exit script and after that cascade to chanel 2
return
end
-- get current state of relais 2
current_state_relais2 = grp.getvalue(address_relais2)
if current_state_relais2 == false then
grp.write(address_relais2, true)
-- exit script and after that cascade to chanel 1
return
end
-- get current state of relais 1
current_state_relais1 = grp.getvalue(address_relais1)
if current_state_relais1 == false then
grp.write(address_relais1, true)
-- exit script
return
end
end
-- Check if chanel 1 need to be turned off, after that cascade to chanel 2, then cascade to chanel 3 etcetera
if power > max then
-- get current state of relais 1
current_state_relais1 = grp.getvalue(address_relais1)
if current_state_relais1 == true then
grp.write(address_relais1, false)
else
-- get current state of relais 2
current_state_relais2 = grp.getvalue(address_relais2)
if current_state_relais2 == true then
grp.write(address_relais2, false)
else
-- get current state of relais 3
current_state_relais3 = grp.getvalue(address_relais3)
if current_state_relais3 == true then
grp.write(address_relais3, false)
else
-- get current state of relais 4
current_state_relais4 = grp.getvalue(address_relais4)
if current_state_relais4 == true then
grp.write(address_relais4, false)
end
end
end
end
end
BR,
Erwin
Hi Erwin,
I have some question about this script.
1. Is this a resident script or event base script?
2 If is it a resident script which is the refresh time? In case it was a event base script, what is the event base object?
3 Power, hyst and power limit are 4 byte floating point object as per Watt?
Thank you for your help.
regards.
Posts: 1760
Threads: 6
Joined: Jul 2015
Reputation:
117
10.12.2018, 18:10
(This post was last modified: 10.12.2018, 18:13 by Erwin van der Zwart.)
Hi,
1. Event based on the measured power
2. NA
3. Doesn’t matter, 1, 2, 4 byte is fine as all is numeric
BR,
Erwin
Posts: 400
Threads: 88
Joined: Jul 2016
Reputation:
3
12.12.2018, 20:09
(This post was last modified: 12.12.2018, 20:09 by Domoticatorino.)
(10.12.2018, 18:10)Erwin van der Zwart Wrote: Hi,
1. Event based on the measured power
2. NA
3. Doesn’t matter, 1, 2, 4 byte is fine as all is numeric
BR,
Erwin
Thank you Erwin. Works very good.
(10.12.2018, 18:10)Erwin van der Zwart Wrote: Hi,
1. Event based on the measured power
2. NA
3. Doesn’t matter, 1, 2, 4 byte is fine as all is numeric
BR,
Erwin
Thank you Erwin. Works very good.
Posts: 1760
Threads: 6
Joined: Jul 2015
Reputation:
117
12.12.2018, 22:45
(This post was last modified: 12.12.2018, 22:46 by Erwin van der Zwart.)
Hi,
Here is a more complex script for load balancing, i use it for EV chargers, they can use max 63 Amp and need minimal 8 Amp, based on active chargers and available power the chargers are set to a maximum loader output over modbus (for our EVLink)
All works with TAG's on the binary state (active/not active) object and a offset of 1 in the main address (32/1/1 = State -> 32/1/1 = Set max charging output) so you can easily add multiple chargers (:
Code: -- Get maximal available amperage
Max_Amp = grp.getvalue('35/0/10')
-- Get current messured amperage
Current_Amp = grp.getvalue('35/0/11')
-- Calculate available amperage for loaders
Available_Amp = Max_Amp - Current_Amp
-- Minimal amperage output on loader
Min_Loader_Amp = 8
-- Maximal amperage output on loader
Max_Loader_Amp = 63
-- Get all loaders on/off states
All_Loaders = grp.tag('LoaderState')
-- Function to sort table by updatetime
local function tableSortCat (a,b)
return a.updatetime < b.updatetime
end
-- Sort table All_Loaders by updatetime
table.sort(All_Loaders, tableSortCat)
-- Create table with active loader
Active_Loaders = {}
-- Determine amount of active loaders
Number_Active_Loaders = 0
-- Ceeate new table with values and only loader tagged bit objects
for _, item in pairs(All_Loaders) do
if item.datatype == 1 or (item.datatype > 999 and item.datatype < 2000) then
if item.value == true then
Number_Active_Loaders = Number_Active_Loaders + 1
end
table.insert(Active_Loaders, {id = item.id, updatetime = item.updatetime, datatype = item.datatype, address = item.address, value = item.value})
end
end
-- Sort table Active_Loaders by updatetime
table.sort(Active_Loaders, tableSortCat)
-- Determine maximum loaders based on available power
Max_Number_Loaders_Possible = math.floor(Available_Amp / Min_Loader_Amp)
-- Check if more loaders are active then max possible loaders
if Number_Active_Loaders < Max_Number_Loaders_Possible then
Max_Number_Loaders_Possible = Number_Active_Loaders
end
--Set available amperage per loader
Available_Amperage_Loader_Per_Unit = math.round(Available_Amp / Max_Number_Loaders_Possible, 2)
--Check if output exceeds loaders Max_Amp
if Available_Amperage_Loader_Per_Unit > Max_Loader_Amp then
Available_Amperage_Loader_Per_Unit = Max_Loader_Amp
end
-- Set loaders to 0 when current amperage exceeds max amperage
if Current_Amp > Max_Amp then
Max_Number_Loaders_Possible = 0
Available_Amperage_Loader_Per_Unit = 0
end
-- Write values to the output of each loader
Number_Loaders_Value_Written = 0
for _, item in pairs(All_Loaders) do
Address_Table = string.split(item.address, "/")
New_Address = Address_Table[1]+1 .. '/' .. Address_Table[2] .. '/' .. Address_Table[3]
if item.value == true then
if Number_Loaders_Value_Written < Max_Number_Loaders_Possible then
grp.checkupdate(New_Address,Available_Amperage_Loader_Per_Unit)
Number_Loaders_Value_Written = Number_Loaders_Value_Written + 1
else
grp.checkupdate(New_Address,0)
end
else
grp.checkupdate(New_Address,0)
end
end
BR,
Erwin
Posts: 12
Threads: 5
Joined: Jul 2018
Reputation:
0
(07.12.2018, 21:19)Erwin van der Zwart Wrote: Hi,
I created this a while ago, maybe it could help you in your task.
Code: -- Set adresses
address_max = '1/1/2'
address_hyst = '1/1/3'
address_relais1 = '1/1/4'
address_relais2 = '1/1/5'
address_relais3 = '1/1/6'
address_relais4 = '1/1/7'
-- Get measured power
power = event.getvalue()
-- Get limit value
max = grp.getvalue(address_max)
-- Get Hysteresis
hyst = grp.getvalue(address_hyst)
-- Calculate floor value
hyst_floor = math.floor((max - hyst) + 0.5)
-- Check if chanels need to be turned on
if power < hyst_floor then
-- get current state of relais 4
current_state_relais4 = grp.getvalue(address_relais4)
if current_state_relais4 == false then
grp.write(address_relais4, true)
-- exit script and after that cascade to chanel 3
return
end
-- get current state of relais 3
current_state_relais3 = grp.getvalue(address_relais3)
if current_state_relais3 == false then
grp.write(address_relais3, true)
-- exit script and after that cascade to chanel 2
return
end
-- get current state of relais 2
current_state_relais2 = grp.getvalue(address_relais2)
if current_state_relais2 == false then
grp.write(address_relais2, true)
-- exit script and after that cascade to chanel 1
return
end
-- get current state of relais 1
current_state_relais1 = grp.getvalue(address_relais1)
if current_state_relais1 == false then
grp.write(address_relais1, true)
-- exit script
return
end
end
-- Check if chanel 1 need to be turned off, after that cascade to chanel 2, then cascade to chanel 3 etcetera
if power > max then
-- get current state of relais 1
current_state_relais1 = grp.getvalue(address_relais1)
if current_state_relais1 == true then
grp.write(address_relais1, false)
else
-- get current state of relais 2
current_state_relais2 = grp.getvalue(address_relais2)
if current_state_relais2 == true then
grp.write(address_relais2, false)
else
-- get current state of relais 3
current_state_relais3 = grp.getvalue(address_relais3)
if current_state_relais3 == true then
grp.write(address_relais3, false)
else
-- get current state of relais 4
current_state_relais4 = grp.getvalue(address_relais4)
if current_state_relais4 == true then
grp.write(address_relais4, false)
end
end
end
end
end
BR,
Erwin
Hello,
A well working script, but is it a easy way to get the outputs to stay off only for 10-15 minutes a time and gets blocked to turn off for a 30-60min or something afterwards? So the it loops trough all the relay channels befor the first channel turns off again.
Bjørn
|