OneButton: several actions from a single button
OneButton, by Matthias Hertel, turns one push button into several inputs. It watches the button鈥檚 timing and calls a function you choose for a single click, a double click, any number of quick clicks, the start of a long press, every moment of it, and its end. A device with one button can then have a menu: click to step, double click to confirm, hold to go back.
Built in on Mokxi: #include <OneButton.h> and it builds, with nothing to install. Free, and no account needed.
What OneButton does
It works by polling. Your loop() calls button.tick() on every pass, and the library debounces the contact and times each press. That means loop() must keep turning over: a delay(500) in it can swallow a double click completely.
One behavior surprises people. When a double click handler is attached, a single click is reported only after the double click window (400 ms by default) has passed with no second press, because until then the library cannot know which it was. Shorten the window with setClickMs() if single clicks feel slow.
| Library Manager name | OneButton |
|---|---|
| Author | Matthias Hertel |
| Include | #include <OneButton.h>#include <OneButtonTiny.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 <OneButton.h> and the sketch compiles, with no download, no zip and no Library Manager.
On a real board, install "OneButton" by Matthias Hertel from the Arduino IDE鈥檚 Library Manager (Sketch, Include Library, Manage Libraries), or add OneButton to lib_deps in PlatformIO. Mokxi follows the calls of release 2.6.1, 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 路 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.
OneButton button(2, true)
A button on pin 2 that reads LOW when pressed, with the internal pull-up turned on. Wire it between the pin and ground.
button.attachClick(onClick)
Calls onClick() after a single short press. The function takes no arguments and returns nothing.
button.attachDoubleClick(onDouble)
Calls a function after two presses close together.
button.attachLongPressStart(onHold)
Calls a function once when the button has been held for the long press time (800 ms by default). attachLongPressStop() fires on release.
button.attachMultiClick(onMany)
Fires after three or more quick presses; getNumberClicks() inside the handler says how many.
void onMany() {
Serial.print("clicks: ");
Serial.println(button.getNumberClicks());
}button.setPressMs(1000)
Changes how long a press must last to count as long. setClickMs() and setDebounceMs() set the other two timings.
button.tick()
Reads the button and runs any handler that is due. Call it every time through loop().
Example: Click and long press on one button
On the Arduino Uno R3. It runs in the browser exactly as printed.
#include <OneButton.h>
OneButton button(2, true);
void clicked() { Serial.println("click"); }
void longStart() { Serial.println("long press"); }
void setup() {
Serial.begin(9600);
button.attachClick(clicked);
button.attachLongPressStart(longStart);
Serial.println("ready");
}
void loop() {
button.tick();
delay(5);
}Wiring
- Arduino Uno R3 2 to Pushbutton 1a
- Arduino Uno R3 GND to Pushbutton 2a
Common errors and how to fix them
None of the handlers ever run
tick() is not being called often enough, or at all. Put button.tick() in loop(), and take out delay() calls that hold loop() up for more than a few milliseconds.
Single clicks react half a second late
That is the double click window: the library waits to see whether a second press follows. Lower it with button.setClickMs(250), or leave double click unattached if you do not need it.
invalid user-defined conversion from lambda to 'callbackFunction'
Handlers are plain function pointers, so a lambda that captures variables does not fit. Use a lambda with an empty [] capture or a normal function, or attachClick(fn, pointer) to pass your data in.
Keep going
Learn
Parts
Try OneButton without installing anything
Open the example, change the sketch, and keep your version in a free account.