Help with Button behaviour(pressed/hold released)

Hi there,

I am getting a problem with button behaviour using this button library: https://github.com/carlynorama/Arduino-Library-Button

Actually the library works really well, but it seems that my code has an issue.

My goal is: When I press and release a button the arduiono should print in serial "button pressed" When I press and hold a button, the arduino should print in serial "button hold", when I release it after that, the arduino should send the message "button released".

My current code has the problem that it sends a "button pressed" message prior to "button hold" when I hold a button pressed from the beginning.

The code works well if I just press and release the button.

Any idea how I must change my code, so that my goal above is reached? Many thanks in advance!

boolean holding = false;
button.setDebounceDelay(10);
button.setHoldDelay(500);

button.listen();

if (button.onPress()) {
    Serial.print("Button pressed");
  }

  if(!holding && button.isHold()) {
    Serial.print("Button is hold");
    holding = true;  
  }

  if(holding && button.onRelease()) {
    Serial.print("Button released");
    holding = false;
  }
}

Any idea how I must change my code

Not a clue, as you failed to post ALL of it.

What you want to do is trivial without using a library at all.

PaulS: Not a clue, as you failed to post ALL of it.

What you want to do is trivial without using a library at all.

I only posted the relevant part of the code. What is missing is the library inclusion, which should be obvious and the hardware pin assignment which can vary and is not really important for the code behaviour.

I used the library because it has debouncing feature that I have not to code from scratch again in the sketch.

Pls feel free to post your trivial code without library use. Thx.

cesarius: I only posted the relevant part of the code.

That's kind of okay but you should make it compilable! The rule is, only complete code so everybody can easily test it. You want help so you should put in the effort, not us ;)

I must confess I did not read all rules. I am sorry.

This is the code for the button part of my project(the whole sketch is too long and is really not relevant for my issue).
I compiled the code and uploaded it to my Arduino and it reproduces my problem.
As stated before it uses this library: Link

#include <Button.h> 

const unsigned int DPin = 5;

Button button = Button(DPin, HIGH);

boolean holding = false;

void setup()
{
  button.setDebounceDelay(10);
  button.setHoldDelay(700);
}

void loop()
{
button.listen();

if (button.onPress()) {
    Serial.print("Button pressed");
  }

  if(!holding && button.isHold()) {
    Serial.print("Button is hold");
    holding = true; 
  }

  if(holding && button.onRelease()) {
    Serial.print("Button released");
    holding = false;
  }
}

I preferred the library because it keeps the sketch clean. If you push and hold the button there will be a “Button pressed” message before “Button is hold”. I need to omit that “Button pressed” message if and only if the button was pressed AND hold. I hope I explained it well. I think the problem is in my algorithm not the library itself.

I suspect you just need to change the order of the IF statements.

...R

If you push and hold the button there will be a "Button pressed" message before "Button is hold". I need to omit that "Button pressed" message if and only if the button was pressed AND hold. I hope I explained it well.

You did describe what you want to do.

In order for the switch to be held, it must be pressed. The library determines that the switch has become pressed. When the switch does not become released within some time frame, the library notices that the switch is held.

Since your code is responsible for all the messages printed, you need to print them differently.

What you are doing now is asking the library if the switch has become pressed. If the library says yes, YOU print that the switch is pressed.

Then, you ask if the switch is held. If the library says yes, you print another message.

If you want different messages printed, YOU must change when you ask the library for data or when you print messages or both.

Ok I got rid of the library. I added some delay in my routine with library but that caused also a delay for the simple button presses.

Now I got a solution for it without the library and it works very good.

The task itself seems so trivial but its realisation in code needs some thinkering, at least for my dumb head.

Just for future reference if someone needs a similar code:

const unsigned int DPin = 5;


int debounceDelay = 50;
int holdDelay = 700;
int lastButtonstate = LOW;
int hold = 0;
long startTime = 0;

void setup() {
 Serial.begin(9600);
}

void loop() {

int buttonState = digitalRead(DPin);

//Initial button press timestamp

 if (buttonState == HIGH && lastButtonstate == LOW) {
   startTime = millis();
 }

//Button held

 if (buttonState == HIGH && lastButtonstate == HIGH) {
   if ((millis() - startTime) > holdDelay) {
     if (hold==0){
     Serial.println("Button is held");
     hold=1;
     }  
    }
 }

//Button released

 if (buttonState == LOW && lastButtonstate == HIGH) {
   if (((millis() - startTime) > debounceDelay) && hold != 1) {
     Serial.println("Button pressed");
   }
   if (hold == 1) {
     Serial.println("Button released");
     hold = 0;
   }  
 }
 lastButtonstate = buttonState;
}

What happend to:

cesarius:
I preferred the library because it keeps the sketch clean.

It indeed keep everything nice and clean.

Now I look at the last sketch and spot:

//Button released

 if (buttonState == LOW && lastButtonstate == HIGH) {
   if (((millis() - startTime) > debounceDelay) && hold != 1) {
     Serial.println("Button pressed");
   }

Why can you see you need to detect a “Button pressed” when you release it if you write the whole code and fail to do simply the same with a library?

#include <Button.h>

const byte DPin = 5; //byte is more then big enough ;)

Button button = Button(DPin, HIGH);

boolean holding = false;

void setup()
{
  button.setDebounceDelay(10);
  button.setHoldDelay(700);
  
  Serial.begin(115200); //You might want to start serial, otherwise still not compilable ;)
}

void loop()
{
  button.listen();

  if(!holding && button.isHold()) {
    Serial.print("Button is hold");
    holding = true;
  }

  else if(holding && button.onRelease()) {
    Serial.print("Button released");
    holding = false;
  }
  if (!holding && button.onRelease() ) {
    Serial.print("Button pressed");
  }
}

I tryied your code with library but now I get the same Issue as in my first post after releasing the button. :)

When I press and hold the button, I got the message "Button held" when I release it I get "Button released" And "Button pressed" after that.

Ok now got it finally with library :slight_smile:

#include <Button.h>

const byte DPin = 5; //byte is more then big enough ;)

Button button = Button(DPin, HIGH);

boolean holding = false;

void setup()
{
  button.setDebounceDelay(70);
  button.setHoldDelay(700);
 
  Serial.begin(115200); //You might want to start serial, otherwise still not compilable ;)
}

void loop()
{
  button.listen();

  if(!holding && button.isHold()) {
    Serial.print("Button is hold");
    holding = true;
  }
  if (!holding && button.onRelease() ) {
  Serial.print("Button pressed");
  }
  else if(holding && button.onRelease()) {
  Serial.print("Button released");
  holding = false;
  }

}

Ok now got it finally with library

Feels good, doesn't it?

Sorry, that's indeed what I meant ;) Forgot to add the else to the last part as well when I moved it around. But good to see you thought of that yourself now ;) See it as a final test :D

Thank you guys with this great help! :D