Hacker News new | past | comments | ask | show | jobs | submit login
Ultimate Guide to Switch Debounce (eejournal.com)
121 points by baybal2 on April 18, 2020 | hide | past | favorite | 54 comments

Debouncing is a useful concept in software design too.

Many UI elements are all too eager to emit hundreds of state update events (like a slider) as the user is finalizing the input they want - but you wouldn't want to send 100 AJAX requests to the webserver while the user's fiddling around. So resetting a 200ms timer before sending the web request is a great analog to the process of physical debouncing.

Another useful software concept is exponential back-off algorithm: https://en.wikipedia.org/wiki/Exponential_backoff

Useful in interacting with rate-limits, unpredictable externalities that are not schedule bound, etc

...and also when 2+ people are trying to talk during a remote meeting.

All too common today! I should internalize this since it seems to happen to me more than it should...

That's useful as an implementation detail, but even more important is the user experience of failing to debounce correctly. If I press a button (etc) twice within 100ms, that generally does not mean I want this to be seen as two presses. Rather, my finger slipped, maybe I have minor neurological problems, I'm drinking, the software itself glitched, whatever. For the user's sake, user interfaces should debounce themselves.

It's all rather striking to me, as the concept of debouncing was one of the first things I learned while reading microcontroller code as a child. (No, I'm not kidding--that was the only book on computers I could find growing up in BFE.)

That we still haven't generally solved this in 2020 is appalling.

(There are lots of variations. There was an article in Software: Practice and Experience in the 90s (?) lamenting the UI race in most X interfaces (and probably all other GUIs). Briefly, lots of interfaces can pop up a dialog or whatever while the user is pressing a button underneath. The dialog often gets the press, resulting in the software executing some action the user did not even see, much less intend.)

If a computer is going to disobey my instructions it should be extremely sure it's doing the right thing. 100ms is too long a threshold to make that assumption. 100ms repetition interval is only 10Hz, which is easily accomplished in short bursts by anybody with moderate skill in button mashing. I'd set it no higher than 50ms (20Hz), which is very difficult even in short bursts.

It depends on the context. If you're trying to fire your gun in a video game, sure, it should respect every button press (subject to hardware debouncing which is always required). If you're submitting an online payment, a delay of 10 seconds per order is still not enough. If you're posting in a forum, duplicates should be automatically pruned.

Trying to pin down the number of milliseconds without context is a great example of bikeshedding.

Yeah, well, wait until you're older. Or sicker.

When I'm older or sicker, I'll use a thing that works for me when I'm older or sicker. Otherwise it's like turning on the screen reader for everyone because blind people can't operate computers otherwise.

That's great for people that are technically inclined. Spend some time with senior citizens and the disabled and you might develop a bit more compassion.

Overly long debounces are frustrating and 100ms is kinda questionable in that regard. And honestly if I wanted debouncing I'd get a mouse that did that.

And carry it around and plug it into every computer you ever touched? Not workable.

On this I definitely recommend checking out RxJS and it's stream operators like denounce: https://www.learnrxjs.io/learn-rxjs/operators/filtering/debo...

The simplest strategy I have been using successfully since forever is one that I found on some device I have repaired.

For most devices it is enough to just probe the switch periodically.

Nobody is ever going to notice couple of milliseconds of lag. Other debouncing strategies also introduce latency as they need to observe the signal for some time.

It is important to set the check period to be longer than settling time.

Assume the switch is in stable state before the check, then there is check and then it is in another stable state. It does not matter which state the check finds as long as the state changes from one stable to another stable. Even if the switch is bouncing at the moment of the check it will be either interpreted as previous state before the switch or the next state after switch.

If you have delicate switch with good (for example gold plated) contacts, to extend the life of the switch it is then possible to only apply potential for a brief period of the check which means that during actual bounce the contact is very unlikely to see any sparks, extending the life of the switch. This does not work for some switches that rely on spark to remove oxides to get good contact.

When you have more than a dozen switches to debounce, it is best to opt for a hardware solution unless you're making something in the 100k+ quantities.

We've used MAX7370 chip for keyboard applications. Comes with built-in debounce capabilities along with ESD protection, low quiescent current and interrupt-based signal to the MCU. It is expensive but well worth the hassle - it can handle up to 64 switches and saves you the pain of GPIO nightmare with custom matrix. In addition, it comes with a hardware memory buffer so you could do an n-key roll over. I've built stuff that I can mash with my palm - like jamming on a couple of dozen switches at the same time and this chip handles it all. Flawlessly.

If you are doing this for a Linux platform, there's actually a gpio matrix keypad driver that works really well. The driver shows up as a regular keyboard input device that can interface with any program that knows how to read /dev/input things.

I do not like the idea of sending an interrupt and cause a havoc on OS side every time two metal plates bounce off each other.

