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.

Number of "Pulses" Detection
#1
Hi,

Is there an easy way to recognize number of "button presses" in a specific time period.

What I want to do is to apply different scenario if client presses a specific button one time and another scenario if he presses button twice in a defined time interval.

Thanks in advance!
Reply
#2
Check this https://forum.logicmachine.net/showthrea...d=74#pid74
------------------------------
Ctrl+F5
Reply
#3
(04.10.2021, 11:06)p_xatzi Wrote: Hi,

Is there an easy way to recognize number of "button presses" in a specific time period.

What I want to do is to apply different scenario if client presses a specific button one time and another scenario if he presses button twice in a defined time interval.

Thanks in advance!

Hi,

Thanks for the reply!

I have only some basic knowledge of coding so as far as the practical side is concerned let me know if i get it right:

   1. I have to program push button to sent 1 on press and 0 on release on knx bus.
   2. On value 1 of push button telegram (button "press"), time stamp of new event is captured
   3. On value 0 of push button telegram (button "relased"), counter is increased by 1 and event script is executed. First of all sleep function is activated to wait for the result to come from switcher function for specified period (1 sec).
   4. After this period (1 sec) the result (that is edje down ("realeases") detections) is read. If time period has expired the result will be 0.
 
May I ask:
In case of 2nd edje down detection during period, due to new event script call, the desired command will be executed 1 sec later.
So, suppose we have second pulse edje detection almost at the end of time period is it true that a slight delay (of 1 sec) may be present? 

I will test and ask for more help is something goes wrong.

Thanks again!
Reply
#4
Hi again,

