# Q. Respond to 3 within any 60 sec. period

#### dchurch

##### New Member
New-B
Using 8M or 14M

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
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
goto start``````
Note. Untested. May need tweaking.

Last edited:

#### moxhamj

##### New Member
Hippy and boriz - your code is genius. Occam's razor at work.

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