I can understand this when this happens to a device that is created to monitor the switch (switch matrix controller, keyboard controller, etc.) but when this happens to a machine that may have something more important to do it feels at the very least inelegant.

Agreed, just as encapsulation/abstraction is an important and indispensible concept in software engineering, it is also equally if not more critical in hardware applications. For most electronics, there is usually an IC that can solve a problem better than you can develop, often cheaper. 25 discrete components can be encapsulated by a single IC sometimes (with a couple of bypass caps).

> For most devices it is enough to just probe the switch periodically.

No, no, no, please don't. Almost all appliances I use ignore an estimated 60% of my usual button presses because they're polling in intervals just long enough to not recognise anything, and I absolutely hate it.

I always have to hold it down for a bit to make sure my input isn't just ignored. My laptop's power switch has this issue just like the washing machine, the dish washer and pretty much everything else that's not a PC keyboard, and it's one of the most infuriating UI issues I encounter every day, beside inactive text input fields with blinking cursors or selected text.

> No, no, no, please don't. Almost all appliances I use ignore an estimated 60% of my usual button presses because they're polling in intervals just long enough to not recognise anything, and I absolutely hate it.

That's just sloppy design. "Periodically" has meant "every 20 milliseconds" for projects I've shipped in the past. Anything shorter than 100 ms or so should be imperceptible.

Part of the problem you're likely seeing is due to the rise of capacitive touch "buttons", which are terrible in so many ways. But, alas, they are cheap and give a smooth front face, so designers and product managers love them....

