1

I would like to do an action if both buttons on my arduino pro micro are depressed simultaneously. I'm getting some strange results:

// Buttons
Bounce button0 = Bounce();
Bounce button1 = Bounce();

void setup() {
  Serial.begin(115200);
  while (!Serial) {
    ;
  }

  pinMode(2, INPUT_PULLUP);
  button0.attach(2);
  button1.interval(1);

  pinMode(3, INPUT_PULLUP);
  button1.attach(3);
  button1.interval(1);

  Serial.println("Setup Complete");
}

void loop() {
  button0.update();
  button1.update();

  if (button0.fell()){
     Serial.println("button0 fell");
  } else if (button0.rose()) {
    Serial.println("button0 rose");
  }

  if (button1.fell()){
     Serial.println("button1 fell");
  } else if (button1.rose()) {
    Serial.println("button1 rose");
  }

  if (button0.fell() & button1.fell()){
    Serial.println("buttons fell");
  } else if (button0.rose() && button1.rose()) {
    Serial.println("buttons rose");
  }
}

Here is the output to the Serial console:

Setup Complete
button0 fell
button1 fell
button0 rose
button1 rose

Why isn't this branch being executed? button0.fell() & button1.fell() For the life of me I cannot figure this out. Thank you!

EDIT

This doesn't work either, which is crazy:

void loop() {
  button0.update();
  button1.update();

  if (button0.fell()) {
    if (button1.fell()) {
      Serial.println("buttons fell");
    }
  }

  if (button0.rose()) {
    if (button1.rose()) {
      Serial.println("buttons rose");
    }
  }
}

EDIT

Thank you for the answers! Unless the person was to push both buttons in the exact same iteration of the loop, my code would never work. Here is what I ended up using:

if ((button0.fell() && !button1.read()) || (button1.fell() && !button0.read())) {
3

You can test it easily by calling the function twice directly after each other. If the first time a true is returned and the second time a false, the state is internally reset.

But probably because after you call the fell function, the internal state is reset, so after the call not a new fell has been happened.

So store the return value of the fell and rose functions and use those instead.

Update:

I'm not sure if this is the actual implementation but I found for fell/rose and see this:

bool Bounce::rose()  
{  
    return ( state & _BV(DEBOUNCED_STATE) ) && ( state & _BV(STATE_CHANGED));  
}  

bool Bounce::fell()  
{  
    return !( state & _BV(DEBOUNCED_STATE) ) && ( state & _BV(STATE_CHANGED));  
}  

So as long as the state has not changed it returns false (which is similar/equal as 'resetting the internal state'. Except this reset is done at a different location (but checked in the fell and rose function).

Update:

See remarks from gre_gor below

|improve this answer|||||
  • The fell function doesn't reset the state. – gre_gor Nov 3 '17 at 17:28
  • @gre_gor ... it checks if the state has changed, which is functionaly similar. – Michel Keijzers Nov 3 '17 at 17:33
  • @MichelKeijzers The state is changed in update. Multiple calls to fell don't affect it. – gre_gor Nov 3 '17 at 18:26
  • @gre_gor than it's strange that storing the boolean would work. – Michel Keijzers Nov 3 '17 at 20:36
2

https://github.com/thomasfredericks/Bounce2/wiki

I'm not familiar with the Bounce(2) library, but looking at the above site, it looks like "fell" is more of an "instant" thing, where it isn't something that maintains state over the Arduino loop.

Seeing as we are human, we can't (normally) push buttons at the same exact time. This means that we would usually end up pushing the buttons within milliseconds, plural, of each other, but your simple example could loop multiple times between the first button and the 2nd button being triggered.

Don't forget that the Arduino Uno runs at 16mHz. This is extremely slow compared to today's computers, but it's still running millions of operations a second. My first computer, the IBM XT, ran at 4.77 mHz and that was the standard computer for years.

https://en.wikipedia.org/wiki/IBM_Personal_Computer_XT

I suggest putting in a loop counter to help you discover if this is the case. Trying to display it every loop may slow the loop down, so only display the counter on your current displays. If your "button0 fell {#}" display shows a different number than your "button1 fell {#}", then you know what's going on. You may also want to display the actual contents of "button{01}.fell()".

IDK if this library does it, but in app programming, sometimes getting the value of an event like this will cause the event to be flushed and reset the value. This would mean that calling a method the first time would render a different value than calling it a second time, even if the second time was immediately following the first call. Setting "button{01}.fell()" to a variable might be a better option than trying to call it twice.

|improve this answer|||||
1

I'm getting some strange results:

your code doesn't really measure the two pins "simultaneously". instead, it measure the two pins sufficiently fast and it appears to be simultaneously.

use input capture for that.

|improve this answer|||||
1

Maybe I missed something but the branch doesn't execute because

button0.fell() & button1.fell()

should be

button0.fell() && button1.fell()

the else if clause also never executes.

|improve this answer|||||

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.