{"id":281,"date":"2012-09-11T01:00:00","date_gmt":"2012-09-10T23:00:00","guid":{"rendered":"https:\/\/www.fussylogic.co.uk\/blog\/?p=281"},"modified":"2012-10-26T10:48:19","modified_gmt":"2012-10-26T09:48:19","slug":"debounce","status":"publish","type":"post","link":"https:\/\/www.fussylogic.co.uk\/blog\/?p=281","title":{"rendered":"Debounce"},"content":{"rendered":"<p>It\u00e2\u20ac\u2122s been a while since I\u00e2\u20ac\u2122ve had to use this knowledge, but I happened upon <a href=\"http:\/\/hackaday.com\/2010\/10\/13\/open-call-send-us-your-debounce-code\/\">this request<\/a> on Hackaday. It\u00e2\u20ac\u2122s from a few years ago, and so I won\u00e2\u20ac\u2122t be submitting to them; but am inspired enough to write an article about debouncing.<\/p>\n<p>So first, what is \u00e2\u20ac\u0153debouncing\u00e2\u20ac\u009d? More importantly, what is \u00e2\u20ac\u0153bouncing\u00e2\u20ac\u009d in such a way that it needs debouncing? The answer is buttons (amongst other things). In an embedded project you often have a couple of buttons that the user can press to activate various functions. In the would of full computers, the hardware and operating system take care of all the nasty stuff and so you just get <em>key pressed<\/em> and <em>key released<\/em> messages. When you\u00e2\u20ac\u2122re dealing with switches wired straight into a pin on the microcontroller chip, the nasty stuff is your problem.<\/p>\n<p>The nasty stuff in question is that when the button is pressed, the signal doesn\u00e2\u20ac\u2122t simply go from \u00e2\u20ac\u0153off\u00e2\u20ac\u009d to \u00e2\u20ac\u0153on\u00e2\u20ac\u009d, it goes off, on, off, on, off, on, off, on. Imagine this was a button that represented \u00e2\u20ac\u0153next channel\u00e2\u20ac\u009d on a TV remote; if you don\u00e2\u20ac\u2122t process that signal a bit first, you have received four \u00e2\u20ac\u0153next channel\u00e2\u20ac\u009d presses, instead of the one that the user wanted.<\/p>\n<div class=\"figure\">\n<img decoding=\"async\" src=\"http:\/\/hackadaycom.files.wordpress.com\/2010\/10\/debounce-waveform.jpg\" alt=\"Plot of bouncing signal\" \/><\/p>\n<p class=\"caption\">Plot of bouncing signal<\/p>\n<\/div>\n<p>The above plot shows exactly what\u00e2\u20ac\u2122s going on; in this case \u00e2\u20ac\u0153high\u00e2\u20ac\u009d means \u00e2\u20ac\u0153off\u00e2\u20ac\u009d and \u00e2\u20ac\u0153low\u00e2\u20ac\u009d means \u00e2\u20ac\u0153on\u00e2\u20ac\u009d. The two traces are showing, effectively, the same signal.<\/p>\n<p>There are a number of ways that designers of these embedded systems typically deal with this:<\/p>\n<ul>\n<li>Only consider a change valid if it persists for two samples.<\/li>\n<li>Wait for a change; start a timer; after x milliseconds, look again. Only if the two samples are the same is the change valid.<\/li>\n<li>Low pass filters on the inputs.<\/li>\n<\/ul>\n<p>Taking the last of these first. Yuck. You\u00e2\u20ac\u2122re basically smoothing out the sharp edges, the signal changes slowly from A to B as the capacitor in the filter charges or discharges. Throwing hardware at the problem is sloppy. It\u00e2\u20ac\u2122s wasteful of components and board space and is unreliable because the exact values for the filter aren\u00e2\u20ac\u2122t easy to determine in advance \u00e2\u20ac\u201c you need a sample of the actual switch, and some typical button press styles (heavy handed people generate different bounce profiles to light fingered ones). In fact, there is so much variation possible, that it\u00e2\u20ac\u2122s not really viable to pick a filter that leaves the system responsive. You don\u00e2\u20ac\u2122t want the user pressing a button and then having a noticeable delay while the action is noticed. Further, if you slow the response too much, the system will completely miss the button push.<\/p>\n<p>Option one. Easy to implement, but very unreliable. It\u00e2\u20ac\u2122s easy to see why looking at the plot. The bounces don\u00e2\u20ac\u2122t come in nice uniform chunks, and they certainly don\u00e2\u20ac\u2122t arrange themselves to the sample period of your program. So, while this method will get you over some high frequency bounce, it won\u00e2\u20ac\u2122t do a good job in all cases.<\/p>\n<p>Option two. This is the one most commonly used. It works pretty well. You can see why from the trace, after a millisecond, the bouncing has finished and the flat trace means the signal is reliable. There is a drawback: you have to pick a long enough time that <em>all<\/em> possible bouncing must be well and truly over. If we picked one millisecond on the basis of the above plot, what will happen on the day that the bounce continues for 1.5 milliseconds? So, you have to go a bit mad and pick an excessively long timeout.<\/p>\n<p>My solution (although I\u00e2\u20ac\u2122m not claiming I was the first to do it, I\u00e2\u20ac\u2122m just saying that this is the method I picked and have used for years) is a combination of these two techniques. As far as I can tell it is the most reliable and lowest-latency method for debouncing that there is.<\/p>\n<p>Here\u00e2\u20ac\u2122s how it goes:<\/p>\n<ul>\n<li>Wait for a change<\/li>\n<li>Start a timer<\/li>\n<li>If another change happens while the timer is running, reset it<\/li>\n<li>When the timer reaches its end, sample again. That is your debounced signal.<\/li>\n<\/ul>\n<p>The timer in this case can be set very short, it needs only be longer than the longest time between bounces, rather than longer than the total period of bouncing expected. It works because it solves the problem that we never know which is the last bounce, there could always be one more. What we\u00e2\u20ac\u2122re really doing is requiring that the signal maintain a particular state for X milliseconds, before we consider it valid.<\/p>\n<p>This method adapts to light fingers, heavy fingers, cheap hardware, expensive hardware. As long as we pick our X such that it is longer than the slowest possible bounce, we\u00e2\u20ac\u2122ll be fine. Going by the above trace, I think I\u00e2\u20ac\u2122d pick one millisecond.<\/p>\n<p>How would we implement this though? Well, it can be tricky if you need to handle multiple buttons simultaneously, since we have no way of knowing which one would be pressed first, or which one will finish bouncing first. Therefore we need a timer per button.<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">bit button_signal_now[NUMBER_OF_BUTTONS];\nbit button_signal_last[NUMBER_OF_BUTTONS];\n<span class=\"dt\">uint8_t<\/span> button_timer[NUMBER_OF_BUTTONS];\n\n<span class=\"dt\">void<\/span> interrupt_TIMER0() interrupt TIMER0\n{\n    TimerTicks++;\n}\n\n<span class=\"dt\">void<\/span> main()\n{\n    <span class=\"dt\">unsigned<\/span> <span class=\"dt\">int<\/span> i;\n\n    <span class=\"kw\">while<\/span>( <span class=\"dv\">1<\/span> ) {\n\n        <span class=\"co\">\/\/ ...<\/span>\n\n        <span class=\"kw\">for<\/span>( i = <span class=\"dv\">0<\/span>; i &lt; NUMBER_OF_BUTTONS; i++ ) {\n            <span class=\"co\">\/\/ Change of button state resets the per-button timer<\/span>\n            <span class=\"kw\">if<\/span>( button_signal_now[i] != button_signal_last[i] )\n                button_timer[i] = BUTTON_TIMEOUT;\n            <span class=\"co\">\/\/ A timer tick since our last look decrements the<\/span>\n            <span class=\"co\">\/\/ active per-button timers<\/span>\n            <span class=\"kw\">if<\/span>( TimerTick &gt; <span class=\"dv\">0<\/span> &amp;&amp; button_timer[i] &gt; <span class=\"dv\">0<\/span> )\n                button_timer[i]--;\n            <span class=\"co\">\/\/ Store the current state for next time<\/span>\n            button_signal_last[i] = button_signal_now[i];\n            <span class=\"co\">\/\/ If a timer has reached zero, then the button state is<\/span>\n            <span class=\"co\">\/\/ considered valid<\/span>\n            <span class=\"kw\">if<\/span>( button_timer[i] == <span class=\"dv\">0<\/span> )\n                button_state[i] = button_signal_now[i];\n        }\n        <span class=\"co\">\/\/ Acknowledge the tick<\/span>\n        <span class=\"kw\">if<\/span>( TimerTick &gt; <span class=\"dv\">0<\/span> )\n            TimerTick--;\n\n        <span class=\"co\">\/\/ ...<\/span>\n\n    }\n}<\/code><\/pre>\n<p>Ta da. Our timer interrupt handler is small and fast (which they always should be); our handler can cope if a few ticks are missed because something more pressing comes up; and we can handle as many buttons as are needed. I\u00e2\u20ac\u2122ve taken a few liberties with syntax and race conditions for the sake of clarity, but the idea should be clear.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It\u00e2\u20ac\u2122s been a while since I\u00e2\u20ac\u2122ve had to use this knowledge, but I happened upon this request on Hackaday. It\u00e2\u20ac\u2122s from a few years ago, and so I won\u00e2\u20ac\u2122t be submitting to them; but am inspired enough to write an article about debouncing. So first, what is \u00e2\u20ac\u0153debouncing\u00e2\u20ac\u009d? More importantly, what is \u00e2\u20ac\u0153bouncing\u00e2\u20ac\u009d in such\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.fussylogic.co.uk\/blog\/?p=281\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[15,6],"_links":{"self":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/281"}],"collection":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=281"}],"version-history":[{"count":10,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/281\/revisions"}],"predecessor-version":[{"id":876,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/281\/revisions\/876"}],"wp:attachment":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=281"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=281"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=281"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}