Key Engineering Takeaways
- •When mechanical switch contacts collide, elastic metallic spring leaves bounce rapidly for 2ms–10ms before settling.
- •To a high-speed microcontroller running at 16MHz–240MHz, a single finger press appears as 10 to 50 distinct rapid button presses.
- •Hardware debouncing uses an RC low-pass filter (10kΩ + 100nF) to smooth voltage spikes, paired with a Schmitt Trigger for sharp logic edges.
- •Software debouncing ignores state changes occurring within a 20ms–50ms refractory time window.
- •Never put delay() inside an Interrupt Service Routine (ISR) for debouncing; compare timestamps using millis() or micros().
- • Pull-Up Resistors and Basic RC Time Constants
- • Pushbuttons
- • 10kΩ Resistors
- • 100nF Ceramic Capacitors
- • 74HC14 Schmitt Trigger IC
- • Microcontroller / Oscilloscope
The Physics of Mechanical Contact Bounce
Hardware Debouncing: RC Low-Pass Filter & Schmitt Trigger
Software Debouncing: Non-Blocking Millis() Timer Algorithm
const int BUTTON_PIN = 4;
int buttonState; // Current stable reading
int lastButtonState = HIGH; // Previous raw reading
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 50; // 50 milliseconds debounce window
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
Serial.begin(115200);
}
void loop() {
int reading = digitalRead(BUTTON_PIN);
// If the switch changed due to noise or press, reset debounce timer
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
// If reading has persisted longer than debounce delay, accept it as real
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
if (buttonState == LOW) {
Serial.println("Legitimate Click Registered!");
}
}
}
lastButtonState = reading;
}Frequently Asked Questions
Why should I never use delay(50) for debouncing?
delay(50) completely halts CPU execution for 50 milliseconds. During this time, your robot cannot calculate motor PID loops, decode sensor streams, or respond to emergency stop commands. Always use non-blocking millis() timer comparisons.