(About the only time they're actually a good solution is when you need a completely sealed button.)

Power buttons, like on a PC or washing machine, often require being held as a means of preventing accidental activation.

I don't mean just power buttons. When I said almost every button not on a PC keyboard I meant it. On the washing machine every single button has to be held almost half a second or it won't do anything. It's super frustrating. But of course it's possible to mess this up the other way too - one of my devices reacts quick to button presses, but you have to wait about half a second until it will react to the next press.

I believe that in some applications this is by design

You don't want your washing machine to start just because you bumped into the button. Give it a good press and it's ok. (Same with the mechanical sensitivity of the buttons itself, they're not the same as your phone touchscreen let's put it this way)

There's no need for debouncing to introduce latency under normal circumstances. React immediately to state changes, and whenever you observe a state change begin temporarily ignoring further state changes for long enough for the bouncing to settle. The only added latency is on the falling edge of extremely short presses (or rising edge of extremely short releases), which in practice doesn't happen because of limited speed of the human hand. But note that latency-adding debouncing methods double as noise filters, which this technique does not, so you might want to add a bit of noise filtering (and associated latency) too.

I think of this as "non causal debouncing". You debounce before the event happens.

> For most devices it is enough to just probe the switch periodically.

Often you want to use interrupts instead of polling - well again, you can just ignore subsequent interrupts if they are within too short of an interval.

Fortunately on many MCUs you can just enable hardware debounce.

> Often you want to use interrupts instead of polling - well again, you can just ignore subsequent interrupts if they are within too short of an interval.

And you are really screwed if you have to do it with an extremely simple, and cheap IC, like 4 bit micros, because their CPU power may well be not enough for that, especially if they are to control something real time.

This is exactly why super cheap electronics uses conductive rubber buttons. Conductive rubber buttons don't bounce.

Conductive rubber buttons absolutely do bounce (though I presume that was a joke).

??? for as long as I remember, all and everybody was using them exactly for that reason. Slow raising edge can be considered a bounce by some logic, but that is easily fixable by Schmitt triggers

Thanks, that's interesting. I suppose they specifically choose contacts with a high resistance.

Well, according to The Art of Electronics by Horowitz & Hill (Page 506 of the Second Edition), “When the switch is closed, the two contacts actually separate and reconnect, typically 10 to 100 times over a period of about 1 msec.” This just goes to show you how undefined this field is, because this book is regarded as the “Electronics Bible” by many engineers, but their value of 1 msec (which is the one I was told as a young engineer) is less than Jack’s average findings, let alone his maximum findings.

In the Third Edition, on page 802, Horowitz and Hill write "For physically large switches, the bounce can be as long as 50ms." That first quote is from a section on clocked debouncing, which can be made insensitive to contact bounce by digital means.

I like the data sheet for the automotive contact debouncing IC.[1] That's very cute. In dirty environments, you need a minimum current and voltage, maybe 10mA, 12V, to punch through dirt and water on the contacts. That IC does that, but it only turns on the power intermittently, so you don't drain the battery polling the dashboard switches.

I've hit that with the antique Teletype machines. They were intended to run with 120VDC on the keyboard contacts, and you need about 24V or so to get reliable punch-through.

[1] https://www.ti.com/lit/ds/symlink/tic12400-q1.pdf

The Maxim's MAX6816/MAX6817/MAX6818[1] are pretty good as well in that you don't need RC filters for each input, so less components needed to debounce inputs.

[1] https://datasheets.maximintegrated.com/en/ds/MAX6816-MAX6818...

In my experience with a variety of switches and microcontrollers this actually isn't too big of a deal as it used to be. It is worth testing out, but I think it's worth testing before investing a lot of hardware/software development on it. Adding some resistance or a simple RC low-pass filter can help, and also many microcontrollers come with basic anti-bounce inputs.

As other posters said another easy effective strategy is to just ignore inputs after the initial transition. You can do this and still pick up long presses too if you need to!

This is definitely a problem with any circuit that is complex enough. It was nice to see Ben Eater explain it and solve it in multiple ways, once using a 555 timer and a capacitor[1] and the other time using just the SR latch of the 555[2].

[1] https://www.youtube.com/watch?v=81BgFhm2vz8

[2] https://www.youtube.com/watch?v=WCwJNnx36Rk

Must admit I've always though this is an oscillation created by the inductivity and capacitance of the circuit, never though of it as an actual mechanical switch bouncing off the other contact. Shouldn't a spark form and short-circuit the mechanical contacts even if they bounce around a little?

Arcing is only present if there's a significant amount of current flowing, which there isn't in switches used for user input.

Technology Connections has a good video on switches sparking, or not, https://youtu.be/jrMiqEkSk48

Tangential. but you want to avoid arcing on contacts as much as possible, because electric arcs are insanely hot and physically erode and destroy the contacts eventually (this is the normal mode of relay failure)

When I started dabbling in electronics recently, I ran into switch bouncing apparently as I used a push button to generate the "clock" input of a CD4017 decade counter and it showed rather erratic output behavior.

Adding a capacitor fixed it. Which reminds me that I should really invest in an oscilloscope to validate my (not so) educated guesses.

Great resource to read up on this topic, thanks.

He never explains why this actually happens. As a non-engineer, I'm curious why it's not immediate...

Nothing is perfectly stiff. Nothing moves perfectly smoothly. Every mechanical part has some amount of "springiness" and will vibrate when struck, pushed, flexed, etc. So a switch contact literally "bounces" like a hammer on a piano string as it is closed. His analogy of a ping-pong ball on a desk isn't great, but it's not exactly wrong, either.

As for "immediate", the switch closure feels immediate to human perception (supposedly limited to about 1/20 second, for touch). But to modern electronics, nanoseconds are easily countable; and switch bounce can be measured in microseconds, or even milliseconds for a big, heavy electromechanical component.

Here are some better articles.



A switch is a mechanical thing, obviously, that must have two metal plates touching one another fur electricity to flow. It takes time for one metal plate to move from position one to position two.

So, while this switching is generally really fast, there is a period of time when the two metal plates are reeeally close, but not touching.

Small bits of dust, grit and/or oxide on the metal can get in the way while the plates are really close, but not touching, causing electricity to flow, then not flow, then flow...

Arcing can also happen when there's higher voltages used too.

This happens a lot when you're using a push button, and also when you're switching on something that uses lots of current. You can actually hear the problem if you deliberately turn on your light switch really slow... The buzzing you hear is when electricity is arcing across the plates (wearing them out somewhat). It's not a problem for the light, but it's a huge problem for, say, a large pump.

Back in the day with big springy switches, the metal contacts would literally bounce off each other when turning on/off!

when you move the switch contacts together or apart for a very brief moment they may literally bounce microscopically and make/break contact a few extra times

When I saw the title I thought it would be the old Jack Ganssle article which is also worth a look if you're interested in this topic: http://www.ganssle.com/debouncing.htm

Is it really that hard to just add a simple RC circuit?

No polling required.

And here's a component values calculator: https://protological.com/debounce-calaculator


If you see the circuit this calaculator (sic) proposes, you'll see it won't debounce fully the closing the switch (and you'll have to invert the logic, which in principle it's ok).

Plus adding one component to the circuit (you'll most likely have the resistor anyway).

It might work for your case but you'll most likely need a software solution as well, depends on your switch and the logical gate input impedance.

aka : what functional transform can I apply to an unpredictable function Signal(Time) to decide if it models a zero or a one.

Isn't the answer some form of hysteresis? Whether you implement it in hardware or software it's up to you.

When given the chance, I like using SPDT switches and an SR Latch to deal with bouncing.

One problem, finding SPDT momentary switches is haaard, near nothing there that is small, and smt

Yeah - that is one problem. I would love to have MX switches in SPDT format. I have find these a while back ago: https://www.aliexpress.com/item/32430367243.html

I instantly closed this website because it loaded slow and then hit me with 2 pop-ups and a location request.

I instantly skipped reading your comment when I saw "I instantly..."

Applications are open for YC Winter 2023

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact