JC_Button: presses, releases and long presses, polled
JC_Button by Jack Christensen is a small, plain button library with no handlers or callbacks. You call read() at the top of loop(), and then ask simple questions about what it saw: wasPressed() and wasReleased() for the moment of change, isPressed() for the current state, and pressedFor(ms) for whether the button has been held at least that long.
Built in on Mokxi: #include <JC_Button.h> and it builds, with nothing to install. Free, and no account needed.
What JC_Button does
That polling style keeps the logic in your own loop(), which suits state machines well: a menu can check wasReleased() in one state and pressedFor(1000) in another without registering and unregistering functions. Debouncing is built in, 25 ms by default, and a change counts only once the level has held that long.
pressedFor() stays true for as long as the button stays down, so the runnable example keeps a flag to print "held a second" once per press. The class is named Button, which can clash with another library’s Button class in the same sketch. ToggleButton is a second class that flips its state on each press, for on and off switches.
| Library Manager name | JC_Button |
|---|---|
| Author | Jack Christensen |
| Include | #include <JC_Button.h> |
| Boards | every board Mokxi compiles for |
| In the simulator | Simulated: it runs against the part the way it does on the bench. |
| Parts it drives | Pushbutton |
Install it
It builds on every board Mokxi compiles for.
In Mokxi it is built in: #include <JC_Button.h> and the sketch compiles, with no download, no zip and no Library Manager.
On a real board, install "JC_Button" by Jack Christensen from the Arduino IDE’s Library Manager (Sketch, Include Library, Manage Libraries), or add JC_Button to lib_deps in PlatformIO. Mokxi follows the calls of release 2.1.6, so a sketch written here builds there too.
- ESP32-C3
- Arduino Uno
- Arduino Nano
- Arduino Mega 2560
- Arduino Leonardo
- SparkFun Pro Micro
- Arduino Micro
- ESP32-C6
- WCH CH32V003
- ATtiny85
- Raspberry Pi Pico
- Raspberry Pi Pico W
- Seeed XIAO SAMD21
- STM32
- STM32 Nucleo-F411RE
- STM32 Blue Pill
- micro:bit V2
- Arduino Uno R4
- ESP32 DevKit
- ESP32-S3-DevKitC-1
- ESP8266 NodeMCU
- Arduino Pro Mini 3.3 V
- Seeed XIAO ESP32-C3
- ESP32-C3 SuperMini
- Seeed XIAO ESP32-C6
- ESP32-DevKitC V4
- LOLIN32 Lite
- Wemos D1 R32
- Cheap Yellow Display
- TTGO T-Display
- Seeed XIAO ESP32-S3
- Arduino Nano ESP32
- Arduino Nano RP2040 Connect
- Seeed XIAO RP2040
- Waveshare RP2040-Zero
- Arduino Uno R4 WiFi
The calls you will use
In the order a sketch meets them.
Button myBtn(2)
A button on pin 2 with a 25 ms debounce, the pull-up on, and LOW meaning pressed. Further arguments change each of those.
myBtn.begin()
Sets the pin mode and reads the starting level. Call it in setup().
myBtn.read()
Reads and debounces the pin and returns whether it is pressed. Call it once at the start of every pass of loop().
myBtn.wasPressed()
True on the one read() where the button went down.
myBtn.wasReleased()
True on the one read() where it came back up. Acting on release is useful when a long press should do something else.
myBtn.pressedFor(1000)
True while the button has been down for at least 1000 ms. It stays true until release, so use a flag to act once.
if (myBtn.pressedFor(1000) && !longDone) {
longDone = true;
Serial.println("long press");
}myBtn.releasedFor(5000)
True when the button has been up for at least 5 seconds, for a screen that turns itself off when idle.
ToggleButton toggle(3)
A button that flips between on and off at each press; toggleState() returns the current state.
Example: Presses and a long press with JC_Button
On the Arduino Uno R3. It runs in the browser exactly as printed.
#include <JC_Button.h>
Button button(2); // to ground, pull-up on
void setup() {
Serial.begin(9600);
button.begin();
Serial.println("ready");
}
void loop() {
static bool longShown = false;
button.read();
if (button.wasPressed()) Serial.println("pressed");
if (button.wasReleased()) {
Serial.println("released");
longShown = false;
}
if (button.pressedFor(1000) && !longShown) {
Serial.println("long press");
longShown = true;
}
}Wiring
- Arduino Uno R3 2 to Pushbutton 1a
- Arduino Uno R3 GND to Pushbutton 2a
Common errors and how to fix them
The long-press action runs over and over while the button is held
pressedFor() is true on every read() after the time is reached. Set a flag the first time it fires and clear it on wasReleased(), as the example does with longShown.
conflicting declaration of class Button
Another library or your own code also defines a class called Button. Rename your own class, or remove the other button library, since only one Button can exist in a sketch.
wasPressed() never fires
read() is missing or called only now and then. The was calls report what the last read() saw, so read() must run at the start of every pass of loop().
Try JC_Button without installing anything
Open the example, change the sketch, and keep your version in a free account.