alextaujenis / RBD_Button

Arduino Button Library - Read and debounce buttons and switches without delay or interrupts.
https://robotsbigdata.com/docs-arduino-button.html
MIT License
32 stars 9 forks source link

button.onReleased() is true before the button is ever pressed #14

Open mshulman opened 2 years ago

mshulman commented 2 years ago

This is strange. In the example program, button.onReleased() is only called after the button is pressed.

But in my sketch, button.onReleased() is true the first time through my loop(), before the button has been pressed.

I'm using an Adafruit m0 board, and pin 11 is a standard GPIO pin (docs)

#include <RBD_Timer.h>  // https://github.com/alextaujenis/RBD_Timer
#include <RBD_Button.h> // https://github.com/alextaujenis/RBD_Button
#include <stdio.h>

// input pullup enabled by default
RBD::Button button(11);

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
}

void loop() {  
  if(button.onPressed()) {
    Serial.println("Button Pressed");
  }

  if(button.onReleased()) {
    Serial.println("Button Released");
  }
}
alextaujenis commented 2 years ago

This could be any number of problems:

  1. The wires are loose or crossed to your button.
  2. Your button is faulty. Try a different one.
  3. Your button is on by default, and you press it to turn it off.
  4. You might need to increase your debounce time.

I’d check all of these things. Let me know if you find the problem or if your are still stuck.

mshulman commented 2 years ago

Alex, your sample works fine, but mine doesn't.

I wonder if there's something special about GPIO 11 on my board?

alextaujenis commented 2 years ago

Sorry about closing this issue, that was an accidental click. Try changing pins, or buttons, or rewiring it. Do you have a different Arduino board to test the button?

mshulman commented 2 years ago

When I start with your example sketch, and change the pin to 11, it works. When I take my own sketch, and remove everything else, it doesn't work.

The only difference I see from your sample is the #include <stdio.h>, and that my serial port is at 9600 and yours was 115k. So strange.

Your .cpp file looks fine too.

I solved it with a flag that gets set to true the first time the button is pressed, but that's messy in my own code. Maybe we just need to add that state flag to the library?

Have you heard of this issue from anyone else?

alextaujenis commented 2 years ago

Do you need to include stdio.h? If you take that out does the the button behave properly?

mshulman commented 2 years ago

It still happens if I don't include #stdio.h

fishdaa commented 2 years ago

I also encountered this on esp8266 and esp32, but works fine on uno

peter58228 commented 1 year ago

I have same issue on Arduino IDE + RP2040: You can remove this line: btn[i].onReleased(); //!!!!!!<-Remove onReleased() default: true!!!!!! after that, you can see all button's onReleased value is true by default. (PS. No any wire connected on dev board)

#include <RBD_Timer.h>
#include <RBD_Button.h>

RBD::Button btn[16] = {
  RBD::Button(0),
  RBD::Button(1),
  RBD::Button(2),
  RBD::Button(3),
  RBD::Button(4),
  RBD::Button(5),
  RBD::Button(6),
  RBD::Button(7),
  RBD::Button(8),
  RBD::Button(9),
  RBD::Button(10),
  RBD::Button(11),
  RBD::Button(12),
  RBD::Button(13),
  RBD::Button(14),
  RBD::Button(15)
};

unsigned short onPressed;
unsigned short onReleased;
unsigned short isPressed;

void setup() {
  Serial.begin(115200);

  onPressed = 0b0;
  onReleased = 0b0;
  isPressed = 0b0;

  for (int i = 0; i < 16; i++) {
    btn[i].onPressed();
    btn[i].onReleased();  //!!!!!!<-Remove onReleased() default: true!!!!!!
  }

  Serial.print("onPressed: ");
  Serial.println(onPressed);
  Serial.print("onReleased: ");
  Serial.println(onReleased);
  delay(5000);
}

void loop() {
  unsigned short onPressedUpdate = 0b0;
  unsigned short onReleasedUpdate = 0b0;

  for (int i = 0; i < 16; i++) {
    if (btn[i].onPressed()) {
      bitSet(onPressedUpdate, i);
    }
    if (btn[i].onReleased()) {
      bitSet(onReleasedUpdate, i);
    }
  }

  onPressed |= onPressedUpdate;
  onReleased |= onReleasedUpdate;

  Serial.print("onPressed: ");
  for (int i = 0; i < 16; i++) {
    Serial.print(bitRead(onPressed, 15 - i));
  }
  Serial.println("");
  Serial.print("onReleased: ");
  for (int i = 0; i < 16; i++) {
    Serial.print(bitRead(onReleased, 15 - i));
  }

  delay(3000);
}
alextaujenis commented 1 year ago

@peter58228 There are a few things going on here...

1) Don't use delay() in your loop. You need to keep the event loop running for the RBD libraries to behave correctly. Your sketch here only executes the event loop once every three seconds, this code won't identify button presses correctly.

2) The for loop in the setup doesn't store any values or perform any actions besides executing the .onPressed() and .onReleased() functions across all buttons stored in your button array. Nothing is happening here. Why is this code significant?

3) This library initializes all variables as false by default, and the xxPressed() functions return false unless the registered button pin is HIGH. This is extensively backed by unit tests for this library (look in extras/unit_test in this library to see the tests). Buttons do not initialize as pressed, period.

In summary; your code won't register button events because you use delay() in your loop(): Remove delay() from your sketch.

Also, there are several other reasons why your code might not work as intended. You could have wiring issues or a faulty Arduino board... or you most likely have normally closed buttons. They are "pressed" by default and when you push the button it opens the circuit. If this is the case you should run this code once in your setup() to invert all button readings instead:

void setup() {
  for (int i = 0; i < 16; i++) {
    btn[i].invertReading();
  }
}

Let me know if you are still having issues after adjusting your code. Others have reported this issue and I still think there might be hardware or library compatibility issues across all of the different flavors of Arduino development.