Q. Respond to 3 within any 60 sec. period

dchurch

New Member
New-B
Using 8M or 14M

Please help.

I am trying to find a routine that will only respond (EG output 1 high) when input pin1 goes momentarily high 3 times within "any" 60 second period.

My routine wont cut it> It only responds to 3 highs within "a" 60 second period_ and then goes back to start.

What I tried:
I wrote a routine that basically uses high #1 to start it, followed by a loop that requires high #2 to continue (or back to start), followed by a loop that requires high #3 to get a response (or back to start).

Details...
I used something like loop 1 to 30 with a pause to add up to about 60 seconds. My momentary switch goes high for 3 seconds, so_ I included a "wait" prior to "goto" so that a mom high wouldn't continue to the next loop.

I was looking at using "If Then..." but I still see the same problem.
 

lbenson

Senior Member
The timer code in this long but informative thread will raise a flag for you once a second, which would allow you to do what you want: [a]http://www.picaxeforum.co.uk/showthread.php?t=5849[/a]

But the code below just uses a pause of one second in each loop. The timing is only approximate, and doesn't take into account the amount of time the non-pause instructions take.

Essentially you do a short main loop (code not tested, but something like this should work):

Code:
symbol push1 = b13 ' count of seconds since push # 1 was detected
symbol push2 = b12 ' count of seconds since push # 2 was detected
symbol pushbutton = pin3

main:
  do
    if push1 > 0 then 
      push1 = push1 + 1
    endif
    if push2 > 0 then 
      push2 = push2 + 1
    endif
    if push1 > 61 then          ' we have timed out on this counter (we started counting at 1, not zero)
      push1 = push2
      push2 = 0
    endif
    if pushbutton = 1 then
      pause 100   ' or whatever you want to do to debounce
      do while pushbutton = 1
      loop
      if push1 > 0 and push2 > 0 then  ' condition is satisfied--3 pushes within a minute
'[your code here--zero the counters]
      elseif push1 = 0 then            ' start counting seconds after the first push
        push1 = 1
      else
        push2 = 1                      ' start counting seconds after the second push
      endif
    endif
    pause 1000
  loop
 

moxhamj

New Member
This might be a situation where one gets too close to the code and loses sight of the big picture. I'd go back to a piece of paper. 3 keypresses in any 60 second period. Draw a line on a piece of paper. Mark it off in 60 second increments. Mark some test pulses - eg one pulse or two or 3 at random places. Put "now" on the line. The question is whether anything happened in the 60 seconds before "now".

So each pulse needs a time associated with it. You can set up a simple clock with
main:' code here
...

pause 1000' 1 second
goto main

make b13 a counter - it can have values 0, 1 or 2. Put it in a subroutine. Each time the subroutine is called add one to b13. If b13 is >2 then make it zero. b13 keeps track of the keypresses in a round robbin way.

detect a keypress. If b13 is 0 then use select case to set w0 to 60. If b13 is 1 then set w1 to 60. If it is 2 then set w2 to 60.

Every main loop once a second, subtract 1 off w0,w1 and w2. When they get to zero then make sure they don't go less than zero.

Every second, check if w0 and w1 and w2 are all >1. If they all are then three keypresses must have happened in the last 60 seconds.
 

hippy

Senior Member
It may be even simpler ... everytime the input goes high increment it, when it hits three do whatever it needs to, and every minute decrement the count if above zero.

Code:
  msCounter = 0
  pushCounter
  Do
    If input gone high then
      pushCounter = pushCounter + 1
      If pushCounter >= 3 Then
        Gosub TriggerWhatever
      End If   
    End If
    Pause 10
    msCounter = msCounter + 10
    If msCounter >= 6000 Then
      msCounter = 0
      If pushCounter > 0 Then
        pushCounter = pushCounter -1
      End If
    End If
  Loop
 

dchurch

New Member
Fantastic

lbenson,
Thank you for the code and link. I pasted the code into my program and it seems to work perfectly. Don't ask me how_ I've just been chipping away at the manual...

Honestly, I was a long way from the routine that you sent and I'm sure you save me a lot of time and frustration.

The link is very enlightening_ I’m headed back for a closer (ya, long) study of it.

Regards,
dchurch
 

dchurch

New Member
Thanks Seniors

You've given a Picaxe freshman some welcomed direction. It's very helpful to see the different avenues that will take me there.

Happy Trails,
dchurch
 

boriz

Senior Member
Another way:

60/3=20. So add 20 to a variable every time you push a button. Also subtract one from the same variable every second. If the variable gets over 60, then there is your ‘3 presses within 60 seconds’. Like a water tank with a steady leak getting a one-third refill every time you press the button.

It’s easier to work in multiples of 10 milliseconds than in seconds.

Code:
symbol tank=w1
start:
do
	pause 10
	if pin3=1 then
		tank=tank+2000
		do
		loop until pin3=0
	elseif tank>0 then
		dec tank
	endif
loop until tank>6000
'your code here
goto start
Note. Untested. May need tweaking.
 
Last edited:

hippy

Senior Member
I'm tipping my hat to Boriz; one variable and a much simpler algorithm.

The 10mS loop time helps to keep responsiveness to button pushes up. If the pause is too long then button pushes during the pause will get missed.

The code may need a slight modification for some applications to only detect rising edge of the button push or holding it down long enough will act as three pushes.

Also, very pedantically here, it may be best to decrement every 10mS not just if the button is not held to keep timing accurate; three button pushes in 6030mS will trigger the event. But, if decrementing every 10mS the counter will only hit 6000 after four pushes, so need to compare with 4000, or alter the amount each push adds.

With 'Pause 10' and ignoring the code execution time we don't have dead-on timing anyway so the effort isn't worth it unless it saves needed code space.

That's just more food for thought in pursuit of [ often un-needed ] perfection; I'd be happy to use Boriz's code in this application.
 
Top