Created
March 16, 2025 09:54
-
-
Save skull-squadron/f8a9307b4bec00609401530b88d0866d to your computer and use it in GitHub Desktop.
[Arduino] Properly debounced button class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Arduino proper switch debouncing | |
// Based on https://docs.arduino.cc/built-in-examples/digital/Debounce | |
// | |
// Button libraries that do not work properly: | |
// - Button - doesn't debounce | |
// - EZButton - doesn't debounce | |
// - ezButton - laggy | |
// Arduino Nano 5V | |
// 5V pin -> Vcc | |
// Gnd pin -> Gnd | |
// D2 pin -> SW0 -> 10K resistor -> Gnd | |
// D10 pin -> 20K resistor -> BJT NPN Collector (i.e, S9013) | |
// SW0 other side -> Vcc | |
// LED+ -> BJT NPN Base | |
// LED- -> Gnd | |
// BJT NPN Emitter -> 220 ohm resitor -> Vcc | |
#define __ASSERT_USE_STDERR | |
#include <assert.h> | |
const unsigned long SERIAL_BAUD = 250000; | |
void serial_begin() { | |
static volatile bool did = false; | |
if (!did) Serial.begin(SERIAL_BAUD); | |
did = true; | |
} | |
void __assert(const char *func, const char *file, int lineno, const char *sexp) { | |
serial_begin(); | |
Serial.print("Assertion failed: "); | |
Serial.print(sexp); | |
Serial.print(' '); | |
Serial.print(func); | |
Serial.print(' '); | |
Serial.print(file); | |
Serial.print(':'); | |
Serial.println(lineno); | |
Serial.flush(); | |
abort(); | |
} | |
const int SW0_PIN = 10; | |
const int LED_PIN = 2; | |
bool led = false; | |
class Button { | |
public: | |
Button(int pin) : Button(pin, 50) {} | |
Button(int pin, unsigned long debounce_delay) : _pin(pin) { | |
setDebounceDelay(debounce_delay); | |
pinMode(pin, INPUT_PULLUP); | |
} | |
bool isPressed() { | |
bool reading = read(); | |
if (_lastButtonState != reading) { | |
_lastButtonState = reading; | |
_lastDebounceTime = millis(); | |
} | |
if (millis() - _lastDebounceTime > _debounce_delay) { | |
if (_buttonState != reading) { | |
_buttonState = reading; | |
return reading; | |
} | |
} | |
return false; | |
} | |
void setDebounceDelay(unsigned long delay) { | |
assert(delay >= 2); // Must be >= 2 ms because humans can't type that fast | |
_debounce_delay = delay; | |
} | |
private: | |
int _pin; | |
bool _buttonState = false; | |
bool _lastButtonState = false; | |
unsigned long _lastDebounceTime = millis(); | |
unsigned long _debounce_delay; // ms | |
bool read() { | |
return digitalRead(_pin) == HIGH; | |
} | |
}; | |
Button sw0(SW0_PIN); | |
void setup() { | |
serial_begin(); | |
pinMode(LED_PIN, OUTPUT); | |
// Flash the LED twice to show it's working | |
digitalWrite(LED_PIN, HIGH); | |
delay(250); | |
digitalWrite(LED_PIN, LOW); | |
delay(250); | |
digitalWrite(LED_PIN, HIGH); | |
delay(250); | |
digitalWrite(LED_PIN, LOW); | |
Serial.println("setup"); | |
} | |
void sw0Pressed() { | |
Serial.println("pressed"); | |
led = !led; | |
digitalWrite(LED_PIN, led); | |
delay(50); | |
} | |
void loop() { | |
if (sw0.isPressed()) | |
sw0Pressed(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment