## Debounce Code

31 posts / 0 new
Author
Message

Hello. Usually when I need debouncing, I just add a delay for some period of time. I came across an article yesterday that implemented code to do the debouncing. I was wondering what you all do while debouncing. Do you implement code, or use hardware or both? I am wondering what different methods there are for debouncing?

-Amrit

Last Edited: Sun. Oct 29, 2017 - 01:00 PM

There are as many different methods as there are people trying to debounce.

My favorite is to have a timer running at about 1 KHz. I usually use this for any other timing odd jobs besides debouncing I may need.

Every other interrupt I read the switch and shift in its value (1 = closed, 0 = open) into an unsigned volatile char. Then anywhere else in the program at any time I can check that variable. If it's 0xff, the switch is closed and debounced. If it's 0x00, the switch is open and debounced. If it's anything else, the switch is in transition.

The 8 bit shift at 500 Hz means the debounce time is 16 ms, probably considerably longer than needed, but it usually works fine for me.

Chuck Baird

"I wish I were dumber so I could be more certain about my opinions. It looks fun." -- Scott Adams

http://www.cbaird.org

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

zbaird wrote:

Every other interrupt I read the switch and shift in its value (1 = closed, 0 = open) into an unsigned volatile char. Then anywhere else in the program at any time I can check that variable.

I like that idea.. haven't seen it before.

I use a similar method. Initialize an uint8_t to 0x7f. On a fixed period, read sw: 1=count up, 0 = count down with limits of 0x00 and 0xff. If the count isn't 0x00 or 0xff, the switch is in transistion.

That is indeed a very straightforward method for a newbie. In practice I think the more parallel methods that we've discussed in the past would have some advantages in size, speed, and flexibility. [Bob likes to start with Mega32 and up; I end up with many/most apps fairly well packed into a Mega48 or '88.]

In some apps, 8 stages are just plain too much. [That is rare in practice and doesn't matter for buttons/switches but can be important for e.g. flowmeter pulses.]

My parallel debounce ends up with rising and/or falling edges--new presses and releases--as a byproduct of the debouncing mechanism. With the described method there would be an extra pass with "previous".

It is rare for me to have 1 or 2 inputs to the debouncer. Most times it is 4-8; sometimes an additional 4-16 inputs; 12-16 button keypad is not unusual. With parallel the amount of code and cycles is the same for 1-8 (or 9-16 if word-wide). The only jiggering that needs to be done is the gathering of the new samples which is usually quite short.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

theusch wrote:
That is indeed a very straightforward method for a newbie.
Lee

What I described is basically a digital low-pass filter. It works very well for situations where you have unpredictable bouncing with a periodic wave. One example would be a pressure sensor at the end of a long line with multiple valves opening/closing. Standing waves cause all kinds of weird things in this case. I think the most common "newbie" approach I've seen is a read / delay / read. That doesn't cut it for 100% realiability in the application I just described. I'll have to read some more on the other methods you mentioned. Sounds interesting.

Thanks for all the input!

Chuck, it seems that effectively you are just waiting 16 ms. Why wouldn't you just want to do a 16 ms delay to ensure the debounce is done?

-Amrit

amrit wrote:
Thanks for all the input!

Chuck, it seems that effectively you are just waiting 16 ms. Why wouldn't you just want to do a 16 ms delay to ensure the debounce is done?

Keeping a "running check" on the switch state, such as these techniques do, lets you get a debounced switch result quicker on average, while better handling the occasional pathological case of a switch that bounces for a very long time. This is useful because a given switch can have widely varying bounce times from one activation to another.

Mike

Quote:

Why wouldn't you just want to do a 16 ms delay to ensure the debounce is done?

Because a 16 milliseconds delay wastes 16 ms of useable CPU cycles, whereas an interrupt service routine going in 8 times during 16 milliseconds "wastes" a fraction of a millisecond total? (Assuming AVR running at 1 MHz and that every ISR activation takes say 50 CPU cycles that would be 400 microseconds. And running at say 8 MHz it would be 50 microseconds.)

Looking at the switch state before and after a 16 millisecond delay in practice means that you are taking two samples. And if the switch actually has a long time bouncing, longer than 16 milliseconds, you risk seeing two identical states while the switch is still bouncing.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

This much I understand. But it appears to me that you know exactly what is going on in the debouncing period. But what is you have an unknown number of bounces over an unknown time period. Then how would you do it? From the examples, it seems like most methods assume you already know how it will work?...

-Amrit

Google "Ganssle". He has written the ultimate document on debounce techniques.

Leon

Leon Heller G1HSM

Quote:

Then how would you do it?

The timer interrupt debounce pollers basically work on the principle that when they've seen more 0's than 1's the state is reported 0 and when they've seen more 1's than 0's the state is 1. It doesn't matter how long the bounce takes to settle - this rule will continue to be applied. If the switch has just transitioned from 1 to 0 at some point it will settle and be reported as 0 - however long it takes.

Don't over-think the problem.

Switches bounce, but different switches bounce differently. Some are hardly noticable. For many applications, simply polling them every millisecond or so is suficient.

Similar to the idea of low-pass filtering the input to an A/D converter, add a simple series R between the switch and the AVR and a small cap on the AVR I/O pin (NOT ON THE SWITCH!) and set the time constant to some small value like 0.01 - 0.001 second. The series R and C hide most short events from you, and they also serve to reduce ESD hits coming in from the switch.

Do you see why you do not want the cap directly across the switch?

Make sure the resistor (pull up or down) is low enough that you get at least a milliamp into the switch, more if it needs it. (google "wetting current")

Try not to use interrupts, they pretty much guarantee that you'll see every glitch.

Quote:

Try not to use interrupts, they pretty much guarantee that you'll see every glitch.

Just to be clear - you mean "external" or "pin change" interrupts? Obviously most debounce schemes do use a timer interrupt.

Perhaps Atmel should implement a configurable debounce in micro code. In the AVR world of highly integrated parts, what's one more configurable alternate function?

Several functions do have "spike rejection", with like 4 clock cycle "debounce". Another reason for you slow-AVR fans to run at 32kHz and waste power. ;)

