https://github.com/Xylopyrographer/XP_Button
XP_Button is an Arduino IDE library for debouncing and reading momentary contact switches like tactile button switches. "Long presses" of arbitrary length can be detected. Works well in state machine constructs. Use the read()
function to read each button in the main loop, which should execute as fast as possible.
The simplest way to use a button with a microcontroller is to wire the button between a GPIO pin and ground, and turn on the internal pullup resistor. The Button
class constructor takes four arguments, but three have default values that work for a button wired in this manner.
A derived class, ToggleButton
, implements button objects that need only "push-on, push-off" functionality.
The following example sketches are included with the library:
- SimpleOnOff: Turns a LED connected to a GPIO pin on and off.
- LongPress: Demonstrates detecting long and short button presses.
- UpDown: Counts up or down, one number at a time or rapidly by holding the button down.
- Toggle: Demonstrates ToggleButton functionality.
The constructor defines a button object.
Button( pin, dbTime, puEnable, invert );
pin
: GPIO pin number that the button is connected to. (uint8_t
)
dbTime
: debounce time in milliseconds. Defaults to 25ms if not given.(uint32_t
)
puEnable
: when set true
enables the microcontroller's internal pull-up resistor. When set false
, an external pull-up or pull-down resistor is used. Defaults to true
if not given. (bool
)
invert
: when set false
, interprets a high logic level to mean the button is pressed. When set true
interprets a low level as pressed. true
should be used when a pull-up resistor is used, false
for a pull-down resistor. Defaults to true
if not given. (bool
)
None.
// button connected from pin 2 to ground, 25ms debounce, pullup enabled, logic inverted
Button myButton( 2 );
// same as above but this button needs a longer debounce time (50ms)
Button myButton( 3, 50 );
// a button wired from the MCU pin to Vcc with an external pull-down resistor
Button myButton( 4, 25, false, false );
The constructor defines a toggle button object, which has "push-on, push-off" functionality. The initial state can be on or off. See the section, ToggleButton Library Functions for functions that apply specifically to the ToggleButton object. The ToggleButton class is derived from the Button class, so all Button functions are available, but because it is inherently a more limited concept, the special ToggleButton functions will be most useful, along with begin()
and read()
.
ToggleButton( pin, initialState, dbTime, puEnable, invert );
pin
: GPIO pin number that the button is connected to (uint8_t
)
initialState
: Initial state for the button. Defaults to off (false
) if not given. (bool
)
dbTime
: Debounce time in milliseconds. Defaults to 25ms if not given. (uint32_t)
puEnable
: true
to enable the microcontroller's internal pull-up resistor, else false
. Defaults to true
if not given. (bool
)
invert
: false
interprets a high logic level to mean the button is pressed, true
interprets a low level as pressed. true
should be used when a pull-up resistor is employed, false
for a pull-down resistor. Defaults to true
if not given. (bool
)
None.
// button connected from pin 2 to ground, initial state off,
// 25ms debounce, pullup enabled, logic inverted
ToggleButton myToggle( 2 );
// same as above but this button is initially "on" and also
// needs a longer debounce time (50ms).
ToggleButton myToggle( 3, true, 50 );
// a button wired from the MCU pin to Vcc with an external pull-down resistor,
// initial state is off.
Button myButton( 4, false, 25, false, false );
Initializes the Button object and the pin it is connected to.
myButton.begin();
None.
None.
myButton.begin();
Reads the button and returns a boolean
value to indicate whether the button is pressed. The read()
function needs to execute very frequently in order for the sketch to be responsive. A good place for read()
is at the top of loop()
. Often, the return value from read()
will not be needed if the other functions below are used.
myButton.read();
None.
true
if the button is pressed, else false
(bool
)
myButton.read();
These functions check the button state from the last call to read()
and return false or true accordingly. These functions do not cause the button to be read.
myButton.isPressed();
myButton.isReleased();
None.
true
or false
, depending on whether the button has been pressed (or released) or not. (bool
)
if ( myButton.isPressed() ) {
//do something
}
else {
//do something else
}
These functions check the button state to see if it changed between the last two calls to read()
and return false or true accordingly. These functions do not cause the button to be read. Note that these functions may be more useful than isPressed()
and isReleased()
since they actually detect a change in the state of the button, which is usually what we want in order to cause some action.
myButton.wasPressed();
myButton.wasReleased();
None.
true
or false
, depending on whether the button was pressed (released) or not. (boolean
)
if ( myButton.wasPressed() ) {
//do something
}
Checks that the button has not changed state for at least the button debounce time.
This function does not cause the button to be read. Using this function preceded by multiple calls to read()
can be used during setup()
to ensure the button state is debounced before proceeding.
myButton.isStable();
None.
true
if the variable has not changed state for at least the debounce time (dbTime
) as specified when calling the constructor, false
otherwise. (bool
).
while ( myButton.isStable() != true ) {
myButton.read();
}
// button is stable (either pressed or released) - continue
These functions check to see if the button is pressed (or released), and has been in that state for the specified time in milliseconds. Returns false
or true
accordingly. These functions are useful to detect "long presses". Note that these functions do not cause the button to be read.
myButton.pressedFor( ms );
myButton.releasedFor( ms );
ms
: The number of milliseconds (uint32_t)
true
or false
, depending on whether the button was pressed (or released) for the specified time. (bool
)
if ( myButton.pressedFor( 1000 ) ) {
// button has been pressed for one second
}
Under certain circumstances, it may be useful to know when a button last changed state. lastChange()
returns the time the button last changed state, in milliseconds (the value is derived from the millis()
function).
myButton.lastChange();
None.
The time in milliseconds when the button last changed state. (uint32_t
)
uint32_t msLastChange = myButton.lastChange();
Returns a boolean value to indicate whether the toggle button changed state the last time read()
was called.
myToggle.changed();
None.
true
if the toggle state changed, else false
. (bool
)
if ( myToggle.changed() ) {
// do something
}
else {
// do something different
}
Returns a boolean value to indicate the toggle button state as of the last time read()
was called.
myToggle.toggleState();
None.
true
if the toggle is "on", else false
(bool
)
if ( myToggle.toggleState() ) {
// do something
}
else {
// do something different
}
XP_Button is a virtual clone of the JC_Button library written by Jack Christensen, available at https://github.com/JChristensen/JC_Button. This work is fully acknowledged and credited.
XP_Button adds the isStable()
library function and incorporates a fix to ensure the button state is only updated after its pin becomes stable for a time equal to the debounce time.
The XP_Button library is also enabled within the Arduino IDE for all microcontrollers.
The functions and syntax are exactly the same as JC_Button.
Many thanks Jack!
XP_Button Library Copyright (C) 2024 Xylopyrographer, released under GNU GPL v3.0
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License v3.0 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/gpl.html
- Internal code cleanup. No functional changes.
- Documentation tweak.
- Initial release.