Debounce Code

Go To Last Post
31 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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?

Last Edited: Sun. Oct 29, 2017 - 01:00 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"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]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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?...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

Leon

Leon Heller G1HSM

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

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

Yes.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

 

http://www.avrfreaks.net/comment...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

@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)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

 

  • Ask in one thread.
  • 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.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"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]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

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.

'This forum helps those who help themselves.'

 

pragmatic  adjective dealing with things sensibly and realistically in a way that is based on practical rather than theoretical consideration.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@diogofvc

 

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

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

Topic locked