Elliott Sound Products | Switch De-Bouncing |
Main Index Articles Index |
We like to think that a switch is a simple binary (on/ off) device that provides power when on, and removes it when off. With lighting and most appliances, they come on when the switch is operated, and go off again when the switch is turned off. What we don't see is the chaos that occurs - especially when a switch is turned on. With high voltage or current loads (e.g. AC mains), there can also be considerable chaos when the switch is turned off. Mostly, it's not a problem.
Switches are used everywhere, and most of the time they do what we want. The contacts bounce as they close, but for the majority of applications this doesn't matter at all. It's usually not even audible when we switch an audio source, although occasionally you may hear a soft 'click'. The number of makes and breaks as a switch (or relay contacts) closes can range from 2 or 3 up to 50 or more, from the same switch operated in the same way every time.
If a switch is used to control a logic circuit, that's a whole new can of worms, because a counter (for example) will advance somewhere between 5 and 50+ counts due to contact bounce. Relay contacts do the same, and even a reed relay (which you'd think would be ideal) will have contact bounce. The 'general wisdom' used to be that bounce would last for ~20ms, but some switches can extend that significantly. Even the opening bounce shown in Fig. 1.2 extends beyond 30ms.
Always make sure that there is sufficient contact 'wetting' current when switching DC. If the current is too low, some contact materials will not become fully conductive upon closure. A few milliamps is usually enough, but switches designed for high current may need more. The minimum current may be shown in the datasheet if you use a 'name brand' switch or relay.
Contact bounce is very close to being completely random. Even a relay, activated in the same way with the same voltage will give you a different pattern pretty much every time. I've not performed a thorough statistical analysis of the process, but I have measured countless relays and switches over the years, and every contact closure is different from the others. Some might look similar, but make and break timings will be different, as will the number of disconnections and the total duration. To get a reliable de-bounce circuit you need to test the switch (or type of switch) to see just what variations you'll get in use.
To give you an example, the on-line EE Journal has a 9-part series on switch contact bounce. That's an extraordinary amount of information about something that many people won't even realise is a problem. It is a problem, but not in all cases. Logic circuits (including processors) are the most vulnerable because they're so fast that they can 'see' every transition as a potentially valid switch closure. Fortunately, an oscilloscope can also see the transitions. The series referred to isn't the only one of course - there are countless examinations of switch contact bounce on the Net.
The drawing shows the essential 'bits' of a miniature toggle switch. The contact actuator is spring-loaded, and as it traverses the centre point of its travel, the movable contact suddenly 'snaps' from one position to the other, aided by the spring. This drawing is pretty close to reality, as the exploded photo shows. Some switches may have surprisingly complex internal mechanisms to ensure that the snap action is as positive as possible. The contact actuator is usually made from a slippery plastic material, and it has to provide insulation to isolate the moving contact from the switch bushing and lever (and of course the end-user). As you can see from the photo, the plastic insulator is tiny. Note that I removed one side of the plastic switch body so the contacts are visible. The 'NO' and 'NC' contact designations are arbitrary, as you decide which is which when you wire the switch.
You can see why I never recommend using miniature toggle switches for mains voltages - the only thing between the mains and the switch housing is a tiny piece of plastic! Other mechanisms may be quite different, depending on the size, current rating, etc. The range is vast, but hopefully you get the general idea.
I've included this not just to show (more-or-less) what's inside, but to show that no position of the switch can allow continuity between the NO (normally open) and NC (normally closed) contacts unless the switch has been physically broken. It also gives you an idea as to how contact bounce occurs - anything with a spring behind it has the ability to provide recoil when it suddenly stops moving. The drawing and photo don't cover all possibilities, just the demo switch I used.
Pushbutton switches are a common 'HMI' (human-machine interface), and the range is staggering. Some have 'snap' action (tactile), some make an audible 'click', some are noiseless and have no mechanical feedback. They are available as 'NO' (normally open), 'NC' (normally closed), changeover (SPDT - single-pole, double-throw), some have multiple poles (separate switching circuits) and others have integral lamps (usually LEDs). Contacts may just push together under the force of the human, others slide together to provide a 'self-cleaning' function. Almost all of them show contact bounce when activated!
When you need a switch to perform a simple make-break action, the choice of switch is important. You need to consider the current and voltage that the contacts are subjected to. Most small switches and relays will be limited to about 30V DC, with an AC rating that depends on the contact clearance and insulation provided. Using miniature toggle switches for mains is not recommended, even if the claimed ratings indicate that it 'should be alright'. Mostly it's not, for the simple reason that the clearance between hazardous voltages and the end-user is almost always insufficient.
If circuitry is activated by an electromechanical relay (EMR), de-bouncing the contacts will also be necessary if the output is handled by logic circuits. Relays can have extended bounce because the contacts are at the end of flexible 'arms', and that can result in much longer than expected contact bounce duration. Where completely bounce-free operation is essential, it may better to use an optoisolator. This isn't always possible, especially if one needs to interface with 'legacy' equipment. Optoisolators may also be less reliable in the (very) long term, as they are electronic components which can be damaged by ESD (electrostatic discharge), where an EMR is immune from most ESD 'events'.
If you are switching very low voltage and current (e.g. an audio signal), the contact material is important, with gold (or gold plated) being the best. It's not the best conductor, but gold is resistant to corrosion from almost all substances. If the coating is too thin or impure the underlying contact material may corrode through the gold plating, causing intermittent operation. If the task is switching the AC mains, the switch contacts must be rated for the full voltage and peak current encountered in use, and gold is a poor choice.
Always check the datasheet for the switch you intend to use, bearing in mind that if they come from anywhere other than a major distributor, a datasheet won't be available. That being the case, you need to perform tests to find out what the switch really does when it activated/ deactivated. One thing is certain - it won't be what you hope for! Even if you do read the datasheet, it will tell you how many times the switch can make or break its rated current, it might include info on the contact material, and it almost certainly will not describe contact bounce. For example, the C&K 8020 series pushbutton datasheet tells you (almost) everything you need to know, a lot of stuff you don't need, but nothing at all about contact bounce.
Many of the issues described here are also present with relays, and I suggest that you read Relays, Selection & Usage. Both Part 1 and Part 2 are relevant. In many cases, contact bounce is not an issue (switching mains, muting audio, etc.) but if the switch interfaces with logic or a microcontroller (including PICs, Arduino, etc.) then you'll almost always need to mitigate any contact bounce.
To test any switch, it can be wired as shown next. Although I've only shown single-pole switches, the same applies for dual or multi-pole switches, with each pole tested individually. This is important, because if multiple poles are tested as a group, the actions of each will be obscured by the others and you may get a false impression of the problem. You need to know how to run your scope in single-sweep mode, and set the trigger for rising or falling as appropriate. You test by capturing traces as the switch is closed, and as it's opened. Once you've set it up it only takes a few seconds for each test, but you'll spend more time than that being fascinated by the number of contact bounces you see each time.
The test is easy, but a digital scope with single sweep capability is essential. The two types of switch I tested were SPST and SPDT. For an SPST switch, you'll need to capture the waveform using positive edge and negative edge so you can see both closing and opening. With SPDT switches, the test is arranged so you see not just the contact bounce, but also the contact transit time from NC to NO and vice versa. This shows everything in a single capture, but you need to arm the scope's trigger to capture both a switch press (or activation by whatever means) and a release. They will rarely be the same (as shown in Fig. 2.5).
Fig. 1.2 is a scope capture of a miniature push-button closing. The image has been modified only to remove excess screen space, but the waveform is untouched. The supply was 12V, feeding a 1k resistor. This is by no means the worst I saw, but it's representative of what you are likely to see in practice. Much of the time you won't care about contact bounce, but there will come a time where you must eliminate it lest 'bad things' happen. Apparently intermittent operation of logic or PIC circuits is a common result of contact bounce.
The capture was taken using a C&K 8020 series miniature pushbutton, with the scope's timebase set for 100μs/ division. The contacts bounce for over 400μs, but it can be a lot worse. Relays have a heavier armature and 'springy' internals that can cause contact bounce to extend for several milliseconds. If you need to deal with contact bounce, you also need to be acquainted with the exact type of switch you have to interface with. One of the few switches that (theoretically) has no bounce is a mercury tilt switch, but these are uncommon to the point where most people will never have seen one. I tested one and was disappointed to see low-level 'hash' as the blob of mercury made contact (these switches are hermetically sealed, so contact contamination isn't possible). I do admit that the mercury switches I have are at least 50 years old, but they have an indefinite life.
Contact bounce is not just a problem as a switch closes contacts, as some switches have significant make/ break cycles as the contacts open as well. Others open cleanly, with no hint of bounce - most of the time! If you run a series of test and see just one instance of bounce, it has to be fixed so you can be confident that it will do what's expected every time.
I tested a toggle switch and got the output shown above. The disturbances last for over 40ms, with multiple makes and breaks. Note that the timebase is 10ms/ division - 100 times that of the previous test! The switch is SPST, so has a single contact set. Contact make bounce was no better, but I haven't shown it because it's similar to the results for breaking contacts, but reversed (the final output is 12V rather than 0V as seen in Fig. 1.2).
Most activations of the mercury switch were 'clean', with a perfect transition from open to closed (and vice versa). However, I saw the above a few times and captured it for posterity. It's not 'bounce', but shows a high resistance 'semi-contact' for about 10μs before proper contact is made (the scope is set for 4μs/ division). The test current was 12mA. This is of academic interest only, and won't be useful for most applications because mercury switches (of all kinds) are frowned upon because of their highly toxic contents. All contact breaks were clean, with no sign of disturbance in any of the multiple tests I performed.
It's been possible for quite some time for you to buy ICs with one or more de-bounce circuits, and there was one that I used many, many years ago. It was an elegant solution, but it's long-gone, and I can't even recall the part number. There are modern replacements though, but they are only available in SMD packages.
The (currently available) MAX6818 has 8 circuits, but at AU$20 each, it's an expensive IC - especially if you only need to de-bounce one or two switches. There are quite a few options, and with the proliferation of PICs in everything now it's often done in software. It's not trivial though, and requires a fair bit of code to ensure that the signal is stable before it's acted upon. This may mean that a hardware solution is preferable. Using the software might seem like a good idea, but it can use a fair bit of available code space, and may prevent the PIC/ micro (etc.) from doing anything else while it's busy trying to determine if a switch closure is valid or not.
There are easier ways to do it if you need a clean switching signal without any bounce. A small-signal MOSFET (e.g. 2N7000) can work (at least with switches without too much bounce), but a CMOS Schmitt trigger will work very well. Both will ignore contact bounce when the switch is closed, and intermittent contact when it's opened, but both need some external circuitry to do so. An important part of that is protection against electrostatic discharge (ESD) if the switch is exposed to the 'real world'. The timing capacitor may be sufficient, but you may need more robust protection in some circuits.
In general, it's best to avoid custom ICs (IMO), because they can vanish without a trace. The LS18 is a case in point. It's shown in an application note from Digikey, but it doesn't appear to be available to buy. Getting the datasheet was easy, but the IC itself seems to have gone the same way as the one I mentioned above. CMOS Schmitt trigger ICs are available anywhere, and their inbuilt hysteresis makes de-bouncing fairly easy.
There are two options for switching - applying a positive voltage to initiate the switching, or applying a ground. Using a positive switching voltage is fairly uncommon, because it requires that the supply voltage is routed to the switch. A ground (pretty much by definition) is available almost everywhere within a chassis, so (at least in theory) only one switching wire is required. Most of the time, we expect that a positive input to logic or a microcontroller will indicate a 'switch closed' condition, as that is taken to be the active state. Simple logic might be polarity sensitive, but it makes no difference with a PIC or Arduino (for example) as it's programmable.
A 'simple' timer circuit (whether integrated or discrete) will use a capacitor to integrate the switch output, and it has to be either charged (switched from the positive supply) or discharged (ground referenced). Either way, if even a small capacitor is shorted, the instantaneous current can be extreme. The series resistance of the switch and its track(s) will be less than 1Ω, so with a 5V supply the cap discharge will be over 5A. This is undesirable for many reasons. It won't damage the capacitor, but it can create a noise 'spike' on the ground or supply circuit that may cause the circuit to malfunction. The high peak current may also damage the switch (long term) if it's not designed to handle much current. In most cases, if the current can be limited to a few hundred milliamps there should be no issues.
The process of contact bounce elimination is a difficult one, and there is no 'one size fits all' solution. Even with dedicated ICs, it may be necessary to make adjustments to the oscillator frequency if the bounce period is longer than expected. This is allowed for in the MC14490 for example. Ultimately though, no technique will be 100% perfect with any old switch you happen to have lying around. The first thing you need to do is select a switch that satisfies your mechanical and aesthetic requirements, then test several of them multiple times to get an idea of how much bounce you have to deal with.
A 2N7000 MOSFET requires more attention than a CMOS Schmitt trigger, because there is no hysteresis. Even so, the circuit shown should work well if the amount of contact bounce is relatively small (lasting for around 10-20ms or so). If your switch has a longer bounce duration, increase the value of either C1A and/or R2A. Capacitor current is limited by the forward resistance of D1 in both circuits.
If you use a CMOS Schmitt trigger there are also only three essential parts, with another two if very robust ESD protection is necessary (shown later). Two resistors, one diode and one capacitor are needed for the de-bounce circuit. The values of the resistors and caps aren't especially critical, but those shown worked well with a miniature SPDT pushbutton that I tested. You do need to be aware of the delay when the switch is closed or opened. Expect closing to be around 30ms, as it has to be long enough to ensure that glitches are suppressed. R1A/B provides contact wetting current when the contact is closed, at a peak of around 5mA with a 5V supply. There's also a delay when the switch is released, and it will be about 20ms after the last bounce as the contacts separate.
Both circuits work the same way. When the push-button is pressed, the peak available current charges C1 (A or B) almost instantly, and it can only discharge via R2. This gives a time-constant of 15ms, which allows for a considerable drop-out period during contact bounce. Both circuits will maintain a low output (button pressed) for about 10ms after it's released. For anything manually operated, this can be extended by increasing the value of R2 (500k or more is quite alright). The 2N7000 circuit may still be troublesome because there's no hysteresis. The peak charging current is limited by the diode, and with a 1N4148 that's around 2Ω at 800mA, but the worst-case peak current will be under 0.5A
ESD protection may be required if the pushbutton is outside the chassis, perhaps on long wires (see Section 4). If everything (including the pushbutton) is inside the same case/ chassis, then protection isn't required. Of course ESD protection does no harm, but it's extra parts that you have to buy and they take up space on a PCB.
The amount (and duration) of contact bounce is dependent on the size of the switching mechanism. A large moving mass (comparatively speaking) will have more bounce than a smaller one simply due to inertia and rebound. You might expect that miniature panel mount push-buttons would be better than a toggle switch, but that's not always true.
If you'd rather have the switch grounded (and this is the preferred way to do it), then either of these circuits will do the job. The output is normally low, and pulses high when the button is pressed. The feed resistor needs to be a higher value, and when power is first applied there will be an 'unexpected' switch closure as C1 charges. Following circuitry needs to be set up to ignore any input for perhaps 100ms after power is applied.
In most cases, contact bounce doesn't extend beyond around 10ms, but it can be much more for some switches (anything up to 40ms is entirely possible). Where severe bounce is expected, you may be better off using a 'set-reset' flip-flop, generally made up using a pair of 'OR', 'NOR', 'AND' or 'NAND' gates.
When the switch is in it's 'normal' position (NC contacts closed), R1 is grounded and the logic levels shown are in effect. When the switch is turned on, the very first transient closure of the NO contacts causes the latch to change state, so the Q output will go low and the -Q output will go high. Once a condition has been set, the condition of the latch cannot change until a signal is applied to the other input (reset). The two outputs are complementary, so you can trigger your circuit using either the positive or negative-going output (the logic transitions are shown in the output labels).
You can see that the first transition of the green trace (-Set) forces the 'Q' output high, and nothing that happens subsequently makes a difference. Likewise, the first transition of the blue trace (-Reset) pulls the 'Q' output low, and that's unaffected by additional transitions (bounce). Once either input has been pulled low, the state of the flip-flop latches that, and the only way for the circuit to change state it to pull the other input low. It's completely immune from the effects of contact bounce. Note that I've shown momentary contact only - normally the contact will be 'solid' after the bounce period.
I've shown 1k resistors, which is probably much lower than you may see elsewhere. With few exceptions, switch contacts are expected to pass a 'reasonable' current, and somewhere between 1mA and 10mA is usually sufficient to ensure that the contacts really do 'make' properly. If the current is too low, you may discover that the signal isn't at the full 5V or ground, but is intermediate and variable. Alternatively, it may take longer then expected before you get a solid signal. The reason for this is that an insulating oxide layer can form on the contacts, and at least some voltage and current are needed to ensure that the oxide is broken down allowing current flow. Gold contacts generally don't have this problem because gold doesn't tarnish.
Contact bounce is a repetitive sequence of connections and disconnections, but with a SPDT switch as shown in Fig. 2.3, a disconnection means the contact is floating - it does not mean that the terminal receives a reconnection to the opposite polarity. Switches are almost always break-before-make, so cross-connections don't happen (unless the voltage and current are too high for the switch, meaning you have a real problem!).
The benefit of the S/R flip-flop is that it will usually trigger at the first impulse, and successive impulses have no effect. That means that there's almost no time delay, unlike the timer-based solutions described above. The 'zero delay' works in both directions, so both 'Set' and 'Reset' are as close to instantaneous as the switch will permit. It's important that both inputs are never at the same voltage at the same time, as this results in an unstable (disallowed) state. The transition time of a switch depends on its size and moving mass. This isn't something that most people are aware of, but there is a period when neither contact is closed. Not surprisingly, small switches will have a shorter transition than large switches with a heavy moving contact. The transition time can be up to 4ms for some switches, but can be as little as 1-2ms. This has received scant attention on the Net which I find a bit strange, because it can be important.
Something else that no-one seems to mention is that an S/R flip-flop will require something to ensure that it always starts from a known state. Most will have a 'preferred' state when powered on, due to slight circuit mismatches. However, that could leave the Q output either high or low. Adding a capacitor will force it to start from the same state each time the circuit is powered on. With the switch as shown the issue is forced because the switch grounds the 'reset' line(s), but there may be situations where each contact is momentary. If that's the case, use a 10nF cap to ground from the reset input.
The NO and NC contacts were joined, so the only time the voltage is at zero is when both contacts are open. I ran a number of tests, and Fig. 2.5 is a reasonable average. There's a significant difference depending on whether the button is pressed or released. The long period (upper trace) is pressed, the lower trace is released. For a couple of tests I saw the transit time reach 10ms with a very occasional extension to 100ms (yes, really), so you do need to consider that both contacts are open for that long in some cases.
Given that the switch itself is very small, I'm surprised that it could take so long for the moving (i.e. common) contact to be floating (open circuit). Bear in mind that this is one example of one type of SPDT switch, and they will all be different from each other and for each test. The contact bounce periods are also visible on the two traces. These were by no means the worst, but they were also not the best I saw. I tested another identical switch that had never been used, and it showed equally erratic timing and much the same contact bounce characteristics.
The MC14490 is a hex 'contact bounce eliminator', made by OnSemi. It's a fairly complex IC, but also very capable. The delay between getting a 'clean' output from the switch and an output from the IC depends on the clock frequency (it has an internal clock generator). In most cases (especially DIY), this level of complexity (and cost) isn't needed. For μControllers, you may consider a software routine to be 'better', rather than 'old fashioned' analogue solutions. You may also be disappointed!
One switch I've tested fairly extensively is shown below, both complete and dismantled. The tiny disc is the contact, and it has such a low mass that there is usually no bounce at all, but occasionally you will see a small 'disturbance' as the contacts close. Opening is usually completely 'clean' - I've not seen any bounce when the button is released. These are very common in modern electronics, and it's not hard to see why. They are cheap, and seem to be very reliable. However, if these switches are used with a μcontroller, de-bouncing is still necessary.
The (almost) complete lack of any contact bounce makes them ideal for 'man-machine' interfaces, and only a basic (and with a very short delay) de-bounce circuit is needed to get clean switching every time. Obviously, you must run your own tests to verify that the switches you have perform the same as the ones I have. With so many suppliers you can't count on them all being the same. The general principle still holds good though - the lower the moving mass, the less contact bounce you're likely to see.
At the other end of the spectrum, avoid large ('full-size') toggle switches, because they have a high moving mass and most show prolonged bounce times. Some switches will provide a reliable, bounce free break, but others do not. Nothing is guaranteed in the wide world of switches because they are so diverse. Even switches of the same type and from the same manufacturer can be different, and as noted earlier, no two bounce patterns will be the same - even with the same switch.
Of all the switch types I've looked at, the mini tactile switches as shown in Fig. 3.1 are the best candidates for minimum bounce, but are certainly the worst choice if users expect a large button they can hit with a clenched fist - think emergency stop buttons as an example. The final selection will always be based on the purpose of the switch and they way it will be used.
In some cases you may find that a switch without 'snap' action gives cleaner make and break action, and a couple I tested had zero bounce, but not 100% of the time. I saw clean pulses (make and break) probably 90-95% of the time, but that's not good enough. When you need 100% reliability, 95% is not even close, so de-bounce circuitry is still a requirement. A lot of different switches were checked during the compilation of this article, and I didn't find a single one that was 100% bounce free.
There are as many techniques for ESP protection as there are designers. One popular method is to use TVS (transient voltage suppressor) diodes, which are very fast and can dissipate a large energy spike. Zener diodes are less popular these days, but they have the advantage that they are easy to get, and most people will have a few values in their parts drawers. With a well-defined breakdown voltage, adding a series resistor to limit the peak current provides a low-cost but robust solution.
In most cases the timing capacitor will provide enough protection to ensure reliable operation, but if the push-button or other switch is outside of the enclosure on a lead, I recommend that you add the resistor and zener diode network between the timer and the MOSFET's gate or CMOS input. A large transient could easily cause the destruction of sensitive circuits without protection. The zener is shown as 5.1V, but if your supply voltage is higher, use a zener to suit (typically 10V, 12V or 15V).
A TVS diode is also shown, along with a ferrite bead (high impedance at high frequencies). The resistor may or may not be included, depending on how brave you are. I prefer the zener diode, but for various reasons many designers like TVS diodes, which may be unipolar (like a zener) or bipolar as shown. The advantage of TVS diodes is that they can withstand a greater overload without failing, but their breakdown voltage is less well-defined. A MOV (metal oxide varistor) is another way to protect the circuit, but they have a poorly defined breakdown voltage. MOVs are often employed along with additional protection when serious voltage spikes are likely.
If you're using a PIC or other microcontroller that's intended to be turned on/ off with the same pushbutton, de-bouncing is essential. Without it, a button-press can leave the circuit in the off state, turn it on then back off again, or it may seem to refuse to turn off unless you press the button 'X' number of times until it finally does as it's told.
Software de-bounce almost always relies on a timer or a delay within the switch detection subroutine. This means that you may have to wait for perhaps 50ms before the subroutine detects a 'clean' signal, be it high or low. The delay is rarely a problem, but if the switch closure is a limit switch, you may need to activate the appropriate routine at the first instance of a change of state being detected. The (sub)routine should then ensure that motors (for example) are stopped, and only then return to determine if the closure is valid.
A software failure to stop a travelling mechanical component immediately when a limit is detected may result in damage to the equipment. There are so many possibilities that I can't even begin to cover them, so it's up to the hardware and software people to collaborate to get an outcome that's satisfactory.
An alternative that works well if you have two microcontroller pins available is a software version of Fig. 2.2. The switch will be a SPDT type with a pull-up resistor for each controller pin, and the software is configured to detect a low on one pin or the other. Detection is instant, because the very first closure (however brief if the processor is fast enough) will cause the internal 'state machine' to switch over. It cannot be switched back until the first pin is disconnected and second pin is pulled low. The first pin is assured to be either high or floating (which amounts to the same thing), because the two states can't exist simultaneously.
The following is pseudo-code, produced by ChatGPT. I make no representations for its accuracy or otherwise, but it's included to give you an idea of what is required to de-bounce a switch. Somewhat predictably, I'd go for one of the (simple) analogue techniques shown above because there is no penalty imposed on a microcontroller. If you have an already large program, adding the de-bounce code may mean it won't fit into available memory after it's been compiled, or it may impose unwanted 'wait states' that cause the program or whatever it's controlling to appear erratic.
# Define constants
DEBOUNCE_DELAY = 20 # Set the debounce delay in milliseconds
# Initialize variables
switch_state = read_switch() # Read the initial state of the switch
last_switch_state = switch_state
last_switch_time = current_time()
# Main loop
while True:
# Read the current state of the switch
switch_state = read_switch()
# Check if the switch state has changed
if switch_state != last_switch_state:
# Update the time when the switch state last changed
last_switch_time = current_time()
# Check if enough time has passed since the last switch state change
if (current_time() - last_switch_time) > DEBOUNCE_DELAY:
# Update the last switch state and perform the desired action
last_switch_state = switch_state
if switch_state == HIGH:
# Switch is pressed
perform_action_on_switch_press()
else:
# Switch is released
perform_action_on_switch_release()
# Optionally, add a small delay to avoid continuous checking and reduce CPU usage
sleep(small_delay)
This is a fair representation of the processes involved. It's not particularly efficient though, and assumes that the switch routine is the main program. Using this as a subroutine would probably be ill-advised. As shown, it's a continuous loop and assumes that the processor has nothing else to do. The above routine is very basic - read the switch state, and if it's changed, wait for a few 'small delay' and check it again. If the 'new state' is different from the 'old state' after the de-bounce delay has expired, it's assumed that the switch has changed and the status is updated. If the delay time is inadequate, an incorrect initial reading is still possible, typically not recognising the new state because the final check is during a bounce (open circuit) period. As we've seen from a variety of switches, 20ms may not be long enough with some of them. Because it's a continuous loop, the state change will be picked up the next time around. All rather inefficient though.
Using interrupts improves processor utilisation, but results in more complex code ...
# Define constantsDEBOUNCE_DELAY = 20 # Set the debounce delay in milliseconds
# Initialize variables
last_switch_state = LOW
last_switch_time = current_time()
# Function to handle switch press
def handle_switch_press():
# Perform action on switch press
perform_action_on_switch_press()
# Function to handle switch release
def handle_switch_release():
# Perform action on switch release
perform_action_on_switch_release()
# Interrupt service routine (ISR) for switch changes
def switch_isr():
switch_state = read_switch()
# Check if the switch state has changed
if switch_state != last_switch_state:
# Update the time when the switch state last changed
last_switch_time = current_time()
# Check if enough time has passed since the last switch state change
if (current_time() - last_switch_time) > DEBOUNCE_DELAY:
# Update the last switch state and perform the desired action
last_switch_state = switch_state
if switch_state == HIGH:
# Switch is pressed
handle_switch_press()
else:
# Switch is released
handle_switch_release()
# Set up interrupt for switch changes
setup_interrupt(switch_isr)
# Main loop (program to perform desired tasks)
while True:
# Your main loop code here
do_primary_tasks()
Setting an interrupt is far more efficient, but it also requires more code. The above was ChatGPT's response to my asking for interrupt-driven pseudo-code. I was a bit surprised that AI was able to write what looks like reasonable code. Note that it really is pseudo-code, and is not intended to represent any 'real' language. If you were to ask for an interrupt-driven routine in (say) C#, you'll get real code, but whether it really works or not could only be determined by loading and compiling it. Again, it's possible that the routine could mis-read the state of the switch
The circuits shown are a small subset of the many that have been published. Some are simple and work well, others are overly complex but work well, and a few may not work at all. Contact bounce has been the curse of logic circuits that are expected to do 'something' when a button is pressed from the beginning of digital processing. While mini tactile switches may test ok, you have to ask yourself if you feel lucky. When new they might well be fine, but will that continue for the life of your project?
You will find that some switches give a clean break every time, so you could consider setting up your circuit to react to a contact break rather than a make. However, there must be a 'make' at some point so a break can be detected, so this is not a realistic solution.
Unfortunately, simulations of contact bounce are difficult, because you must be able to create at least a pseudo-random bounce waveform (you can use a noise generator if your simulator supports it), but the tests are still difficult to set up. So much so that it's often easier to head to the workshop and build the circuits and run 'real life' tests. Your solution may still be specific to a particular type of switch, because as shown in the scope captures in Section 1, the range of bounce periods is extreme.
Of course there are many situation where we really don't care if the contacts bounce or not. A relay turning on an amplifier (e.g. as used in Project 39 inrush limiter) doesn't care about contact bounce, and countless pieces of equipment use 'ordinary' switches with no ill-effects. This all changes when some logic circuits are used, especially if a counter is involved. No-one wants a counter thatshould advance by one count when a button is pressed to advance by ten (or more) counts. A logic-based input switching system is one possibility - see Project 163 (Preamp Input Switching Using Relays) for examples of switching systems, many of which have de-bounce circuitry included.
Regardless of the method used for de-bouncing contacts, it's inevitable that the action is delayed. This is of no consequence if the switch is manually operated, because a delay of (say) 50ms is too fast for us to register. Even if we did notice, it's no different from us having pressed (or released) the button 50ms later than we did. However, there will be situations where this delay may cause a problem. An example is a limit switch on a high-speed machine. If part of a machine travels at 10m/s (which is pretty fast), it will travel 500mm in 50ms. That much delay for a limit switch could cause a major failure. In that case, you'd be better off using a photo-interrupter to indicate that the limit has been reached (I'm not sure how quickly you could stop something travelling that fast though!).
Engineering requires compromises, so you need to determine how long you can afford to wait for a button-press to make something happen. As noted, if it's a manual function, then a short delay is of no consequence, but if the user can detect the delay s/he may not be happy. In some cases you may be able to use a switch that has very little (if any) bounce, such as the mini-tactile switches described above.
Most of the circuits shown are simple applications of basic principles. Switch contact bounce is (and always has been) a problem, as s quick search will reveal. The fact that dedicated ICs have been produces shows how important it is. The following is a small sample of the information you'll find if you search.
Main Index Articles Index |