How to register simultanious button press

Hi Guys,

I have a question I can’t seem to work out and not find a good example code for. There are 4 buttons and I would like to register if button 1 & 2 are pressed simultaniously. I can register the doubleclick. What I can not manage is to then bypass the single click functionality.

Probably something very obvious but how can I manage this?

#include <Arduino.h>
int nbts = 4;
int startpin = 14;
int bts[4];
boolean btgs[4];
boolean doubleClick = false;

void setup (){
  Serial.begin(9600);
  for (int i=0; i<nbts; i++) bts[i] = i+startpin;      // set the pin for the buttons
  for (int i=0; i<nbts; i++) btgs[i] = false;          // set booleans to false
  for (int i=0; i<nbts; i++) pinMode(bts[i], INPUT_PULLUP);   // pins to input_pullup
}
void loop () {
    for (int i=0; i<nbts; i++) {

      /////////////////// DOUBLE CLICK CODE /////////////////////////////
      if (!doubleClick) {
        if (digitalRead(bts[0])==LOW && digitalRead(bts[1])==LOW) {
          Serial.println("doubleclick");
          doubleClick = true;
        }
      }
      else {
        if (digitalRead(bts[0])==HIGH && digitalRead(bts[1])==HIGH) {
          Serial.println("doublerelease");
          doubleClick = false;
        }
      }


      /////////////////// SINGLE CLICK CODE /////////////////////////////
      if (!btgs[i]) {
        if (digitalRead(bts[i])==LOW) {
          Serial.println("bt" + String(i) + " pressed");
          btgs[i] = true;
        }
      }
      else {
        if (digitalRead(bts[i])==HIGH) {
          Serial.println("bt" + String(i) + " released");
          btgs[i] = false;
        }
      }
    }
    delay(15);
}
  for (int i=0; i<nbts; i++) bts[i] = i+startpin;      // set the pin for the buttons
  for (int i=0; i<nbts; i++) btgs[i] = false;          // set booleans to false
  for (int i=0; i<nbts; i++) pinMode(bts[i], INPUT_PULLUP);   // pins to input_pullup

