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.

Logic Gates with Logic Machine FB Editor
#1
Hi
I would like to create a logic schedule like in the photo I am sending (its from a LOGO! Soft Comfort example I made for this schedule). 
What I need to make is when the last room thermostat is getting close I need on electrovalalve to stay oppened so I will create a by pass hydraylic system for the water to avoid much pressure in the water circuit.
How I am going to do it in FB editor cause as far as I can see there is no NAND gate inside editor.
Can you please help me withis issue?

BR

Attached Files Thumbnail(s)
       
Reply
#2
I added nor function to the universal gate script. Resident scrpt 0 interval and tag your inputs sctipt and fill the table
Code:
if not client then   -- each group has 3 fields:   -- tag - status object tag   -- output - status output object   -- mode - calculate mode (and/or/avg/nor)   groups = {         { tag = 'nor1', output = '0/0/8', mode = 'nor' },       }   -- time to wait between last telegram from any status in group and update   updatedelay = 0.5   -- object value cache   values = {}   -- object datatype cache   datatypes = {}   -- send update only when value changes   grp.checkupdate = function(alias, value)     if values[ alias ] ~= value then       grp.update(alias, value)     end   end   calc = {}   -- AVERAGE value   calc['avg'] = function(group)     local result, count, value = 0, 0     for _, address in ipairs(group.objects) do       value = values[ address ]       -- number must be in [0..100] range       if type(value) == 'number' then         result = result + value         count = count + 1       -- boolean true is 100%, false is 0%       elseif type(value) == 'boolean' then         if toboolean(value) then           result = result + 100         end         count = count + 1       end     end     if count > 0 then       result = math.floor(result / count + 0.5)       grp.checkupdate(group.output, result)     end   end   -- AND gate   calc['and'] = function(group)     local result = true     for _, address in ipairs(group.objects) do       result = result and toboolean(values[ address ])     end     grp.checkupdate(group.output, result)   end   -- OR gate   calc['or'] = function(group)     local result = false     for _, address in ipairs(group.objects) do       result = result or toboolean(values[ address ])     end     grp.checkupdate(group.output, result)   end      -- NOR gate   calc['nor'] = function(group)     local result = false     for _, address in ipairs(group.objects) do       result = result or toboolean(values[ address ])     end     grp.checkupdate(group.output, not result)   end   -- prepare each group   for _, group in ipairs(groups) do     object = grp.find(group.output)     -- cache output status object value and datatype     values[ object.address ] = object.data     datatypes[ object.address ] = object.datatype     group.output = object.address     -- group input status object list     group.objects = {}     -- find all status objects and cache values and datatypes     objects = grp.tag(group.tag)     for _, object in ipairs(objects) do       values[ object.address ] = object.data       datatypes[ object.address ] = object.datatype       table.insert(group.objects, object.address)     end     -- force update on first run     group.timer = 0     -- calc function reference     group.fn = calc[ group.mode ]   end   -- handle group writes   function eventhandler(event)     local dst, datatype     dst = event.dst     datatype = datatypes[ event.dst ]     -- unknown object, stop     if not datatype then       return     end     values[ dst ] = dpt.decode(event.datahex, datatype)     -- check if any group needs to be updated     for _, group in ipairs(groups) do       for _, address in ipairs(group.objects) do         if address == dst then           group.timer = updatedelay         end       end     end   end   require('genohm-scada.eibdgm')   client = eibdgm:new({ timeout = 0.25 })   client:sethandler('groupwrite', eventhandler) end tsec, tusec = os.microtime() client:step() delta = os.udifftime(tsec, tusec) -- check if any group has an active timer for _, group in ipairs(groups) do   timer = group.timer   if timer then     timer = timer - delta     -- timer expired, run calc function     if timer <= 0 then       group.fn(group)       timer = nil     end     group.timer = timer   end end
------------------------------
Ctrl+F5
Reply
#3
Hi and thank you for your answer.
Beacuse I am not very familiar with scripting is it another way to do it or can you please explain me how is this going to be executed?
Thank you in advance
Reply
#4
There is no need for any scripting here. Just copy whole script to a resident one and fill the table in line 8. tag is the tag name which you should add to all input objects you want to monitor. output is the group address to you want to write result. mode no need to change, You can use same script for other logics as described.
------------------------------
Ctrl+F5
Reply
#5
(24.11.2022, 08:37)Daniel Wrote: There is no need for any scripting here. Just copy whole script to a resident one and fill the table in line 8. tag is the tag name which you should add to all input objects you want to monitor. output is the group address to you want to write result. mode no need to change, You can use same script for other logics as described.

Hi! 
I just created a new scripting to a resident one as you can see in the photo image and I filled the line in table 8 . I changed the name in the tag place (tag name) but whre all the other inputs are ?
And how I am going to test it to my office like a simulation if it's working or not?

Attached Files Thumbnail(s)
   
Reply
#6
Go to objects and find your input object and click on it. You will see one of the fields Tag, type there nor1
   
