Arduino library · Input

AceButton: every button event through one handler

AceButton by Brian Park takes a different approach from the click-handler libraries. Instead of one function per action, every event from every button goes to a single handler, which is told which button, which event and the button’s state. A switch on the event type then decides what happens. This scales well: ten buttons still need only one handler.

Built in on Mokxi: #include <AceButton.h> and it builds, with nothing to install. Free, and no account needed.

What AceButton does

Pressed and released are always reported. The rest are switched on as features of the button’s ButtonConfig: kFeatureClick, kFeatureDoubleClick, kFeatureLongPress, kFeatureRepeatPress for auto-repeat while held, and kFeatureHeartBeat for a regular tick. The kFeatureSuppress flags hide the released event that follows a click or long press, so the handler is not told about the same press twice.

AceButton does not set the pin mode itself, so the sketch calls pinMode(pin, INPUT_PULLUP) first. The default timings are a 20 ms debounce, 200 ms for a click, 400 ms between the two presses of a double click and 1000 ms for a long press. Beyond plain pins, it can read a resistor ladder of buttons on one analog pin, or binary-encoded buttons, through other ButtonConfig classes.

Library Manager nameAceButton
AuthorBrian T. Park
Include#include <AceButton.h>
#include <ace_button/fast/ButtonConfigFast1.h>
#include <ace_button/fast/ButtonConfigFast2.h>
#include <ace_button/fast/ButtonConfigFast3.h>
Boardsevery board Mokxi compiles for
In the simulatorSimulated: it runs against the part the way it does on the bench.
Parts it drivesPushbutton

Install it

It builds on every board Mokxi compiles for.

In Mokxi it is built in: #include <AceButton.h> and the sketch compiles, with no download, no zip and no Library Manager.

On a real board, install "AceButton" by Brian T. Park from the Arduino IDE’s Library Manager (Sketch, Include Library, Manage Libraries), or add AceButton to lib_deps in PlatformIO. Mokxi follows the calls of release 1.10.1, so a sketch written here builds there too.

The calls you will use

In the order a sketch meets them.

AceButton button(BUTTON_PIN)

A button on a pin that reads HIGH when released, the pull-up arrangement. A second argument of LOW is for pull-down wiring.

pinMode(BUTTON_PIN, INPUT_PULLUP)

Turns the pull-up on. AceButton leaves the pin mode to the sketch, so this line is required.

ButtonConfig *config = button.getButtonConfig()

The settings object the button uses. By default every button shares the one system config.

config->setEventHandler(handleEvent)

Sets the handler for all buttons on this config: void handleEvent(AceButton *button, uint8_t eventType, uint8_t buttonState).

config->setFeature(ButtonConfig::kFeatureLongPress)

Turns on an extra event. Call it once per feature: click, double click, long press, repeat press or heartbeat.

config->setLongPressDelay(2000)

Changes how long a press must last to be a long press. setClickDelay() and setDoubleClickDelay() change the others.

button.check()

Reads and debounces the pin and calls the handler for any event. Call it on every pass of loop(), every few milliseconds at least.

case AceButton::kEventClicked:

The event names to switch on: kEventPressed, kEventReleased, kEventClicked, kEventDoubleClicked, kEventLongPressed and kEventRepeatPressed.

switch (eventType) {
  case AceButton::kEventClicked: toggle(); break;
  case AceButton::kEventLongPressed: reset(); break;
}

Example: Button events with AceButton

On the Arduino Uno R3. It runs in the browser exactly as printed.

sketch.ino · Arduino Uno R3
#include <AceButton.h>
using namespace ace_button;

const int BUTTON_PIN = 2;
AceButton button(BUTTON_PIN);

void handleEvent(AceButton *button, uint8_t eventType, uint8_t buttonState) {
  Serial.print("pin ");
  Serial.print(button->getPin());
  Serial.print(" state ");
  Serial.print(buttonState);
  Serial.print(": ");
  switch (eventType) {
    case AceButton::kEventPressed:
      Serial.println("pressed");
      break;
    case AceButton::kEventReleased:
      Serial.println("released");
      break;
    case AceButton::kEventClicked:
      Serial.println("clicked");
      break;
    case AceButton::kEventLongPressed:
      Serial.println("long pressed");
      break;
    default:
      Serial.println(eventType);
  }
}

void setup() {
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  ButtonConfig *config = button.getButtonConfig();
  config->setEventHandler(handleEvent);
  config->setFeature(ButtonConfig::kFeatureClick);
  config->setFeature(ButtonConfig::kFeatureLongPress);
  Serial.println("setup(): ready");
}

void loop() {
  button.check();
}

Wiring

  • Arduino Uno R3 2 to Pushbutton 1a
  • Arduino Uno R3 GND to Pushbutton 2a

Open it in the editor, wired and ready to run

Common errors and how to fix them

The handler gets pressed and released but never clicked

Click, double click and long press are off until switched on. Call config->setFeature(ButtonConfig::kFeatureClick) and the others you need in setup().

A long press also triggers a released event that undoes it

Set ButtonConfig::kFeatureSuppressAfterLongPress, which hides the release after a long press (or reports it as kEventLongReleased), so the handler can treat the two cases apart.

The button reads pressed as soon as the sketch starts

The pin is floating because the pull-up is off. Add pinMode(pin, INPUT_PULLUP) in setup() before the first check(); AceButton does not do it for you.

Try AceButton without installing anything

Open the example, change the sketch, and keep your version in a free account.