Logic Machine Forum
Peak load limiter - Printable Version

+- Logic Machine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8)
+--- Thread: Peak load limiter (/showthread.php?tid=1779)



Peak load limiter - tomnord - 07.12.2018

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.


RE: Peak load limiter - buuuudzik - 07.12.2018

I think firstly you should create a list of your controllable loads with their power and priority.


RE: Peak load limiter - Erwin van der Zwart - 07.12.2018

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


RE: Peak load limiter - tomnord - 07.12.2018

(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.


RE: Peak load limiter - Erwin van der Zwart - 08.12.2018

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


RE: Peak load limiter - tomnord - 08.12.2018

Sure, do share. Anything helps.


RE: Peak load limiter - Domoticatorino - 10.12.2018

(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.


RE: Peak load limiter - Erwin van der Zwart - 10.12.2018

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


RE: Peak load limiter - Domoticatorino - 12.12.2018

(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.


RE: Peak load limiter - Erwin van der Zwart - 12.12.2018

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


RE: Peak load limiter - BMA - 19.02.2021

(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