As Dave mentioned above, most real-world signals are going to have a series-R for protection. Implementing in microcode may not address all conditions. How many "channels" of this would you put on, say, a Mega88? I've got some Mega48/88 apps with 16 debounced inputs. So put it on all pins like pinchange? Then everyone always has to pay for it, even on apps with 0-3 such signals?

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

clawson wrote:

Just to be clear - you mean "external" or "pin change" interrupts? Obviously most debounce schemes do use a timer interrupt.

Yes.

theusch wrote:
So put it on all pins like pinchange? Then everyone always has to pay for it, even on apps with 0-3 such signals?
Yup. Just like apps that have a use for 0-3 pinchange i/o pay for 24 of them.

Debounce is actually a likely alternate/exclusive function to pinchange. microcode would detect the pinchange condition, determine elapsed time from the previous pinchange, compare to a debounce period, and update the result to the PIN register.

Class88 wrote:
theusch wrote:
So put it on all pins like pinchange? Then everyone always has to pay for it, even on apps with 0-3 such signals?
Yup. Just like apps that have a use for 0-3 pinchange i/o pay for 24 of them.

Debounce is actually a likely alternate/exclusive function to pinchange. microcode would detect the pinchange condition, determine elapsed time from the previous pinchange, compare to a debounce period, and update the result to the PIN register.

BUT, once steady there are no more changes. So there is no final pin-change to tell you that the state has changed. Hardware debounce is actually quite hard, and because of the timing required, requires large registers. More cost effective to leave this in the software domain, as it is more flexible, and applied only to those inputs that need it. The software approach can also be easily tuned for the application, where the hardware approach cannot.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

Quote:
BUT, once steady there are no more changes. So there is no final pin-change to tell you that the state has changed. Hardware debounce is actually quite hard, and because of the timing required, requires large registers. More cost effective to leave this in the software domain, as it is more flexible, and applied only to those inputs that need it. The software approach can also be easily tuned for the application, where the hardware approach cannot.
Just trying to get some more integration.

I agree a hardware implementation is probably a bad idea. I was proposing configurable microcode - essentially a behind the scenes firmware solution.

It could be done and could be done in a way that would neatly satisfy 90% of debouncing requirements.

I'll retract my uninformed/flippant suggestion on how to do it and I'm not going to guess about the monetary cost or resource burden of implementation. I personally would consider it a useful feature even though I have a number of routines that I use for various applications.

