June 2, 2024
Heres a basic button handler class and some variations for arduino, although you can easily adapt it to other platforms.
This code is nothing special, but its here in case you don't want to spend the ten or so minutes to write one of your own.
For all of these, make sure to define BUTTON_ACTIVE_STATE as either true or false. Also, the button.update() method needs to be polled at a high rate, since these classes do not use interrupts.
This first one calls the callback on pressing the button.
class ButtonHandlerOnPress { uint8_t pin_num; void (*callback)(int); uint32_t previous_activation_ms = 0; bool previous_active = false; // to prevent the callback from firing repeatedly if the button is held down. public: ButtonHandlerOnPress(uint8_t pin, void (*cb)(int)) { this->callback = cb; this->pin_num = pin; pinMode(pin, INPUT); } void update() { // this needs to be called frequently uint32_t time = millis(); if (digitalRead(this->pin_num) == BUTTON_ACTIVE_STATE) { if (this->previous_activation_ms + DEBOUNCE_MS < time && !this->previous_active) { this->previous_activation_ms = time; this->previous_active = true; this->callback(this->pin_num); } } else { this->previous_active = false; } } };
This one activates on release of the button, much like most of the buttons in windows apps.
class ButtonHandlerOnRelease { uint8_t pin_num; void (*callback)(int); uint32_t previous_activation_ms = 0; bool previous_active = false; // to prevent the callback from firing repeatedly if the button is held down. public: ButtonHandlerOnRelease(uint8_t pin, void (*cb)(int)) { this->callback = cb; this->pin_num = pin; pinMode(pin, INPUT); } void update() { // this needs to be called frequently uint32_t time = millis(); // this section runs if the button is to activate on release if (digitalRead(this->pin_num) != BUTTON_ACTIVE_STATE) { // button is not pressed if (this->previous_activation_ms + DEBOUNCE_MS < time && this->previous_active) { this->previous_activation_ms = time; this->callback(this->pin_num); } this->previous_active = false; } else { // button is pressed this->previous_active = true; } } };
Or if you need both for some reason:
class ButtonHandler { uint8_t pin_num; void (*callback)(int); uint32_t previous_activation_ms = 0; bool previous_active = false; // to prevent the callback from firing repeatedly if the button is held down. bool activate_on_release = false; // fire callback on push or release? public: ButtonHandler(uint8_t pin, void (*cb)(int), bool activateOnRelease) { this->callback = cb; this->pin_num = pin; this->activate_on_release = activateOnRelease; pinMode(pin, INPUT); } void update() { // this needs to be called frequently uint32_t time = millis(); if (this->activate_on_release) { // this section runs if the button is to activate on release if (digitalRead(this->pin_num) != BUTTON_ACTIVE_STATE) { // button is not pressed if (this->previous_activation_ms + DEBOUNCE_MS < time && this->previous_active) { this->previous_activation_ms = time; this->callback(this->pin_num); } this->previous_active = false; } else { // button is pressed this->previous_active = true; } } else { // this section runs if the button is to activate on press if (digitalRead(this->pin_num) == BUTTON_ACTIVE_STATE) { if (this->previous_activation_ms + DEBOUNCE_MS < time && !this->previous_active) { this->previous_activation_ms = time; this->previous_active = true; this->callback(this->pin_num); } } else { this->previous_active = false; } } } };