Why do you need 3 for loops?
Why do you need 3 for loops?
Why do you need 3 for loops?

    for (int i=0; i<nbts; i++) {

      /////////////////// DOUBLE CLICK CODE /////////////////////////////
      if (!doubleClick) {
        if (digitalRead(bts[0])==LOW && digitalRead(bts[1])==LOW) {
          Serial.println("doubleclick");
          doubleClick = true;
        }

Why do you iterate 4 times, processing the same two pins?

Probably something very obvious but how can I manage this?

First, you need to understand that nothing happens simultaneously on the Arduino. It is impossible to press two switches at the same time.

It is possible to press one switch, and then, while that switch is pressed, press another one.

So, the first thing you need to do is properly define your requirements.

Ok, thanks…
I got rid of the loops and iterations but the case remains… I should probably have something like:

  • first button is pressed
  • do nothing for a bit while checking if another button is pressed
  • if no other button is pressed → do task for pressed button
  • another button is pressed → do task for double press

but I still don’t know how to go about this…

#include <Arduino.h>

int nbts = 4;
int startpin = 14;
int bts[4];
boolean btgs[4];
boolean doubleClick = false;

void setup (){
  Serial.begin(9600);
  for (int i=0; i<nbts; i++) {
    bts[i] = i+startpin;             // set the pin for the buttons
    btgs[i] = false;                 // set booleans to false
    pinMode(bts[i], INPUT_PULLUP);   // set pins to input_pullup
  }
}

void loop () {
    
  /////////////////// DOUBLE CLICK CODE /////////////////////////////
  if (digitalRead(bts[0])==LOW && digitalRead(bts[1])==LOW && !doubleClick) {
    Serial.println("doubleclick");
    doubleClick = true;
    return;
  }
  else if (digitalRead(bts[0])==HIGH && digitalRead(bts[1])==HIGH && doubleClick) {
    Serial.println("doublerelease");
    doubleClick = false;
    return;
  }
    
  /////////////////// SINGLE CLICK CODE /////////////////////////////
  for (int i=0; i<nbts; i++) {
    if (!btgs[i] && !doubleClick) {
      if (digitalRead(bts[i])==LOW) {
        Serial.println("bt" + String(i) + " pressed");
        btgs[i] = true;
      }
    }
    else {
      if (digitalRead(bts[i])==HIGH && !doubleClick) {
        Serial.println("bt" + String(i) + " released");
        btgs[i] = false;
      }
    }
  }
  delay(15);
}

but I still don't know how to go about this....

List the steps YOU would follow, using a watch, a pencil, and a pad of paper.

Making the Arduino do something that you can not describe well is going to be extremely difficult.

You MUST stop using phrases like "for a bit". That either means "for a random amount if time" OR "for I really don't know how long". Dealing with each case is going to be VERY different.

The state change detection example bears looking at.

Try the below code, not tested.

#include <Arduino.h>

int nbts = 4;
int startpin = 14;
int bts[4];
boolean btgs[4];
boolean doubleClick = false;
const int WAIT_TIME = 1000;
int lastClicked = 0;

void setup () {
  Serial.begin(9600);
  for (int i = 0; i < nbts; i++) {
    bts[i] = i + startpin;           // set the pin for the buttons
    btgs[i] = false;                 // set booleans to false
    pinMode(bts[i], INPUT_PULLUP);   // set pins to input_pullup
  }
}


void loop() {
  if (digitalRead(bts[0]) == HIGH) {
    lastClicked = millis();
    doubleClick = false;
  }

  if (digitalRead(bts[1]) == HIGH) {
    if (millis() - lastClicked <= WAIT_TIME) {
      doubleClick = true;
    }
  }

  if (millis() - lastClicked > WAIT_TIME && doubleClick == false)
    Serial.println("Single click");
  else if (doubleClick == true)
    Serial.println("Double Click");

  if (digitalRead(bts[0]) == LOW || digitalRead(bts[1]) == LOW) {
    doubleClick = false;
    lastClicked =0;
  }
}

Some comments.
I always feel difficulty understanding condition checks like

if (!doubleClick)

instead, it will be more readable if you could write

if (doubleClick==false)

may be the difficulty only for me :slight_smile:

may be the difficulty only for me

It is. I prefer to NOT see == true or == false in an if test.

PaulS: It is. I prefer to NOT see == true or == false in an if test.

:) so thats confirmed, it's only for me

Ok, thanks guys,

you put me on the right track with the wait time. Got it working now. Probably by far not the cleanest code but I’m gonna put some time into cleaning it up. Especially the somewhat clumsy delay at the end to get rid of the functionality for the last released button.

Here’s what’s working now:

#include <Arduino.h>

int nbts = 4;
int startpin = 14;
int bts[4];
boolean btgs[4];
boolean doubleClick = false;
boolean timer = false;
const int WAIT_TIME = 150;
int lastClicked = 0;

void setup () {
  Serial.begin(9600);
  for (int i = 0; i < nbts; i++) {
    bts[i] = i + startpin;           // set the pin for the buttons
    btgs[i] = false;                 // set booleans to false
    pinMode(bts[i], INPUT_PULLUP);   // set pins to input_pullup
  }
}


void loop() {
   
for (int i=0; i<nbts; i++) {
    if (digitalRead(bts[i]) == LOW) {       // if a button is pressed
      if (!timer) {                         // and if the timer is not running
        btgs[i] = true;                     // set buttonpress to on
        lastClicked = millis();             // set click time
        timer = true;                       // zet timer to on
      }
    }
  
    if (digitalRead(bts[0]) == LOW && digitalRead(bts[1]) == LOW) {     // if button 0 and 1 are pressed at the same time
      if (millis() - lastClicked <= WAIT_TIME) {                        // and it is done within the waiting time
        doubleClick = true;                                             // set double click to true
        btgs[i] = false;                                                // turn the pressed buttons off again
      }
    }
  
    if (millis() - lastClicked > WAIT_TIME && !doubleClick){            // if the waiting time is over and there is no doubleclick
      if (btgs[i])  {                                                   // and if a buttonpress is set to on
        if (digitalRead(bts[i])==HIGH) {                                //  and if the button is released again
          btgs[i] = false;                                              // turn buttonpress off
          timer = false;                                                // set timer to off
          Serial.println("bt" + String(i) + " released");               // print released button of do whatever is wanted here
        }
      }
    }
    if (digitalRead(bts[0]) == HIGH || digitalRead(bts[1]) == HIGH) {   // if button 0 or 1 is released 
      if (doubleClick) {                                                // and there is a double click
        doubleClick = false;                                            // set double click to false
        Serial.println("Double Click released");                        // print doubleclick released
        lastClicked =0;                                                 // stop the timer
        timer = false;                                                  // set timer to off
        btgs[i] = false;                                                // turn buttonpress off
      }
    }
  }
  delay (100);                                                           // delay to get rid of press for the last released button
 }