Code help - push button

Hello everyone, I have a problem with the code.
Every time I press the button, the if works twice.
I want to press the button and what happens inside the if will be only once.
It is important to me that there is a delay within the if because the original code is longer and it runs an array of motors.
Attaches the two codes here

Thanks for the helpers

#include <ezButton.h>

ezButton limitSwitch(7);  // create ezButton object that attach to pin 7;

void setup() {
  Serial.begin(9600);
  limitSwitch.setDebounceTime(50); // set debounce time to 50 milliseconds
}

void loop() {
  limitSwitch.loop(); // MUST call the loop() function first
  if(limitSwitch.isPressed())
  {
    Serial.println("A");
    delay(500);
  }
  if(limitSwitch.isReleased())
  {
    Serial.println("B");
  }

}

Something like this perhaps?

void loop() {
  limitSwitch.loop();

  static bool pressed = false;
  if (limitSwitch.isPressed() && !pressed)  {
    pressed = true;
    Serial.println("A");
    delay(500);
  }
  if (limitSwitch.isReleased())  {
    pressed = false;
    Serial.println("B");
  }
}

Because it will?
Unless the library detect rising edges and falling edges the if loop will execute until you release the button

Some switch libraries that use a loop call to pay attention to a button do not do well if attention is not paid regularly.

Remove the delay() calls. If the library is functioning the way one might infer from the function names, you don't need the delays anyway.

There should be no need to introduce any tracking variable, that's the job and indeed the whole point of using a library.

Check the ezButton library for a function that shows when the button goes down, if the one you are using now isn't exactly the right one already.

Added: OK, I tested this and you can def lose the delay() and it will work perfectly. on an UNO anyway.

a7

I think that you would be better off without the library. Just use the state change example to detect a rising edge.

It appears that the problem is the debounce time. When you press the button, once the debounce time is up, the press is registered, you print "A", wait a bit and by the end of the delay you have released the button.

The next time around loop, the library notices that the button was released so it sets the debounce timer again. It needs 50mS to be sure that the state is stable, but microseconds later, you check again to see if the button is pressed. The library is still waiting for the debounce time to elapse, so it hasn't changed any of it's local variables that are used to figure out pressed or released. In consequence, even though it knows that the button was released, it is not ready to say so and it returns pressed a second time.

2 Likes

You'll have to figure out a way to pay better attention to the button if you use exButton.

You could just do your own button handling, it is not hard or, better, figure out a way to do the thing you are using delay() as a proxy for in your tests without killing your loop frequency.

It would be better for the future development and enhancements you will no doubt be getting to.

a7

consider - it's that simple

const byte SwPin = A1;
byte swState;

void loop() {
    byte sw = digitalRead (SwPin);

    if (swState != sw)  {
        swState = sw;
        delay (10);     // debounce

        if (LOW == sw)
            Serial.println("A");
    }
}

void setup () {
    Serial.begin (9600);
    pinMode (SwPin, INPUT_PULLUP);
    swState = digitalRead (SwPin);
}

Yes, thank you very much you helped me a lot

A good tutorial to know what's going on and many ways to handle it.
Nick Gammon on knowing switches, etc.

That solution is a patch to the limitations of the library. Sooner later you will have more trouble, and more patches like this.

ezButton reports edges, so the additional variable is just making up for your failure to use the library as it is coded.

There is no need for a library here, and no need to use delay(). This below sets flags on the edges, and it is up to you to handle those facts and clear the flags when you have done as deomonstrated. It will provide the fastest possible response, and the minimum use of time.

# define limitSwitch 7

void setup() {
  Serial.begin(115200);
  Serial.println("hello world!\n");

  pinMode(limitSwitch, INPUT_PULLUP);
}

void loop() {
  unsigned long now = millis();

  static unsigned long lastCheck;
  static bool lastState = true;		// normall HIGH
  static bool gotPressed = false, gotReleased = false;

  if (now - lastCheck > 25) {
    lastCheck = now;
    bool state = digitalRead(limitSwitch);

    if (state != lastState) {
      lastState = state;

      if (state) gotPressed = true;			// clear when you handle this fact
      else gotReleased = true;				// clear when you handle this fact
    }
  }

  if (gotPressed)  {
    Serial.println("Saw it go down!");

    // whatever... any time consumption = sluggish button
    delay(500);

    gotPressed = false;		// handled that
  }

  if (gotReleased)  {
    Serial.println("Saw it go up!");

    // whatever...
    delay(500);

    gotReleased = false;		// handled that
  }
}

Another good one to curl up with in front of the fireplace is

a7

No problem, but as some people here already pointed out, there are cleaner ways of dealing with this in this particular case.

At first glance, the ezButton library does not seem to have edge detecting capability, but upon closer inspection, the count functions seem to do the trick. You could have a look at the setCountMode() example in the documentation.

Using no library is an educational exercise which I can recommend, but wrappers like ezButton will make working with multiple buttons (e.g., an array of buttons) easier and cleaner in my opinion.

My debounce reads the pin every 500 micros and updates a history byte with the last 8 reads in the bits. New read is in bit 0, oldest in bit 7. Bit order is 76543210.

Numbers to look for:

0b00000000 = 0 is button is held down
0b10000000 = 128 is button just pressed
0b01111111 = 127 is button just released
0b11111111 = 255 is button held down

everything else is unstable.

reading twice a ms , it takes 3.5 ms of stable to "prove it"

//Update pin history:
history = history << 1;  // shifts all bits left 1, new bit 0 == 0
history += digitalRead( buttonPin );  // new bit 0 now == pin state

// elsewhere
if ( history == 128 ) // if button just pressed, transition as opposed to state
{

Every button needs 4 bytes. All buttons use the same unsigned interval.
1 byte for pin number
1 btye for history
1 unsigned for time start, timer = micros() gets the low 16 bits, good for 65.535 ms.

arduino-library-badge

Also toggles the built-in LED ... (documentation)

#include <Toggle.h>

const byte swPin = 7;
const byte ledPin = LED_BUILTIN;

Toggle sw1(swPin);

void setup() {
  while (!Serial) { }; // Leonardo
  Serial.begin(9600);
  sw1.begin(swPin);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  sw1.poll();
  if (sw1.onPress()) Serial.println(F("A"));
  if (sw1.onRelease()) Serial.println(F("B"));
  digitalWrite(ledPin, sw1.toggle());
}

LOL! My previous method is more overkill, more noise-sensitive and cycle-hogging!
Reading once or twice a milli instead or 40 to 60 times possible is NOT overkill!

But pray tell please, how this debounce is not suited to buttons on Arduino?

This one is tight so it can be used for multi and matrix buttons with less overhead.

This one might be fast enough to debounce limit switches, my old one is. Buttons and switches are not just for finger presses that "debounce by ignoring 20 to 50ms" "is good enough for slow people".

I picked 500 usec reads to set a good stable period to mark transition. 3.5ms same state.

0b10000000
0b01111111

It makes knowing button state one byte-byte compare.

If you want to give your Opinion then at least back it up with facts.

Thank you so much everyone

Clever method! I hadn't thought of it. I'll keep it in mind for the day when I can use it!

(How do I indicate at the beginning of my message that I am replying to GoForSmoke=?
Edit : ah ! now there is the indication...how did I do it ?

switch_tutorial5
From Nick Gammons' blog on switches, etc.

In the debounce before I kept current pin state in bit 0 and previous state in bit 1, saving 1 byte over having prev and curr vars to detect state changes.

Then I looked at what 8 bits of history could indicate and it works over a wide range of read speeds. The outcome is either bouncing or 1 of 4 meaningful states possible.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.