Do the same of all other input objects but NOT output.

Go to your resident script and delete it! 
Now create new one and paste my script again.
Change 0/0/8 to 0/0/1 (I'm guessing this is your output object)
Save, just in case disable the script and enable again.
You can simply test it by changing manually values of the input objects and monitor the output.  You do it in object tab.
------------------------------
Ctrl+F5
Reply
#7
Hi thank you for your answer
We made another Logo project cause I have been told that when the specific electrovalve mains open then automatically the heatpump must turn to Off cause we don't want heated water pass through just water in a normal temperature.
So we made this Logic diagram

Attached Files Thumbnail(s)
   
Reply
#8
How will this look when min/max/avg


DanielI added nor function to the universal gate script. Resident scrpt 0 interval and tag your inputs sctipt and fill the table
Code:
if not client then   -- each group has 3 fields:   -- tag - status object tag   -- output - status output object   -- mode - calculate mode (and/or/avg/nor)   groups = {         { tag = 'nor1', output = '0/0/8', mode = 'nor' },       }   -- time to wait between last telegram from any status in group and update   updatedelay = 0.5   -- object value cache   values = {}   -- object datatype cache   datatypes = {}   -- send update only when value changes   grp.checkupdate = function(alias, value)     if values[ alias ] ~= value then       grp.update(alias, value)     end   end   calc = {}   -- AVERAGE value   calc['avg'] = function(group)     local result, count, value = 0, 0     for _, address in ipairs(group.objects) do       value = values[ address ]       -- number must be in [0..100] range       if type(value) == 'number' then         result = result + value         count = count + 1       -- boolean true is 100%, false is 0%       elseif type(value) == 'boolean' then         if toboolean(value) then           result = result + 100         end         count = count + 1       end     end     if count > 0 then       result = math.floor(result / count + 0.5)       grp.checkupdate(group.output, result)     end   end   -- AND gate   calc['and'] = function(group)     local result = true     for _, address in ipairs(group.objects) do       result = result and toboolean(values[ address ])     end     grp.checkupdate(group.output, result)   end   -- OR gate   calc['or'] = function(group)     local result = false     for _, address in ipairs(group.objects) do       result = result or toboolean(values[ address ])     end     grp.checkupdate(group.output, result)   end      -- NOR gate   calc['nor'] = function(group)     local result = false     for _, address in ipairs(group.objects) do       result = result or toboolean(values[ address ])     end     grp.checkupdate(group.output, not result)   end   -- prepare each group   for _, group in ipairs(groups) do     object = grp.find(group.output)     -- cache output status object value and datatype     values[ object.address ] = object.data     datatypes[ object.address ] = object.datatype     group.output = object.address     -- group input status object list     group.objects = {}     -- find all status objects and cache values and datatypes     objects = grp.tag(group.tag)     for _, object in ipairs(objects) do       values[ object.address ] = object.data       datatypes[ object.address ] = object.datatype       table.insert(group.objects, object.address)     end     -- force update on first run     group.timer = 0     -- calc function reference     group.fn = calc[ group.mode ]   end   -- handle group writes   function eventhandler(event)     local dst, datatype     dst = event.dst     datatype = datatypes[ event.dst ]     -- unknown object, stop     if not datatype then       return     end     values[ dst ] = dpt.decode(event.datahex, datatype)     -- check if any group needs to be updated     for _, group in ipairs(groups) do       for _, address in ipairs(group.objects) do         if address == dst then           group.timer = updatedelay         end       end     end   end   require('genohm-scada.eibdgm')   client = eibdgm:new({ timeout = 0.25 })   client:sethandler('groupwrite', eventhandler) end tsec, tusec = os.microtime() client:step() delta = os.udifftime(tsec, tusec) -- check if any group has an active timer for _, group in ipairs(groups) do   timer = group.timer   if timer then     timer = timer - delta     -- timer expired, run calc function     if timer <= 0 then       group.fn(group)       timer = nil     end     group.timer = timer   end end
Reply
#9
Average is already implemented, for min/max add these functions before -- prepare each group
Code:
-- MAX value calc['max'] = function(group)   local result = -math.huge   for _, address in ipairs(group.objects) do     local value = values[ address ]     if type(value) == 'number' then       result = math.max(result, value)     end   end   grp.checkupdate(group.output, result) end -- MIN value calc['min'] = function(group)   local result = math.huge   for _, address in ipairs(group.objects) do     local value = values[ address ]     if type(value) == 'number' then       result = math.min(result, value)     end   end   grp.checkupdate(group.output, result) end

Add mapping like this:
Code:
  groups = {     { tag = 'nor1', output = '0/0/8', mode = 'nor' },     { tag = 'avg1', output = '0/0/1', mode = 'avg' },     { tag = 'min1', output = '0/0/2', mode = 'min' },     { tag = 'max1', output = '0/0/3', mode = 'max' },   }
Reply


Forum Jump: