Quit Bouncing Around
Bounce on a single-pole, double-throw (SPDT) switch with normally closed (NC) contact opening and normally open (NO) contact closing (Image source: David Ashton)
In an earlier column -- Say "Hello" to the LogiSwitch Workbench -- I introduced a rather clever shield for the Arduino Uno. This little scamp allows you to break out all of the Arduino's analog and digital input/output (I/O) pins, along with the 5V, 3V3, and GND pins, to three full-size breadboards.
I'm currently finding this bodacious beauty to be extremely useful with regard to prototyping my hobby projects and setting up testbenches to verify the code that accompanies some of my articles.
In the aforementioned column, I noted that there are some additional components on the Workbench. These include three LEDs with associated current-limiting resistors. The inputs to these LEDs are connected to a 3-pin header, thereby allowing you to connect them to any of the Arduino's pins. There are also three momentary tactile switches. These feed into a 3-channel LogiSwitch debouncer IC. The outputs from this IC are connected to a 3-pin header, once again allowing you to connect them to any of the Arduino's pins.
It's this debouncer IC I want to talk about here, but first, it may be a good idea to briefly refresh our memories as to what switch bounce is, the problems it can cause, and the traditional ways that are used to mitigate its effects.
When most people think about a device like a light switch on a wall, they assume that its switching action is a bit like dropping a ball of Play-Doh on a wooden table. In the case of the Play-Doh, it simply goes "splat" on the table and ceases all movement. Similarly, people think the switch simply opens or closes, and "that's all she wrote."
In reality, however, changing the state of a switch -- toggle, rocker, pushbutton, etc. -- is more like dropping a ping pong ball on a wooden table. In the same way that the ping pong ball bounces multiple times before settling down, so too does the switch bounce. Such bouncing can occur both when the switch is closed/activated or opened/deactivated. The reason this may be a problem is when we are working with microcontrollers that can sample their inputs millions of times a second. In this case, switch bounce may cause the microcontroller to think that multiple switch transitions have taken place.
Another issue is that there are no real standards here. As a result, every engineer addresses switch bounce in different ways. Another concern is that many engineers underestimate the effects of bounce, so they fail to account for it properly. For example, I've heard even experienced engineers say that bouncing will have finished after 1 ms (one millisecond; a thousandth of a second), so "If you wait for 2 ms after the first edge you'll be fine."
This simply isn’t true. Embedded guru Jack Ganssle wrote a very interesting article about switch bounce. As part of his column, Jack tested a bunch of switches that he pulled out of his treasure chest of spare parts to discover that the average switch bounce duration was 1.6 ms and the worst-case was 6.2 ms. One of my chums who was a technician in the US Air Force told me that they recommended waiting for 20 ms after the first transition.
Have you ever pressed the up or down channel selector buttons on your TV's remote control, only to see it scroll through a bunch of channels? Guess what -- the controller's designer failed to adequately handle switch bounce.
There are myriad ways in which engineers address debounce -- some of them even work. In the past, it was common to debounce switches using hardware techniques, like a resistor-capacitor combo followed by a Schmitt trigger. For those desiring the best-of-the-best prior to the advent of microprocessors, a really good solution can be achieved using single-pole, double-throw switches, where each switch drives an RS Latch. More recently, it's become common for switch bounce to be addressed in the software using counters or shift registers.
Discussing all of these traditional techniques would make a fantastic column in its own right. For the moment, however, we are going to look at the recently introduced debouncer ICs from LogiSwitch. These little rascals are so affordable, easy to use, and efficacious that they now have pride of place in all of my hobby projects.
There are two families of these ICs: the LS1x and the LS1xx. Each family has 3-, 6- and 9-channel parts, and each of these parts is available in lead through-hole (LTH) or surface-mount technology (SMT) packages. For the purpose of our discussions here, we'll focus on the LTH versions of the LS18 and the LS118, both of which are 3-channel devices.
We'll start with the LS18. Let's assume we have a single-pole, single-throw (SPST) switch feeding one of the LS18's inputs, while its corresponding output feeds a microcontroller. Observe that we don’t need pull-up resistors on the switch inputs to the LS18 or its outputs to the microcontroller because the LS18 takes care of all this for us.
LogiSwitch LS18 noise mitigating switch debouncer IC (Image source: Max Maxfield)
The LS18 is intended for use in electrically noisy environments. The way it works is rather clever, because it ignores any noises spikes on its inputs. Once the LS18 has determined that a real switch event is taking place, it will cause its output to follow the input, but not until 20 ms following the final bounce.
Waveform for LogiSwitch LS18 noise mitigating switch debouncer IC (Image source: Max Maxfield)
Now, let's turn our attention to the LS118. In this case, the three switch inputs, SW0, SW1, and SW2 have associated outputs named NL/HS0, NL/HS1, and NL/HS2, respectively, where "NL/HS" stands for "Normally low with handshake capability." This can be a little tricky to wrap one's brain around, so let's take things step-by-step.
First, the "Normally low" part means that the output is the inverse of the input. When the normally open (NO) switch contact is high, the output from the LS118 will be low, and vice versa. Another aspect of this device is that the output switches almost instantaneously following the first transition on the input. This means that the LS1xx family is intended for use in noise-free environments in which speed of response is a high priority.
Waveform for LogiSwitch LS118 without using its handshake capability (Image source: Max Maxfield)
This is where things start to get very clever indeed. It's common to have a bunch of switches and for the software to be running around a loop. Let's assume that at the beginning of the loop we read the state of all the switches. If one or more of the switches have been activated, in addition to performing actions like incrementing counters, it's common to have to set flags to remember the fact that we are now waiting for these switches to go inactive again.
An alternative is to use the LS118's single-wire handshake protocol. In this case, when the microcontroller sees that a switch has been activated, in addition to performing the requisite action like incrementing a counter, it can change its pin from an input to an output, pull the pin low for 50 ns (nanoseconds), and then revert the pin to being an input again.
Waveform for LogiSwitch LS118 using its handshake capability (Image source: Max Maxfield)
When the LS118 sees its output being pulled low, it responds by pulling this output low itself. One advantage of this approach is that the software no longer has to keep track as to which switch inputs have to go inactive.
Another possibility is to remove the requirement for polling the inputs. In this case, the outputs from the LS118 (and other members of this family) can be fed into an OR gate whose output is used to trigger an interrupt. When the microcontroller services this interrupt, it can check to see which switch or switches have been activated, perform any associated actions, use the handshake protocol to "clear" the switches, and return to do whatever it was doing.
Well, I for one am tremendously impressed. I typically use a mix of the LS1x and LS1xx families depending on what I wish to achieve. In my current project, for example, I'm using an LS118 to debounce the three momentary pushbuttons on the Workbench card, and an LS18 to debounce the toggle switch on my testbench front panel. Having access to these little beauties saves a lot of time and effort on my part, thereby leaving me free to do the fun stuff. How about you? Can you envisage a use for these devices in your own systems?