The secret life of switchesWhen a switch opens or closes, the contacts rebound several times. Jack investigates this behavior by testing a variety of switches.
Click here for reader response to this article
The beer warms a bit as you pound the remote control. Again and again, your temper fraying, you click the "channel up" key until the TV finally rewards your efforts. But channel 345 is playing Jeopardy so you again wave the remote in the general direction of the set and continue punishing the buttons.
Some remotes work astonishingly well, even when you bounce the beam off three walls before it attracts the attention of the TV's IR detector. Others don't. One vendor told me reliability simply isn't important as users will subconsciously hit the button again and again till the channel changes.
When a single remote press causes the tube to jump two channels, we developers know lousy debounce code is at fault. The FM radio on my sailboat has a tuning button that advances too far when I hit it hard. The usual suspect: bounce.
When the contacts of any mechanical switch bang together they rebound a bit before settling, causing bounce. Debouncing, of course, is the process of removing the bounces, of converting the brutish realities of the analog world into pristine ones and zeros. Both hardware and software solutions exist, though by far the most common are those done in a snippet of code.
Surf the net to sample various approaches to debouncing. Most are pretty lame. Few are based on experimental bounce parameters. A medley of anecdotal tales passed around the newsgroups substitute for empirical evidence.
Ask most developers about the characteristics of a bounce and they'll toss out a guess at a max bounce time. But there's an awful lot going on during the bounce. How can we build an effective bounce filter, in hardware or software, unless we understand the entire event? During a bounce a long and complex string of binary bits is hitting our code. What are the characteristics of that data?
We're writing functions that process an utterly mysterious and unknown input string. That's hardly the right way to build reliable code.
So I ran some experiments. I pulled some old switches out of my junk box. Twenty bucks at the ever-annoying local Radio Shack yielded more. (Have you noticed that Radio Shack has fewer and fewer components? It's getting hard to buy a lousy NPN transistor there.) Baynesville Electronics (www.baynesvilleelectronics.com), Baltimore's best electronics store, proved a switch treasure trove. Eventually I had 18 different kinds of switches.
My desktop PC always has a little $49 MSP430 (TI's greatly underrated 16-bit microprocessor) development board attached, with IAR's toolchain installed. It's a matter of seconds to pop a little code into the board and run experiments. Initially I'd planned to connect each switch to an MSP430 input and have firmware read and report bounce parameters. A bit of playing around with the mixed signal scope (MSO) showed this to be an unwise approach.
Many of the switches exhibited wild and unexpected behavior. Bounces of under 100ns were common (more on this later). No reasonable micro could reliably capture these sorts of transitions, so I abandoned that plan and instead used the scope, connecting both analog and digital channels to the switch. This let me see what was going on in the analog domain, and how a computer would interpret the data. A 5V supply and 1,000Ω pull-up completed the test jig.
If a sub-100ns transition won't be captured by a computer why worry about it? Unfortunately, even a very short signal will toggle the logic once in a while. Tie it to an interrupt and the likelihood increases. Those transitions, though very short, will occasionally pervert the debounce routine. For the sake of the experiment we need to see the transitions.
Figure 1: Switches tested
I tested the trigger switches from an old cheap game-playing joystick (the three yellow ones in Figure 1), the left mouse button from an ancient Compaq computer (on PCB in upper left corner), toggle switches, pushbuttons, and slide switches. Some were chassis mount, others were to be soldered directly onto circuit boards.
I pressed each switch 300 times, logging the min and max amount of bouncing for both closing and opening of the contacts. Talk about mind-numbing boredom! I logged every individual bounce time for each actuation into a spreadsheet for half the switches till my eyes glazed over and gentle wife wondered aloud if I was getting some sort of Pavlovian reward.
The results were interesting.
So how long do switches bounce for? The short answer: sometimes a lot, sometimes not at all. Only two switches exhibited bounces exceeding 6,200 μs. Switch E, what seemed like a nice red pushbutton, had a worst-case bounce of 157ms when it openedalmost a 1/6 of a second! Yuk. Yet it never exceeded a 20μs bounce when closed. Go figure.
Another switch took 11.3ms to completely close one time; other actuations were all under 10ms.
Toss out those two samples and the other 16 switches exhibited an average 1,557μs of bouncing, with, as I said, a max of 6,200μs. Not bad at all.
Seven of the switches consistently bounced much longer when closed than when opened. I was amazed to find that for most of the switches many bounces on opening lasted for less than 1μsthat's right, less than a millionth of a second. Yet the very next experiment on the same switch could yield a reading in the hundreds of microseconds.
Identical switches were not particularly identical. Two matching pairs were tested; each twin differed from its brother by a factor of two.
Years ago a pal and I installed a system for the U.S. Secret Service that had thousands of expensive switches on panels in a control room. We battled with a unique set of bounce challenges because the uniformed officers were too lazy to stand up and press a button. They tossed rulers at the panels from across the room. Different impacts created (and sometimes destroyed, but hey, it's only taxpayer money after all) quite an array of bouncing.
So with that experience in mind, I tried to actuate each device in my experiment with a variety of techniques. Pushing hard or soft, fast or slow, releasing gently or with a snap, I was looking for different responses. Switch F, a slide switch, was indeed very sensitive to the rate of actuation. Toggle switch G showed a three to one difference in bounce times depending on how fast I bonked its lever. A few others showed similar results but there was little discernable pattern.
I was fascinated with the switches' analog behavior. A few operated as expected, yielding a solid zero or 5V. But most gave much more complicated responses.
The MSO responded to digital inputs assuming TTL signal levels. That means 0 to 0.8V is a zero, 0.8 to 2V is unknown, and above 2V a one. The instrument displayed both digital and analog signals to see how a logic device would interpret the real world's grittiness.
Switch A was typical. When opened the signal moved just a bit above ground and wandered in the hundreds-of-millivolts range for up to 8ms. Then it suddenly snapped to a one. As the signal meandered up to near a volt the scope interpreted it as a one, but the analog's continued uneasy rambles took it in and out of "one" territory. The MSO showered the screen with hash as it tried to interpret the data.
It was if the contacts didn't bounce so much as wiped, dragging across each other for a time, acting like a variable resistor.
Looking into this more deeply I expanded the traces for switch C and, with the help of Ohm's Law, found the resistance when the device opened crawled pretty uniformly over 150μs from zero to 6W, before suddenly hitting infinity. There was no bouncing per se; just an uneasy ramp up from 0 to 300mV before it suddenly zapped to a solid +5.
Another artifact of this wiping action was erratic analog signals treading in the dreaded no-man's land of TTL uncertainty (0.8 to 2V), causing the MSO to dither, tossing out ones or zeroes almost randomly, just as your microprocessor would if connected to the same switch.
The two from the el cheapo game joystick were nothing more than gold contacts plated onto a printed circuit board; a rubber cover, when depressed, dropped some sort of conductive elastomer onto the board. Interestingly, the analog result was a slow ramp from 0 to 5V, with no noise, wiping, or other uncertainty. Not a trace of bounce. And yet, the logic channel showed a millisecond or so of wild oscillations. What's going on?
With TTL, signals in the range of 0.8 to 2V are illegal. Anything goes, and everything did. Tie this seemingly bounce-free input to your CPU and prepare to deal with tons of oscillationvirtual bounces.
My assessment, then, is that there's much less whacking of contacts going on than we realize. A lot of the apparent logic hash is from analog signals treading in illegal logic regions. Regardless, the effect on our system is the same and the treatment identical. But the erratic nature of the logic warns us to avoid simple sampling algorithms, like assuming two successive reads of a one means a one.
Anatomy of a bounce
We know how long the contacts bounce and that lots of digital zaninessultra-short pulses in particularcan appear.
But what happens during the bounce? Quite a lot, and every bounce of every switch in my experiment was different. Many produced only high- speed hash till a solid one or zero appeared. Others generated a serious pulse train of discernable logic levels like one might expect. I was especially interested in results that would give typical debounce routines heartburn.
Consider switch E again, that one with the pretty face that hides a vicious 157ms bouncing heart. One test showed the switch going to a solid one for 81ms, after which it dropped to a perfect zero for 42ms before finally assuming its correct high state. Think what that would do to pretty much any debounce code!
Switch G was pretty well behaved, except for a couple of times when it provided a logic one a few microseconds before falling to zero for over 2ms. Then it assumed its correct final logic-one state. The initial narrow pulse might escape your polled I/O, but would surely fire off an interrupt, had you dared wire the system so. The poor interrupt service routine would be left puzzled as it contemplates 2ms of nothingness. "Me? Why did it invoke me? Ain't nuthin' there!"
One nice, high-quality microswitch never showed more than 1.18ms of bouncing. But digging deeper I found it usually generated a pulse train guaranteed to play havoc with simple filter code. There's no high-speed hash, just hard-to-eliminate solid ones and zeroes. One actuation yielded seven clean zero levels ranging in time from 12 to 86μs, and seven logic ones varying from 6 to 95μs. Easy to filter? Sure. But not by code that just looks for a couple of identical reads.
What happens if we press the buttons really, really fast? Does that alter the bouncing in a significant way? It's awfully hard for these 50 year old fingers to do anything particularly quickly, so I set up a modified experiment, connecting my MSP430 board to a sizeable 3A four-pole relay. Downloading code into the CPU's flash let me toggle the relay at different rates.
Bounce times ranged from 410 to 2,920μs, quite similar to those of the switches, presumably validating the experiment. The relay had no noticeable analog effects, banging cleanly between 0 and 5V.
The raucous clacking of contacts overwhelmed our usual fare of classical music for a few hours as the MSO accumulated bounce times in storage mode. When the relay opened, it always had a max bounce time of 2.3 to 2.9ms, at speeds from 2.5 to 30Hz. More variation appeared on contact closure: at 2.5Hz bounces never exceeded 410μs, which climbed to 1,080μs at 30Hz. Why? I have no idea. But it's clear there's some correlation between fast actuations and more bounce. These numbers suggest a tractable factor of two increase, though, not a scary order of magnitude or more.
Margin of error
I admit these experiments aren't terribly scientific. No doubt someone with a better education and more initials following his or her name could do a more reputable study for one of those journals no one reads. But as far as I know there are no studies on the subject available anywhere, and we working engineers need some empirical information.
Use a grain of salt when playing with these numbers. Civil engineers don't really know the exact strength of a concrete beam poured by indolent laborers, so they beef things up a bit. They add margin. Do the same here. Assume things are worse than shown.
Next month I'll look at some debouncing strategies.
Jack G. Ganssle is a lecturer and consultant on embedded development issues. He conducts seminars on embedded systems and helps companies with their embedded challenges. Contact him at firstname.lastname@example.org.
The joystick switches you described probably employ carbon pucks in the keypad to bridge the gold contacts. Many membrane switches as used in desktop and laptop keyboards use carbon on two sheets of polyester film placed facing each other.
The carbon switches I've measured show resistance around 50 ohms when closed. I imagine that the slow switching characteristic you saw is a result of that high resistance--which is probably a lot higher when the puck is just starting to make contact with the board.
I imagine many of us have thought of doing a study such as you did but haven't had the time. Thanks for stepping up to the plate!
- Wallace White
Switches appear more interesting than just bounce. There is an urban legend (possibly true) that switch contacts need a minimum amount of current when they bounce in order to self-clean on an atomic scale. The amount of this 'wiping current' is up for grabs - most people I know use a rule of thumb. I actually saw a MicroSwitch rating for this back in '78 or so but can't come up with any now. The object of the wiping current is to keep the contacts functional for the full 10 million closures under the -40C to 125C ratings. It is my contention that the lack of this current is why TV remotes go into the trash can after a year or two.
If you know anything about this legend, I'd very much like to know more.
- Steve Vreeland
I have something of a special interest in this, as I have had to deal with a similar kind of thing in ignition system design. Most of our performance ignitions have been designed to be able to work with point-type triggering, which means that we are constantly struggling with how much we need to filter the input signal. The typical point type distributor has a significant amount of bounce, mostly when the points close, that can confuse RPM limiting software (which looks at the period between triggers to determine RPM). If we filter the signal too much to get rid of the bounce, we run the risk of retarding the ignition timing too much. Modern electronic means of triggering are now so pervasive that if a customer complains about early RPM limiter activation, and I find out that he or she is using a point distributor, I just recommend changing to magnetic or optical triggering. Thanks for all of your "button-pushing"!
- Dave Telling
Interesting. You've validated my insistance on always basing my debouncing on timing rather than majority vote. My favorite el-cheapo debounce code is to only look at the switch every 100ms. Your one perverse switch would defeat this, but for everything else it works surprisingly well.
- Tim Wescott