Based on the proposed solution
(https://forum.logicmachine.net/showthrea...d=74#pid74)

and thread:
https://forum.logicmachine.net/showthrea...4#pid15204

I have made a edje detection group of scripts which I attach.

'Resident (edje detection).lua' detects and counts pulses. When new pulse is present, a timer is created with help of 'common function.lua' and a corresponding 'timer off' is triggered with help of 'Resident Timer Off.lua' script. In the meanwhile new pulses are counted. At the timeout of timer the 'Typical Event Script.lua' is triggered with value of counter at that time and thus the proper action is executed.

The scripts work really well and detect concurrent pulses from different G.A. Also, when long pressing a button you don' t have to release it in order to execute the action. In addition you can set different timeout for each G.A.

However the issue I have is that it takes more than a second to apply action.
The scripts work only then setting 'Resident Timer Off.lua' with sleep time 1sec. So, I guess that this is the reason for longer delay. If I set 0 it does not work properly.

So, question is:
- Is it possible to set multiple resident scripts with sleep time 0 and if yes what is the reason for improper function in my case.
- Is there any way to reduce edge detection and corresponding actions to fractions of 1 sec.
- Is it possible to dublicate 'Resident (edje detection).lua' and run in parallel in order to organize the edge detections (lights and scenes).

Thanks in advance!

.lua   Resident (edje detection).lua (Size: 2.43 KB / Downloads: 6)


.lua   Common Function.lua (Size: 281 bytes / Downloads: 7)


.lua   Resident Timer Off.lua (Size: 569 bytes / Downloads: 10)


.lua   Typical Event Script.lua (Size: 612 bytes / Downloads: 9)
Reply
#5
This won't work correctly. If a resident script with group monitoring has 1 second sleep time it means that this script can only process 1 telegram per second. All other telegrams will be queued and it will lead to larger delays later on.
I'll provide a working example later.
Reply
#6
Resident script with sleep time set to 0. You only need to edit the config table. You will need to restart the script via disable/enable after each config edit. In the config table each key is a group address which sends 1 on button press and 0 on button release. Value for each key is another table with the button configuration. This way you only need a single script for all buttons with multiple press functionality.

Code:
if not client then
  config = {
    ['0/0/1'] = {
      timeout = 0.5,
      longpress = 1,
      press = function(ptype, count)
        local light1 = '1/1/1'
        local light2 = '1/1/2'

        if ptype == 'short' then
          if count == 1 then
            grp.write(light1, not grp.getvalue(light1))
          else
            grp.write(light2, not grp.getvalue(light2))
          end
        else
          grp.write(light1, false)
          grp.write(light2, false)
        end
      end
    },
    ['1/1/3'] = {
      timeout = 0.5,
      press = function(ptype, count)
        log('press 1/1/3', ptype, count)
      end
    }
  }

  function groupwrite(event)
    local cfg = config[ event.dst ]

    if cfg then
      cfg.pressed = tonumber(event.datahex, 16) ~= 0

      if cfg.pressed then
        cfg.timer = 0
        cfg.count = (cfg.count or 0) + 1
      end
    end
  end

  function press(cfg, ptype, count)
    if type(cfg.press) == 'function' then
      cfg.press(ptype, count)
    end

    cfg.pressed = false
    cfg.timer = nil
    cfg.count = 0
  end

  client = require('localbus').new(0.1)
  client:sethandler('groupwrite', groupwrite)
end

ts, tu = os.microtime()
client:loop(0.2)
diff = math.max(0, os.udifftime(ts, tu))

for addr, cfg in pairs(config) do
  if cfg.timer then
    cfg.timer = cfg.timer + diff

    if cfg.pressed then
      if cfg.longpress and cfg.timer >= cfg.longpress then
        press(cfg, 'long')
      end
    elseif cfg.timer >= (cfg.timeout or 1) then
      press(cfg, 'short', cfg.count)
    end
  end
end
Reply
#7
Thanks admin!

I will check in the following days and come back with some questions because I don' t really know how to code.

However, right now I'd like to ask if it is possible to have multiple resident scripts running at 0 sleep time. If yes is there any way to have a standard running order.

Resident scripts with 1 sec sleep time work as expected for the following thread?

Thanks in advance!
Reply
#8
You can have multiple resident scripts with 0 sleep time but make sure that they don't consume all CPU with busy loops. In the previous script most of time is spent inside the client:loop(0.2) call. The script is in a waiting state until a telegram arrives or a timeout happens so there's no busy loops there.
There's no defined execution order for any scripts.
Polling resident scripts (for example, reading storage data) with a sleep time of 1 or more is generally OK.
Reply
#9
Thanks admin! It works perfectly! Great implementation!

Is it possible to explain shortly why different modules were used in first and your solution? Are there any differences in performance or is it just that in second case we want to loop in predefined time intervals?

Code:
-- Implementation with module 'genohm-scada.eibdgm'
--------------------------------------------------
if not client then
  require('genohm-scada.eibdgm')
 
  -- knx group write handler
  function groupwrite(event)
  end
 
  client = eibdgm:new()
  client:sethandler('groupwrite', groupwrite)
end

client:step()


-- Implementation wih module 'localbus'
---------------------------------------
if not client then

  function groupwrite(event)
  end

  client = require('localbus').new(0.1)
  client:sethandler('groupwrite', groupwrite)
end

client:loop(0.2)
Reply
#10
localbus is the new library version. The old one is just a compatibility layer for old scripts which uses localbus internally.
Reply
#11
Hi,

In the above script created by admin I would like to control scenes sequence (order and delay) between scenes for the same G.A. instance like below.

Is it possible to implement this with 'os.sleep' function as below?

Is there any way I could control scene sequence (order and delay) when multiple scenes should run with same command.

Thanks in advance!

   
Code:
-- ΣΚΗΝΗ @H - H - Leave Home for a while
['20/1/130'] = {
    timeout = 0.5,
    longpress = 5,
    press = function(ptype, count)

      if ptype == 'short' then
        if count == 1 then
          scene.run('@H - R1 - Leave Home for a while - Lights')
          scene.run('@H - R2 - Leave Home for a while - Lights')
          scene.run('@H - R3 - Leave Home for a while - Lights')
          scene.run('@H - R4 - Leave Home for a while - Lights')
          scene.run('@H - R5 - Leave Home for a while - Lights')
          scene.run('@H - R6 - Leave Home for a while - Lights')
         
          os.sleep(0.2)
         
          scene.run('@H - G_LR/DR/KTC/COR - Leave Home for a while - Lights')
          scene.run('@H - B1_LR - Leave Home for a while - Lights')
          scene.run('@H - F1_COR - Leave Home for a while - Lights')   
          scene.run('@H - LDR/RF - Leave Home for a while - Lights')
          --scene.run('@H - H - Leave Home for a while - Outside Lights')
        elseif count == 2 then
          scene.run('@H - R1 - Leave Home for a while - Lights')
          scene.run('@H - R2 - Leave Home for a while - Lights')
          scene.run('@H - R3 - Leave Home for a while - Lights')
          scene.run('@H - R4 - Leave Home for a while - Lights')
          scene.run('@H - R5 - Leave Home for a while - Lights')
          scene.run('@H - R6 - Leave Home for a while - Lights')
          scene.run('@H - G_LR/DR/KTC/COR - Leave Home for a while - Lights')
          scene.run('@H - B1_LR - Leave Home for a while - Lights')
          scene.run('@H - F1_COR - Leave Home for a while - Lights')
          scene.run('@H - LDR/RF - Leave Home for a while - Lights')
          --scene.run('@H - H - Leave Home for a while - Outside Lights')
          scene.run('@H - H - Leave Home for a while - Curtains')
        end
         
      elseif ptype == 'long' then
          scene.savelive('@H - R1 - Leave Home for a while - Lights')
          scene.savelive('@H - R2 - Leave Home for a while - Lights')
          scene.savelive('@H - R3 - Leave Home for a while - Lights')
          scene.savelive('@H - R4 - Leave Home for a while - Lights')
          scene.savelive('@H - R5 - Leave Home for a while - Lights')
          scene.savelive('@H - R6 - Leave Home for a while - Lights')
          scene.savelive('@H - G_LR/DR/KTC/COR - Leave Home for a while - Lights')
          scene.savelive('@H - B1_LR - Leave Home for a while - Lights')
          scene.savelive('@H - F1_COR - Leave Home for a while - Lights')
          scene.savelive('@H - LDR/RF - Leave Home for a while - Lights')
          --scene.savelive('@H - H - Leave Home for a while - Outside Lights')
          scene.savelive('@H - H - Leave Home for a while - Curtains')
      end
     
    end
  },   
Reply
#12
You should not use sleep there as it will block the whole script. What you can do is create an event script which is triggered by single/double/long press. Then this event script will run other scenes as needed.
Reply
#13
(20.04.2022, 07:36)admin Wrote: You should not use sleep there as it will block the whole script. What you can do is create an event script which is triggered by single/double/long press. Then this event script will run other scenes as needed.

Thanks admin!
Reply


Forum Jump: