1
\$\begingroup\$

On my arduino project i have 8 buttons connected to a 4051 Multiplexer. I would however like to add single and double click funcionalities to each of these buttons, but i can't find a way to do it.

My code for the buttons at the moment looks like this:

for (int buttonCount = 0; buttonCount < 8; buttonCount++){
b0 = bitRead(buttonCount,0);
b1 = bitRead(buttonCount,1);
b2 = bitRead(buttonCount,2);

digitalWrite(10,b0);
digitalWrite(9,b1);
digitalWrite(8,b2);

buttonValue[buttonCount] = digitalRead(buttonPin);

if (buttonValue[buttonCount] == CLICK_SINGLECLICK && buttonValue[buttonCount] != lastButtonValue[buttonCount]) {
  Serial.println(buttonCount);
}

Any help would be greatly appreciated!

\$\endgroup\$
1
\$\begingroup\$

In am not familiar with Arduino and the libraries but it doesn't really depend on that anyway.

You will at least require a timer of some sort that runs in the background. This timer "expires" after the desired double-click speed (time between two clicks). The timer is reset after each button press.

Then perform some checks like this (pseudo-code):

...
if (buttonHasBeenPressed) {
    if (timerIsExpired || (currentButton != previousButton)) {
        Print("Button has been clicked");
    } else {
        Print("Button has been DOUBLE clicked");             
    }

    ResetTimer(); 
}
...

This is a quick shot, but should give you an idea how to approach it.

EDIT: I just realized in this solution, a double click will always be preceded by a single click. This is probably not what you desire, so you have to actually do some additional checks.

\$\endgroup\$
  • \$\begingroup\$ thanks, that is actually very close to something i tried yesterday. But then i had trouble because i always got SINGLE CLICK + DOUBLE CLICK. I thought about waiting until the end of "timerIsExpired" (from you example) to send the single click message, but that wouldn't be very precise for the SINGLE CLICK. there would always be some kind of "gap" between the single click and the actual message... \$\endgroup\$ – LuisBento Jun 20 '13 at 9:43
  • \$\begingroup\$ @LuisBento: Yes, that kind of gap is to be expected. What kind of delay are you aiming for? Something around 100ms should be a compromise between being able to double click that fast and not have to wait too long for a single click reaction. \$\endgroup\$ – Rev1.0 Jun 20 '13 at 9:57
  • 1
    \$\begingroup\$ Actually, near as I can tell on my desktop, a single-click action does precede the double click action, and I think, by design, the single click action is not harmful. \$\endgroup\$ – Scott Seidman Aug 20 '13 at 21:16
0
\$\begingroup\$

This is some untested code that may give you some ideas. Given that you'll probably want some debouncing even for a single press the approach is to keep shifting eight readings through a byte so that you have a record of the last 8 readings. Then where the MSB is set it counts the number the number of times in those samples that 2-4 ones occur in a row and treats them as a click, two such occurrences are treated as a double-click.

You may need to play around with the sample rate and those numbers to suit your input device, and as mentioned it's untested but it may give you an idea on a way to go about it.

int readButton(int button) {
    b0 = bitRead(button,0);
    b1 = bitRead(button,1);
    b2 = bitRead(button,2);

    digitalWrite(10,b0);
    digitalWrite(9,b1);
    digitalWrite(8,b2);

    if (digitalRead(buttonPin) == HIGH)
        return 1;
    else
        return 0;
}

// Perform following in timer or at a fixed interval
// Keep a list of the last 8 button states, LSB is most recent

for (int buttonCount = 0; buttonCount < 8; buttonCount++) {
   buttonValue[buttonCount] <<= 1;
   buttonValue[buttonCount] |= readButton(buttonCount);

   if (buttonValue[buttonCount] & 0x80) {
       int onCount = 0, clickCount = 0;
       for (int bitPos = 0; bitPos < 8; bitPos++) {
           if (buttonValue[buttonCount] << bitPos & 1)
              onCount++;
           else {
               // Treat 2-4 readings in a row as a click
               if ((onCount >= 2) && (onCount <= 4))
                 clickCount++;
              onCount = 0;
           }
       }  
       if (clickCount > 0)
       {
           if (clickCount == 1)
             singleClick(buttonCount);
           else
             doubleClick(buttonCount);
           buttonValue[buttonCount] = 0;
       }
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.