Bounce2: debouncing buttons and switches on Arduino
Debouncing library for Arduino and Wiring
At a glance
- What is it?
- Bounce2 is a small C++ library for Arduino and Wiring that filters the mechanical chatter of a button or switch, exposing a pressed and released event instead of a flickering pin. It suits anyone wiring a physical control to a microcontroller, and it is the wrong choice for a library that needs interrupt-driven or hardware-timed debouncing.
- Who is it for?
- Bounce2 fits a hobby project or a prototype with a physical button whose chatter would otherwise trigger an action several times, since the library is small, MIT licensed and the pressed and released semantics are exactly what a simple input device needs. It is the wrong choice if you need microsecond timing, if your control loop runs infrequently, or if you want interrupt-driven detection, because the whole design is polling based.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 95 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why a button reports five presses when you pressed it once
Bounce2 is a debouncing library for Arduino and Wiring, and the problem it solves is described in the first line of the readme. The mechanical part of buttons and switches vibrates slightly when closed or opened, causing multiple undesired false states, described as noise. The library filters out these undesired state changes.
The readme links two references on the subject, one on switch bounce and solutions to it from an Arduino experimentation site and the Wikipedia article on contact debouncing, which is the appropriate level of background for a library this small.
So the audience is narrow and well defined. Anyone who has wired a button to a microcontroller and found that one press triggered a menu item three times knows the problem, and the fix is a library that decides what counts as a press.
The project is by Thomas Ouellet Fredericks and many contributors, MIT licensed, with the primary language C++. The homepage is not given separately, and the repository carries an extras/ folder, a library.json and a library.properties file, which are the manifests the Arduino tooling uses to find and install the library.
One historical note is in the readme and worth repeating, because it explains a naming choice that otherwise looks like a mistake. The original version of the library, Bounce 1, is included in the extras folder of the download but is no longer supported.
Three classes, and which one you should actually use
The library is composed of three classes, and the readme is clear about the intended audience for each.
Bounce2::Button is the class most people will use, and it is described as the most feature rich class for debouncing hardware buttons. Debouncer is the code that does the actual debouncing, and only advanced users should use it for creating their own implementations. Bounce links the Debouncer class to a hardware pin on the board. The odd naming of Bounce ensures backward compatibility with previous versions of the library, which is the sort of decision that looks like an accident and is actually a deliberate migration path.
The inheritance chain follows that order. The documentation confirms it: Bounce2::Button extends Bounce and adds pressed() and released() methods, and Bounce extends Debouncer and links it to a hardware pin.
So there are two layers of extension available. The common case is Button, which is a pin plus event semantics. The advanced case is writing your own class on top of Debouncer, which is what you would do if you needed to debounce something that is not a pin, or wanted different timing behaviour.
The Bounce class is described in the documentation as oddly named but kept that way for compatibility with previous code, which is a small thing that tells you something about how the project has been maintained: renaming would have broken every sketch that included it.
Attaching a button, and the three settings you have to get right
Using the library takes a few lines in setup() and a call in loop(), and the readme walks through the three settings that matter.
First, the pin and its mode. Change PIN to the hardware pin of the button, and change PIN_MODE to INPUT_PULLUP if you are using an internal pullup, or INPUT if you are using an external pullup.
Second, the debounce interval. Change INTERVAL_IN_MS to the debounce interval in milliseconds, and the readme says that 5 is a good value.
Third, the pressed state. Change PRESSED_STATE to LOW if the button outputs a LOW when pressed, or to HIGH if the button outputs a HIGH when pressed. The documentation for the Button class notes that by default the pressed state is matched to a HIGH electrical level, which is a detail that trips up anyone using the common pullup arrangement, where a pressed button reads LOW.
The three calls look like this:
button.attach ( PIN , PIN_MODE );
button.interval( INTERVAL_IN_MS );
button.setPressedState( PRESSED_STATE ); Then the loop has to do the work, and the readme is emphatic about it. Call button.update() at the beginning of the loop, and if the button was pressed this loop, check button.pressed(). The method documentation for update() spells out the constraint: because Bounce does not use interrupts, you have to update the object before reading its value, and it has to be done as often as possible, which means including it in your loop(). Only call update() once per Bounce instance per loop().
That polling requirement is the design's main trade, and the rest of this article comes back to it.
The event API, and how it differs from reading a pin
The Button class documentation is a table of methods, and the distinction that matters is between the state of the pin and the state of the button.
isPressed() returns true if the button is currently pressed, whereas pressed() returns true if the button was pressed, and released() returns true if the button was released. The past tense matters, because a physical press lasts a few tens of milliseconds and a loop iteration is much faster, so the loop will usually run several times while the button is down. Only one of those iterations should count as the press.
The rest of the API is the supporting cast. changed() returns true if the state changed on the last update, and read() returns the pin's raw state as HIGH or LOW. fell() and rose() report the signal transitioning from high to low or low to high since the last update, which is the edge-detection pair. attach(int pin, int mode) attaches to a pin and sets that pin's mode, and getPin() returns the pin the instance is attached to.
The timing methods are previousDuration() and currentDuration(), which return the duration in milliseconds of the previous and current state. The documentation says currentDuration() is reset to 0 when the state changes, which is what makes it usable as a hold timer. The duration of the previous state is what you need to detect a long press or a double press.
There is no built-in long-press or double-press detection in the method list, though. You would write it yourself using currentDuration() and changed(), and that is the sort of thing the Debouncer class is there to support.
Where Bounce2 is the wrong choice
The first limitation is the polling model, and it is stated by the library itself. Because Bounce does not use interrupts, you have to call update() before reading the value, and you have to do it as often as possible. A loop() that blocks for a second while talking to a sensor, or that spends most of its time in delay(), will miss the transitions entirely, and a button press can be lost rather than merely debounced incorrectly. For a project with a timing-sensitive input, that is a design constraint you have to design around rather than a setting you can change.
The second is the resolution of the debouncing itself. The interval is set in milliseconds, and 5 is the recommended value. That is appropriate for a human-scale switch, where the contact bounce lasts a few milliseconds. It is not enough resolution for a rotary encoder detent or for a sensor that can change faster than a millisecond, and the library offers no way to use hardware timers or interrupts to improve on it.
The third is that there is no event queue. pressed() is a query of the most recent transition, so a press that happens and is released entirely between two loop iterations is not reported. For a button that is impossible, since a human cannot press and release in under a loop period, but for anything faster it is a real limit.
The fourth is the release pace. The newest published release is v2.71 from 2022-03-21, with v2.60 and v2.58 from a few days in June 2021 before it. The last push to the repository was on 2026-07-20, so the code is still being touched, but the release tags stopped moving four years ago, and there is no changelog in the repository listing to tell you what changed in between.
The fifth is the scope. This is a debouncer for one pin. There is no support for multiple pins in one object, no analogue input, no encoder support, and no interrupt-driven mode to fall back on. A project that needs more than a handful of digital inputs with clean edges will end up writing its own layer on top of Debouncer.
Editorial conclusion
Bounce2 fits a hobby project or a prototype with a physical button whose chatter would otherwise trigger an action several times, since the library is small, MIT licensed and the pressed and released semantics are exactly what a simple input device needs. It is the wrong choice if you need microsecond timing, if your control loop runs infrequently, or if you want interrupt-driven detection, because the whole design is polling based. Before adopting it, copy the three class structure from the readme, pick a debounce interval suited to your switch, and note that the last push was on 2026-07-20 with the newest published release being v2.71 from 2022-03-21.
Frequently asked questions
What is Bounce2 and what problem does it solve?
It is a debouncing library for Arduino and Wiring. Buttons and switches vibrate slightly when opened or closed, producing multiple undesired false states, and the library filters those out so your code sees one press and one release.
How do I install Bounce2?
Install it through your software's Library Manager, or download the latest version and put the Bounce2 folder in your libraries folder. The original Bounce 1 library is included in the extras folder of the download but is no longer supported.
What are the three classes in Bounce2?
Bounce2::Button is the feature rich class most people use, Debouncer is the code that performs the debouncing and is meant for advanced users writing their own implementations, and Bounce links the Debouncer to a hardware pin. Bounce2::Button extends Bounce, and Bounce extends Debouncer.
How do I use a Bounce2 button in my sketch?
Attach it to a pin with button.attach(PIN, PIN_MODE), set the debounce interval with button.interval(INTERVAL_IN_MS), set the pressed state with button.setPressedState(PRESSED_STATE), then call button.update() at the beginning of loop() and check button.pressed(). Because the library does not use interrupts, update() must be called as often as possible, once per instance per loop.
What licence is Bounce2 released under?
MIT, with the licence file at the root of the repository. The last push was on 2026-07-20, and the most recent published release is v2.71 from 2022-03-21.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/thomasfredericks-bounce2)Was this useful?