detecting 3 push of a button

Thread Starter

bug13

Joined Feb 13, 2012
2,002
Hi guys

What is the best not blocking way to detect a 3 pushes of a button. I am thinking this:

Code:
uint16_t timeArray[3];

btnThreePush()
{
  if (btnRead()) timeArray[i++] = ticksNow;
}

// main loop
while(1)
{
  diff = getDifferent(timeArray);
  if (diff > some_time)
  {
     // do something with 3 push
  }
}
Any flaws? or any better way to do it? Thanks guys
 

nsaspook

Joined Aug 27, 2009
16,326
It depends on whether it's three pushes ever or three pushes over a timed period (maybe starting with the first push).
 

Thread Starter

bug13

Joined Feb 13, 2012
2,002
How are you debouncing the button pushes?
Here is how I usually do it, these codes are usually in my timer interrupt, struct inputs is global variable
Code:
                if (!SET6_PORTbit)    // if low
                {
                    if (db < INPUT_BTN_DEBOUNCE)
                        db++;
                    else
                        inputs.set6 = 1;
                }
                else
                {
                    if (db != 0)
                        db--;
                    else
                        inputs.set6 = 0;
                }
 

nsaspook

Joined Aug 27, 2009
16,326
I might put the three button decision logic in btnThreePush() instead of the while loop (diff = ...) if possible as it wastes cpu cycles computing an event (3 presses timed or not) that can be detected and flagged with a variable or status check function for the while loop when the button is pressed in btnThreePush().
 

xainnasir

Joined Nov 8, 2012
15
you need to use button debounce code. Code is as follows for single click check so you have to repeat it for three times:

Code:
int reading = digitalRead(buttonPin);
  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != buttonState) {
      buttonState = reading;

      if (buttonState == HIGH) {
        ledState = !ledState;
      }
    }
  }
 

Thread Starter

bug13

Joined Feb 13, 2012
2,002
you need to use button debounce code. Code is as follows for single click check so you have to repeat it for three times:

Code:
int reading = digitalRead(buttonPin);
  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != buttonState) {
      buttonState = reading;

      if (buttonState == HIGH) {
        ledState = !ledState;
      }
    }
  }
Sorry for the confusion, my btnRead() is already deal with debounce.
 

Thread Starter

bug13

Joined Feb 13, 2012
2,002
You cannot use a function that is executed in your code that you don't want to block.

Use code executed by interrupts.

This thread deals with using interrupts to debounce a button press and differentiate between a short or long press It can be generalized for detecting multiple presses.
http://forum.allaboutcircuits.com/blog/two-state-debounced-pushbutton.730/
that's the same principle in my code in post #5, but pic doesn't usually have as many IO interrupt AVR, so I did my scan in a timer interrupt.
 

ErnieM

Joined Apr 24, 2011
8,415
Sorry for the confusion, my btnRead() is already deal with debounce.
OK, but how does it denounce? My debounce code is tucked away in a timer interrupt that fires every 25 ms and can detect stale button presses.

To get three pulses out of this I would look at a scheme such as this: on the first valid push I would set a count variable to 1 and also start a timing variable. On subsequent checks of the button for denounce I would check the timing variable; should it exceed 1 second I reset the count variable, and if it also detects another button push then increment the count variable. You may want to also reset the timing variable too so your main code has enough time (another second?) to detect a count of three.

This way the same way you read buttons you can also check for a count of the pressings.
 
Last edited:

dannyf

Joined Sep 13, 2015
2,197
Sorry for the confusion, my btnRead() is already deal with debounce.
that's the right approach (to put debouncing in the lower level routines).

I would use a state machine to detect key presses. For example, you receive consecutive NO_KEYPRESS from your lower level routine, you consider a key press has been terminated.

Otherwise, if you receive KEY_PRESSED three times, you consider that to be a valid 3-press instance.
 
Top