Recently one of the microswitches(Omron D2FC-F-7N) on my CM Storm Spawn wore to the point where the mouse would randomly release partway through a drag(They didn't even bother hooking up the switch's NC contact to the microcontroller). So I replaced the switch, hooked it and a brand new switch up to an arduino, and gathered some data on bounce characteristics with a few hundred simulated clicks(used a piece of plastic as a mouse button).
Surprisingly, even the new switch had some really nasty behavior, with, in one instance, the normally open contact losing contact for 200ms when it should have stayed closed. 5% of the time it was over 100ms.
Less surprisingly, it seems like the new switch has a slightly stronger spring in it, so it takes a little less time to snap across the gap.
Source code(I used an arduino micro):
http://pastebin.com/hjRk3yTEExplanation of the various measured times:
flightDown: The time the contact takes to snap from the normally closed contact to the normally open contact when you press the button. Pressing the switch very slowly can make this number very high(several seconds/as long as you want). Flicking the switch can make this number very low(400µs).
flightUp: The time it takes the switch to snap from the normally closed contact to the normally open contact(releasing the button).
maxSingleBounceOnPress: While the switch is bouncing(within 10ms of first closed reading), this is the longest duration between a closed reading and the next closed reading of the normally open contact.
minSingleContactDuration: While the switch is bouncing(within 10ms of first closed reading), this is the shortest time between the first closed reading of the switch and the next open reading of the switch. (I need a faster setup to be confident in a value here, all I can say is you'd need more than 60khz polling rate to catch the closed portion of every bounce if you're not using interrupts).
maxSingleBounceOnRelease: Same as maxSingleBounceOnPress, except after the end of the settle time. This is still the normally open contact..
settleTime: The amount of time it takes for the NO contact to stop bouncing when the switch is pressed, (capped at 10ms, actual settle time typically about 1ms).
bounceNumber: Number of bounces during the settle time.Caveats/future investigation:
The old switch has been soldered and desoldered, the new one has not, so a change in spring characteristics could be caused by the temperature cycling instead of mechanical wear/fatigue. The switch mounting could also be an issue. I may solder both switches to some protoboard to get some more consistency there. Someone with a lot of switches might do a series comparing different brands/models/batches of microswitch.What this means for mouse developers:
If you have double throw switches and extra pins on your microcontroller, USE THEM! If the NO contact reads closed, the button is definitely pressed. If the NC reads closed, the button is released. You don't need any delays for reliable debouncing. (the only reason to delay before reading a button closed is if you have really bad EMI problems. If you want to account for that, only enable that delay if you somehow read the NC and NO contacts both closed at the same time.) This is the only debouncing method that is both fast and reliable.
If you can only afford single throw switches of similar construction, or only use one contact to detect presses, there is no option that is both fast and reliable, you would have to find a way to ignore a 200ms bounce while still registering all the valid clicks(and I can click faster than 5hz).