Configurable microcode? Interesting... Where would this microcode be stored? What cpu core would execute it? Are you suggesting the AVR core simply stop and execute code like an ISR for debouncing? I'm not trying to poke holes in your idea here, just trying to understand better what it is that you are suggesting. Unless we're talking about adding a second core here, I don't see how this can happen without affecting the normal execution of code in the AVR.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

glitch wrote:
Configurable microcode? Interesting... Where would this microcode be stored? What cpu core would execute it? Are you suggesting the AVR core simply stop and execute code like an ISR for debouncing? I'm not trying to poke holes in your idea here, just trying to understand better what it is that you are suggesting. Unless we're talking about adding a second core here, I don't see how this can happen without affecting the normal execution of code in the AVR.
Configurable, like via control registers, microcode, like the same microcode that manages all of the Peripheral Features of the device (stored and executed in the same way as the existing microcode is stored and executed).

Do you think there is a separate core for every peripheral feature [Timer Counter, PWM, ADC, USART, I2C, debugWIRE, etc]? That's unlikely.

The microcode managing the peripheral features runs outside of the core resources. Adding a feature in microcode does not affect the resources available to the core that you are familiar with. Nor does it require adding a core.

Personally, I use hardware debouncing (simple RC circuit) when I can. In the referred treatises on debouncing, all or almost all switches are done debouncing by 20 milliseconds. I use a 50 millisecond debounce period for both hardware and software purposes. I would be hard pressed (get it... "pressed") to push a button or flip a switch as fast as 20Hz, so a 50mS debounce is not TOO long, but quite long enough to eliminate most or all bouncing switches.

Also, I have used a debounce chip that includes a pin change output to trigger a uC interrupt. I have used that one once and it works very well. I foget the number of the chip, but I discussed it here in the past in previous debouncing threads.

-Tony

Can you show me your code? I'm making a alarm clock and in set_alarm function I need to increase two variables, minutes and hours

So are you going to go round and wake up all the old threads you can find on debouncing ... ?

https://www.avrfreaks.net/comment...

Top Tips:

1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...

None of the codes could help me so far, I'm trying, sorry if I bothered you

@diogofvc, perhaps if you explained what "None of the codes could help me..." means in terms of what you need, what you tried, and what did (or did not) occur, then we might be able to offer suggestions. Knowing what you have done to solve your own problem gives us insight to where to point you.

David (aka frog_jr)

diogofvc wrote:
None of the codes could help me so far

Why not - what's the problem?

As you yourself have noted, these have been used countless times by many others - so what is the particular problem that you have which makes them not work for you?

As frog_jr said, if we don't know what your problem is, we can't help you solve it!

Have you read Jack Ganssle's article of switch contact bounce & debouncing? - it's linked from the other thread.

Top Tips:

1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...

diogofvc wrote:
None of the codes could help me so far, I'm trying, sorry if I bothered you

The problem with posting about the same thing in several thread (known as "cross posting") is that different persons might put in work doing the same answer in the different threads. This boils down to essentially all but one of those persons have wasted their time on your behalf.

• If you are not entirely sure that your problem exactly matches the subject of an existing thread, then start your own thread instead of attaching a new post to an existing one.

Be aware of the fact that cross-posting is one of the things that irritates forum members the most - not only here but on most all forums. Simply tossing your question out in all places you can find, in the hope that you will get more help, is actually counter-productive. And it will make you look spoiled and screaming out loud for attention.

The best way to get good attention and help is to post in your own thread, and to try to make your question as complete and to the point as possible. "Non of the [existing threads] could help me" is not very clear. State what you have tried. Instead of simply saying "did not work" tell how what you thought you would observe, what you actually observed and how you observed that. If you want to refer to existing threads then link to them.

You are in a competition for attention. If you want to be a winner in that competition then you need to make your question competitive. The quality of the answers and help you get depends to a large extent to the quality of your question.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

JohanEkdahl wrote:

You are in a competition for attention.

You are in a competition for attention and that attention is given by people for free. If you don't interest them, or you annoy them, then they are under no obligation to help you and they will ignore you even if they know the answer to your problem.

#1 This forum helps those that help themselves

#2 All grounds are not created equal

#3 How have you proved that your chip is running at xxMHz?

#4 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand." - Heater's ex-boss

Create a new thread on this topic and post links in that thread to the code you have tried from other threads as opening old threads is going to confuse others.  This way everyone is on the same page.

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman