Switch debouncing with bounce2

Hello,
I am learning the arduino language from a book by Simon Monk. I have installed the bounce2 library and tested his code show below and it works.

//bounce program using the bounce2 library

#include <Bounce2.h>

const int inputPin = 5;
const int ledPin = 13;

int ledValue = LOW;
Bounce bouncer = Bounce();

void setup()
{
pinMode (inputPin, INPUT_PULLUP);
pinMode (ledPin, OUTPUT);
bouncer.attach (inputPin);
}

void loop()
{
  if (bouncer.update() && bouncer.read() == LOW)
  {
    ledValue = ! ledValue;
    digitalWrite (ledPin, ledValue);
  }

However, in the examples which come with the bounce library is the following code

/*
  DESCRIPTION
  ====================
  Simple example of the Bounce library that switches a LED when
  a state change (from HIGH to LOW) is triggered (for example when a button is pressed).

  Set BOUNCE_PIN to the pin attached to the input (a button for example).
  Set LED_PIN to the pin attached to a LED.

*/

// WE WILL attach() THE Bounce INSTANCE TO THE FOLLOWING PIN IN setup()
#define BOUNCE_PIN 2

// DEFINE THE PIN FOR THE LED :
// 1) SOME BOARDS HAVE A DEFAULT LED (LED_BUILTIN)
#define LED_PIN LED_BUILTIN
// 2) OTHERWISE SET YOUR OWN PIN
// #define LED_PIN 13

// Include the Bounce2 library found here :
// https://github.com/thomasfredericks/Bounce2
#include <Bounce2.h>


// INSTANTIATE A Bounce OBJECT
Bounce bounce = Bounce();

// SET A VARIABLE TO STORE THE LED STATE
int ledState = LOW;

void setup() {

  // BOUNCE SETUP

  // SELECT ONE OF THE FOLLOWING :
  // 1) IF YOUR INPUT HAS AN INTERNAL PULL-UP
  bounce.attach( BOUNCE_PIN ,  INPUT_PULLUP ); // USE INTERNAL PULL-UP
  // 2) IF YOUR INPUT USES AN EXTERNAL PULL-UP
  //bounce.attach( BOUNCE_PIN, INPUT ); // USE EXTERNAL PULL-UP

  // DEBOUNCE INTERVAL IN MILLISECONDS
  bounce.interval(5); // interval in ms

  // LED SETUP
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, ledState);

}

void loop() {
  // Update the Bounce instance (YOU MUST DO THIS EVERY LOOP)
  bounce.update();

  // <Bounce>.changed() RETURNS true IF THE STATE CHANGED (FROM HIGH TO LOW OR LOW TO HIGH)
  if ( bounce.changed() ) {
    // THE STATE OF THE INPUT CHANGED
    // GET THE STATE
    int deboucedInput = bounce.read();
    // IF THE CHANGED VALUE IS LOW
    if ( deboucedInput == LOW ) {
      ledState = !ledState; // SET ledState TO THE OPPOSITE OF ledState
      digitalWrite(LED_PIN,ledState); // WRITE THE NEW ledState
    }
  }
}

Which uses an interval timer which I understand is not the same as using delay which I want to avoid. My main question is this, in the first program which does not appear to use interval, why so? is a default interval value used instead whenever it is not specified?
Also any thoughts on what is better for debouncing, using bounce2 library or the millis function methods.

many thanks if anyone know the answer.

Yes.

In the source code of the library we see, I think, a default setting of 10 milliseconds.

Debouncer::Debouncer():previous_millis(0)
    , interval_millis(10)
    , state(0) {}

When you compile your sketch, every line of all the code that goes into it is on your machine somewhere.

Or you can google your way to the source code on the web, many are hosted on github.

It may be waaaay over your head, but I encourage you to read read read code like you understand it, raise questions for youself and learn bit by byte.

No good writer of anything written is not also widely read.

a7

Suggest you simply scan your switches every 20 to 50ms.

This will de-bounce your switches nicely without the need of using a library.

2 Likes

They both have their places, and Bounce2 uses millis() methods behind the scenes.

Learning how to use millis() for timing is an important skill to gain, but once you have that, using Bounce2 to simplify your code or because you are feeling "lazy" is not a problem to worry about. The .rose() and .fell() methods are useful.

Bounce2 is a very solid library and I frequently use it.

+1 for @alto777 recommendation to get into the habit of reading library source code.

1 Like

In general, using Libarys is like cooking with instant soups. A soup comes out of the pot, but if the soup doesn't taste good, you don't know why it doesn't taste good.

2 Likes

I use

find . -iname "*.cpp" | xargs grep -s -i -l findThis

or even "*.*".

Gotta use all that power somehow.

And MacOS.

a7

When using Windows I prefer the more civilised approach of Agent Ransack

Thanks for all the replies, you certainly cleared it up for me.

I have started using an anti-anti-delay() debounce that will have me banned works for me

  1. define a button on an interrupt pin
  2. define an interrupt service routine that sets a flag on the interrupt
  3. if the flag is set (not a pressed button) use delay(x) to debounce residual button-press oscillations.

These steps allow a button to be pressed during blocking code (for(), while(), do()) without being lost to polling, as long as interrupts are not turned off. Once the blocking code is finished, the button-press will be acted upon. Like this:

volatile bool buttonFlag; // type volatile for interrupt handler
int buttonPin = 2; // interrupt pin INT0
.
.
void setup() {
.
.
  attachInterrupt(digitalPinToInterrupt(buttonPin), buttonISR, FALLING); // INT#, ISR, TRIGGER
.
.
}

void loop() {
.
.
  if (buttonFlag) { // button flag is returned from ISR
    delay(150); // debounce
    buttonFlag = 0; // reset ISR flag
.
.
}

int buttonISR() {
  noInterrupts(); // disable interrupts while in the ISR
  buttonFlag = 1; // set a flag indicating the button was pressed
  interrupts(); // enable interrupts when leaving the ISR
}

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