DEV Community

Ling Chen
Ling Chen

Posted on

Debouncing: The Tiny Hardware Problem That Haunts Every Click, Keypress and Button

Every physical button you have ever pressed lies a little. When metal contacts inside a switch close, they do not make one clean connection. They bounce, rapidly touching and separating for a few milliseconds before settling. To a fast enough circuit, one press looks like several. This phenomenon, called contact bounce, is why engineers write debounce logic, and why your old mouse may suddenly start double-clicking on its own.

What bounce looks like

If you put an oscilloscope on a mechanical switch, a single press shows a jagged burst of on/off transitions lasting anywhere from under 1 ms to over 10 ms, depending on the switch, its age and its condition. Release often bounces too.

A microcontroller sampling every few microseconds would happily report five presses where a human made one.

Debouncing strategies

Engineers handle this in hardware, software or both.

Hardware debouncing

  • RC filter + Schmitt trigger: A resistor–capacitor network smooths the signal, and a Schmitt trigger converts it back into a clean edge.
  • SR latch with an SPDT switch: A set–reset latch locks the first contact, making later bounce irrelevant.

These approaches are robust but add components and cost.

Software debouncing

Most modern devices debounce in firmware. Common approaches:

1. Delay after the first edge (eager):

if (pin_changed && (now - last_change) > DEBOUNCE_MS) {
    report_event();
    last_change = now;
}
Enter fullscreen mode Exit fullscreen mode

This is fast to respond, but noise can trigger it.

2. Wait for a stable state (deferred):

if (raw != stable) {
    if (++count >= STABLE_SAMPLES) { stable = raw; report_event(); count = 0; }
} else {
    count = 0;
}
Enter fullscreen mode Exit fullscreen mode

This is more reliable, but it adds latency equal to the stability window.

3. Integrator or shift-register methods: Shift samples into a byte and treat 0xFF as pressed and 0x00 as released. It is elegant and cheap.

The latency trade-off

Here is the catch: debounce time is latency. Gaming mouse makers compete on responsiveness, so firmware may use very short debounce windows. That works fine when switches are new and clean. As contacts wear or oxidise, bounce lasts longer, can exceed the debounce window and gets reported as a second click.

That is the root of the famous "mouse double-click problem". It is not usually a software bug, but an ageing switch outliving its firmware assumptions.

Some manufacturers now let users adjust debounce time in companion software, trading a few milliseconds of latency for reliability. Others moved to optical switches, where a light beam replaces metal contacts and bounce largely disappears.

Observing bounce without an oscilloscope

You can see the symptoms from the operating system side. Browsers expose mousedown/mouseup events with high-resolution timestamps via event.timeStamp. If you log the interval between consecutive presses of the same button, human-made presses rarely come closer than about 50–80 ms. Intervals of a few milliseconds suggest bounce leaking through.

A minimal logger:

let last = 0;
addEventListener("mousedown", (e) => {
  const t = e.timeStamp;
  console.log(e.button, (t - last).toFixed(1), "ms");
  last = t;
});
Enter fullscreen mode Exit fullscreen mode

For non-developers, a ready-made double click test does the same thing with a friendlier interface. You press a button 25 times, and it logs each interval, flags unusually short repeats and exports a CSV. It is a useful diagnostic, with the caveat that it measures what the browser observes, after OS and firmware processing, and not the raw electrical signal.

Beyond mice

Bounce affects anything with mechanical contacts:

  • Keyboards: Chattering keys type double letters. Mechanical keyboard firmware such as QMK exposes debounce algorithms and timing.
  • Embedded projects: Every Arduino beginner meets bounce on their first button.
  • Industrial controls: Limit switches and relays need debouncing to avoid false triggers.
  • Rotary encoders: Bounce causes skipped or reversed steps, a classic cause of jumpy scroll wheels.

Takeaways

  1. Physical switches always bounce. The only question is by how much.
  2. Debounce logic trades latency for reliability.
  3. Ageing switches can outgrow their firmware's debounce window.
  4. Optical switches and adjustable debounce are the modern answers.
  5. You can observe the symptoms in a browser in a few lines of JavaScript.

Next time your mouse opens a folder you only meant to select, you will know exactly what is going on: a few microscopic metal contacts, bouncing just a little too long.

Top comments (0)