Robot Button, v1.0.0
Posted on

The library for implementing buttons.
Major version. Implementing individual buttons. Support for bypassing contact bounce.
Features
- possibilities:
- implementing individual buttons:
- a delayed polling approach is used to bypass contact bounce;
- a delay between polls is realized without blocking the main cycle (via the Robot Timer library);
- implementing individual buttons:
- structures:
- the
TimerControlledButtonstructure represents an individual button; it uses a built-in non-blocking timer to bypass contact bounce.
- the
Examples
Button modes:
#include <TimerControlledButton.h>
#include <ClockFunc.h>
#include <stdint.h>
using namespace irenica_ideas::robot_button;
using namespace irenica_ideas::robot_timer;
constexpr auto BUTTON_PIN = 12;
// the Arduino documentation recommends 50 ms as the debounce time:
// https://docs.arduino.cc/built-in-examples/digital/Debounce/
constexpr auto BUTTON_UPDATE_PERIOD = 0.05;
constexpr auto BUTTON_LOG_LENGTH = 56;
constexpr auto BUTTON_LOG_FACTOR_FOR_RAW_INPUT = 2;
constexpr auto BUTTON_LOG_FACTOR_FOR_STATE = 3;
constexpr auto BUTTON_LOG_FACTOR_FOR_PRESSING = 4;
constexpr auto BUTTON_LOG_FACTOR_FOR_RELEASING = 5;
auto button = TimerControlledButton(
BUTTON_PIN,
BUTTON_UPDATE_PERIOD,
clockForArduino
);
void setup() {
Serial.begin(9600);
button.initialize();
}
void loop() {
// update the button; only once per loop iteration
button.update();
char buttonLogBuffer[BUTTON_LOG_LENGTH + 1 /* for null terminator */ ] = {0};
snprintf(
buttonLogBuffer,
sizeof(buttonLogBuffer),
"digitalRead:%d,isPressed:%d,didItPressed:%d,didItReleased:%d",
// raw input; due using a pull-up resistor the button logic is inverted, see:
// https://docs.arduino.cc/tutorials/generic/digital-input-pullup
(digitalRead(BUTTON_PIN) == LOW) * BUTTON_LOG_FACTOR_FOR_RAW_INPUT,
// check if the button is pressed; any number of times per loop iteration
button.isPressed() * BUTTON_LOG_FACTOR_FOR_STATE,
// check if the button has been pressed; any number of times per loop iteration
button.didItPressed() * BUTTON_LOG_FACTOR_FOR_PRESSING,
// check if the button has been released; any number of times per loop iteration
button.didItReleased() * BUTTON_LOG_FACTOR_FOR_RELEASING
);
Serial.println(buttonLogBuffer);
}
Different types of buttons:
#include <TimerControlledButton.h>
#include <ClockFunc.h>
#include <stdint.h>
using namespace irenica_ideas::robot_button;
using namespace irenica_ideas::robot_timer;
constexpr auto LED_COUNT = 3;
constexpr auto LED_TRIGGERED_BY_STATE = 0;
constexpr auto LED_TRIGGERED_BY_PRESSING = 1;
constexpr auto LED_TRIGGERED_BY_RELEASING = 2;
// the Arduino documentation recommends 50 ms as the debounce time:
// https://docs.arduino.cc/built-in-examples/digital/Debounce/
constexpr auto BUTTON_UPDATE_PERIOD = 0.05;
uint8_t ledPins[LED_COUNT] = {8, 9, 10};
uint8_t buttonPins[LED_COUNT] = {11, 12, 13};
uint8_t ledVoltageLevels[LED_COUNT] = {LOW, LOW, LOW};
TimerControlledButton buttons[LED_COUNT] = {
TimerControlledButton(
buttonPins[LED_TRIGGERED_BY_STATE],
BUTTON_UPDATE_PERIOD,
clockForArduino
),
TimerControlledButton(
buttonPins[LED_TRIGGERED_BY_PRESSING],
BUTTON_UPDATE_PERIOD,
clockForArduino
),
TimerControlledButton(
buttonPins[LED_TRIGGERED_BY_RELEASING],
BUTTON_UPDATE_PERIOD,
clockForArduino
)
};
void setup() {
for (auto ledIndex = 0; ledIndex < LED_COUNT; ledIndex++) {
pinMode(ledPins[ledIndex], OUTPUT);
buttons[ledIndex].initialize();
}
}
void loop() {
// update all the buttons; only once per loop iteration
for (auto& button: buttons) {
button.update();
}
// check if the button is pressed; any number of times per loop iteration
ledVoltageLevels[LED_TRIGGERED_BY_STATE] =
buttons[LED_TRIGGERED_BY_STATE].isPressed() ? HIGH : LOW;
// check if the button has been pressed; any number of times per loop iteration
if (buttons[LED_TRIGGERED_BY_PRESSING].didItPressed()) {
ledVoltageLevels[LED_TRIGGERED_BY_PRESSING] =
ledVoltageLevels[LED_TRIGGERED_BY_PRESSING] == LOW ? HIGH : LOW;
}
// check if the button has been released; any number of times per loop iteration
if (buttons[LED_TRIGGERED_BY_RELEASING].didItReleased()) {
ledVoltageLevels[LED_TRIGGERED_BY_RELEASING] =
ledVoltageLevels[LED_TRIGGERED_BY_RELEASING] == LOW ? HIGH : LOW;
}
for (auto ledIndex = 0; ledIndex < LED_COUNT; ledIndex++) {
digitalWrite(ledPins[ledIndex], ledVoltageLevels[ledIndex]);
}
}
Screenshots
Output of the Serial Plotter tool for the button modes:
