ESP8266 - Pushbuttons, debounce & how to easy debounce story - Page 1
Forum section: electronics / general

author: TJ232
author_rank: Frequent Contributor
timestamp: March 31, 2015, 07:33:23 am
content: What is your favourite technique and what do you prefer to use in your projects?Below you can see and read about a short experiment with ESP8266 CBDB Board and pushbuttons play or how to use a First order Low Pass Filter combined with Interrupt Trigger on falling/rising edge technique to obtain a very clean response over a broad range of key pressing speeds.Linkhttp://www.esp8266-projects.com/2015/03/buttons-pushbuttons-and-debouncing-story.htmlVideo

author: hamster_nz
author_rank: Super Contributor
timestamp: March 31, 2015, 10:01:46 am
content: When it comes to human interaction I like to do my debounce in software, by having an interrupt on a timer and waiting for a suitable number that differ from the and are in agreement before acting on it. It trades a word of RAM for a few less bits on the board, and can be tweaked without lifting a soldering iron.A case could also be made for this being better for low power designs - in the ISR you can turn the pull-ups on, do a tiny bit of work (maybe update a tick counter), check the input state, and then turn the pull-ups off, all in under a microsecond - but of course if you don't have a need for a timer then sleeping while waiting for an interrupt on change of the port is probably better.You have the option check the input less frequently when no activity has been seen for a few seconds, reducing the number of CPU cycles burnt looking for input in the ISR.

author: ajb
author_rank: Super Contributor
timestamp: March 31, 2015, 10:12:23 pm
content: Once you debounce in software you're halfway to doing short vs long press detection (such as for fast scrolling through menus or secondary button functions), so software makes a lot of sense.

author: digsys
author_rank: Unknown
timestamp: March 31, 2015, 10:35:16 pm
content: Never understood s/ware debounce. Seems such a waste of processing time and memory. I have always used filter caps, which I select togive app 4x the max response rate I require .. after all it's just a human pushing the buttons. Why would I need to know the 200 noiseglitches on make / break at nS / uS accuracy ?? The ol' cap has never failed me.

author: TJ232
author_rank: Frequent Contributor
timestamp: April 01, 2015, 04:18:45 am
content: Quote from: digsys on March 31, 2015, 10:35:16 pm

author: Kjelt
author_rank: Super Contributor
timestamp: April 01, 2015, 08:25:39 am
content: Quote from: digsys on March 31, 2015, 10:35:16 pm+1I try to keep everything <1ms away from the micro as much as possible, why waiste good cycles when a cheap component can do it for you.Keep the non-relevant information as much as possible away from your code at the end you probably need the spared bytes or cycles anyway for much more relevant things. That said, when you have multiple buttons a keymatrix with row/column scanning makes sense but then the scanrate should be slower as the bounce.

author: Marco
author_rank: Super Contributor
timestamp: April 01, 2015, 02:16:55 pm
content: If you have a high'ish frequency timer interrupt to begin with then it doesn't really add anything.

author: Jeroen3
author_rank: Super Contributor
timestamp: April 01, 2015, 02:52:07 pm
content: If you need debouncing it means your pushbutton are connected to an interrupt. And interrupts should be exclusively for inter-ic communications to prevent issues. So you'd need extra hardware, which costs money and board space. Instead of that, reading a key is done every 20 ms. Which is plenty for user-interacted-actuators. Measure the down-time of the key, in x*20ms, and you can do some filtering on press times.A single event is a press-and-release with 2 to 15 times 20ms.A hold event is more than 20 * 20ms. Which is used to increment values automatically. The event is fired repeatedly.Depending on the application usage of the key, a long hold event may be enabled, with a down-time of several seconds.This all can be run from either a single thread, interrupt routine, or call from super-loop. With a for-loop and a settings struct, so the "module" is usable in ALL future projects with similar hardware.A human does not need sub-milliseconds interaction with hardware, so attaching buttons to interrupts is useless. ( except for wake-up purposes )

author: TJ232
author_rank: Frequent Contributor
timestamp: April 01, 2015, 04:08:42 pm
content: Quote from: Jeroen3 on April 01, 2015, 02:52:07 pmInteresting concept, can you elaborate more how a "super-loop/for-loop" setup can be better and use less resources that a interrupt driven one? to make it easier let's suppose it's a low power one, battery & solar powered. I'm really looking forward to see some comparative data. How will look your for-loop routine in a RTOS environment?

author: Jeroen3
author_rank: Super Contributor
timestamp: April 01, 2015, 05:22:22 pm
content: How a "super-loop/for-loop" setup can be better and use less resources that a interrupt driven oneThe superloop requires an interrupt to restart, because a superloop will end __wfi or with sleep modes. It won't bemoreefficient under normal circumstances.A rtos implementation is equal to an reentrant interval-isr, it is only looped infinitely each time the sleep-api expires. A superloop is about the same, an reentrant routine is called when the last execution time is 20ms ago. The advantage of an rtos is that your routine does not need to be reentrant. But an rtos in very lower power stuff is usually unnecessary overhead.When you're not on very-lower-power constraints, consider using the arm systick to increment a global time variable every 1 ms. Or when if(>) are difficult, decrement-saturate a number of software timers and compare boolean. This makes software more portable.In a typical low power application the hardware wakes up sometimes anyways, doing RF, sensors or other communications or display. If will be very fast to compare an input register of GPIO to an known mask to determine if further action is required regarding user requests.If the main chip only wakes up when a button is pressed, as in a remote control, the interrupt is only used to wake up the chip. Make sure to add debouncing logic externally because a low level of significant time is required to successfully wake up any micro. Erroneous behavior might occur when this low level is not long enough. Read the errata sheets before using such wake-up features.

author: TJ232
author_rank: Frequent Contributor
timestamp: April 01, 2015, 07:13:12 pm
content: Quote from: Jeroen3 on April 01, 2015, 05:22:22 pmSo, basically you agree with my opinion that a mix of hardware debouncing + button event subroutine is more desirable than a full software approach as exemplified for example by hamster_nz.I am curious to hear about different approaches especially because I have meet a lot of app engineers ready to write/ask for the most sophisticated functions to avoid a poor man RC filter or even a plain simple Capacitor

author: T3sl4co1l
author_rank: Super Contributor
timestamp: April 01, 2015, 07:30:18 pm
content: Whether it's single level (one bit binary) or multilevel (ADC) data, it's always best to filter in both analog and digital domains. The filtering for an analog signal might need to be more particular (specified cutoff, overshoot, etc.), but for debounce it can be pretty crude (a single RC with a time constant a bit longer than the expected bounce period).What I like to do in digital is use a four bit shift register, and majority voting to change an R-S flip-flop (in VHDL, if (shift + shift + shift + shift == 3) then output <= '1'; elsif (shift + shift + shift + shift == 0) then output <= '0'. Which can be delayed by one additional clocked D-f/f to provide edge detection (if (output == '1' and outputdly == '0') then... etc.).Such a debounce will respond imperceptibly quickly if the clock rate and time constant are on the order of 1-5ms, and so solidly that a contact wire can be dragged along a rusty panel and the intermittent signal will either be ignored or detected properly.Tim

author: Jeroen3
author_rank: Super Contributor
timestamp: April 01, 2015, 08:30:16 pm
content: Quote from: TJ232 on April 01, 2015, 07:13:12 pmI'm also curious to software that is capable of reading double or triple keypress events. I've never put much thought in it myself.It's typical to always have an RC filter on your switches to prevent glitches. Or worse on vibrating devices with damaged buttons. Industrial panels tend to lack maintenance, even when damaged, and vibrate heavily. True stress test for debouncers.ADC multiplexed keys lack dual-key operation. And I did once implement the 20ms read trick with a single 32 bit shift register in software and counting the amount of consecutive 1 bits. Fully 1 is a hold-key, obviously.

author: SL4P
author_rank: Super Contributor
timestamp: April 01, 2015, 09:09:30 pm
content: So, for a number of buttons - or a key matrix, you guys would put a load of RC debounce pads?I can't think of any time in the last ten years that I've used RC debouncing, except on non-logic contacts (power, input or output signal path etc...)As said above, SW debounce is relatively simple - allowing reconfiguration, press-duration timing, inversion etc dynamically with zero hardware revisions...?!

author: mrkev
author_rank: Regular Contributor
timestamp: April 01, 2015, 09:26:40 pm
content: When using uC, most people use loop in main program that sweeps over buttons. There is nothing easier than wrote it the way that after one button was pushed, it's not gonna detect another push for x times that loop is passing through. And fordouble-clicks, it's really not that hard to just use this dead-zone after first push to eliminate ringing, wait for the release and then just time the gap until another push...

author: electr_peter
author_rank: Unknown
timestamp: April 01, 2015, 09:44:09 pm
content: SW and HW debouncers do the same function, literally. HW can provide other functions as well at the same time.RC + schmitt trigger in HW has equivalent in SW. Preferably use polling method, because bad switch bounce can create too many interrupts and create havoc in timing.In ideal world or very harsh conditions, HW+SW debouncer could be used. For mild or moderate conditions, SW solution provides more flexibility because debounce can be easily tuned to suit user input requirements and switch debounce timing. HW solution requires adjustment of values each time.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: April 01, 2015, 11:46:22 pm
content: Quote from: SL4P on April 01, 2015, 09:09:30 pmScanning a matrix doesn't always have the time to filter for debounce (indeed, the scan time per position might be less than the typical bounce period, so that bounce waveforms will technically become aliased -- a messy situation indeed!), but some filtering (and ESD protection!) is always welcome, especially when you consider the RF susceptibility of a row of naked logic inputs -- under the influence of ambient electric fields or RF conducted along cables, who knows what kind of voltages might pop up there! (As for ESD, membrane types are usually pretty good -- they're behind a nice thick layer of plastic film, able to hold off pretty serious voltage. But after some wear and a few million cycles, you might start getting direct strikes from charged fingers, so for long life products, you still want to keep that in mind.)The additional filtering can then be implemented digitally, turning the array into a vector of button states and using a delay-and-voting filter on each bit. You should also add a disambiguation function, that either freezes the button state while multiple presses are detected, or sets everything to zero, or ignores further changes until all buttons are cleared.Tim

author: David_AVD
author_rank: Super Contributor
timestamp: April 02, 2015, 02:04:27 am
content: I always put a small R/C filter on each switch input. It kills off any RF that the wiring may be picking up and smooths out the switch contact bounce at the same time.My usual switch scan rate is every 50ms with that time extended upon detecting a valid press. That seems to lock out any wobbly presses from the user.

author: wraper
author_rank: Unknown
timestamp: April 02, 2015, 02:22:23 am
content: I like this one, it's ultra robust. It works even if input never stabilizes and consists of never ending bounce.Quote

author: wraper
author_rank: Unknown
timestamp: April 02, 2015, 02:34:53 am
content: I could easily achieve 40+ 100% bounce free presses in a second with this method. Mostly tested with signal generator giving out bouncy crap because it's tough for the fingers to press that fast

author: rx8pilot
author_rank: Super Contributor
timestamp: April 02, 2015, 02:54:33 am
content: I have been using RC+Schmidt trigger in HW for debouncing. I am not saying its the best. It was chosen for two reasons.1: The system needs to be very reliable and I did not want the chance of a CPU cycle hog messing anything up.2: My coding skills are modest so I did not trust myself to stay out of trouble. I have been focusing more and more on software so I may try some SW techniques outside of a production design.My current project has 3 8bit AVR's that are all fairly timing sensitive and already more busy than I would like.

author: Kjelt
author_rank: Super Contributor
timestamp: April 02, 2015, 10:37:53 am
content: Some of these debouncing algorithms take up quite a few cycles, besides that you keep on scanning the button(s) each x ms probably calling a function (everything on the stack and back) taking up again unnecessary cycles.When does a user press a button, perhaps 0,00001% of the lifetime of the product.So reserving just a single hw (rc filter) debounced interrupt for flagging a potential keyaction and in that interrupt just set a software flag that the key(s) should be polled for some time can have benefits IMO.

author: Jeroen3
author_rank: Super Contributor
timestamp: April 02, 2015, 11:34:04 am
content: Quote from: Kjelt on April 02, 2015, 10:37:53 amThe 20ms read interval should not. It takes 0.004% of cpu time on a 8 MHz ARM cortex m3? (600 cycles for 8 buttons)Should be a little more on M0, but still sub-percentage numbers.If you are tight in 100 counts of cycles you have the wrong chip.

author: mrkev
author_rank: Regular Contributor
timestamp: April 02, 2015, 01:56:18 pm
content: Quote from: Kjelt on April 02, 2015, 10:37:53 amIf you have two buttons that are gonna be rarely pressed and if you are not using ext. interupt pins for anything else, sure...But in many cases, software is not doing much, without input from the user.

author: Kjelt
author_rank: Super Contributor
timestamp: April 02, 2015, 07:37:35 pm
content: And you can go to ultra low power mode for longer times ( than 20 ms), but you can use the same pin you use for scanning as the ext. int. pin, so no extra pin needed.

author: mrkev
author_rank: Regular Contributor
timestamp: April 02, 2015, 08:26:36 pm
content: Quote from: Kjelt on April 02, 2015, 07:37:35 pmSure, everything has its advantages. Anyway, what do you mean by that second sentence? Many uC have just one pin that can be used for external interruption...

author: Kjelt
author_rank: Super Contributor
timestamp: April 02, 2015, 08:30:13 pm
content: Quote from: mrkev on April 02, 2015, 08:26:36 pmThe microcontrollers I worked with till now like the stm8 and arms for instance can have interrupts on most if not all of its GPIO pins.

author: mrkev
author_rank: Regular Contributor
timestamp: April 02, 2015, 09:54:16 pm
content: Quote from: Kjelt on April 02, 2015, 08:30:13 pmWell, here we go again. Everything can be great in a specific application, and everything has advantages/disadvantages... Something that really good solution (like two RC filtered buttons going to ext. int. pins at low consumption device) can be almost wrong solution in other case (trying to fit whole matrix of buttons with RC filters on two int. pin that you have available on your uC)...

author: T3sl4co1l
author_rank: Super Contributor
timestamp: April 03, 2015, 02:12:52 am
content: Quote from: wraper on April 02, 2015, 02:22:23 amThis method is equivalent to the method I detailed above, and similar or equivalent to those others have mentioned. The difference is practically semantic: my exact wording uses more shift registers (exactly N) and less logic (a handful of full adders); the above uses fewer registers (one for the input, and Lg(N) for the state) and more complicated logic (full Lg(N) bit adder/subtractor, plus comparators and mux to implement the saturating arithmetic). A sufficiently powerful compiler/synthesizer should be able to generalize more-or-less the same logic from either method, although I don't know if they are quite *that* powerful yet.So as you can see, it's a pretty good way to do it.Thanks to the Lg(N) state, and relatively modest logic requirement (loads of combinatorial logic often come for free, e.g. the huge macrocells of a CPLD, or the word-sized addition and conditional statements of software programs), this implementation is much better suited to large N, which through many variations, might be used for debouncing, timers, delay/phase shifter chains, missing pulse detectors, etc.For the small N counts used for simple debounce, it's not usually worth it, but there might be reasons to do it this way regardless. For example, if your processor has SIMD "packed" instructions, you can do a whole pile of these additions and stuff at once. (True SIMD instructions often use saturating arithmetic anyway, so you don't even have to implement that, it comes for free!) Probably not likely to be relevant on a microcontroller, but a possibility to be aware of.Tim

author: T3sl4co1l
author_rank: Super Contributor
timestamp: April 03, 2015, 02:17:28 am
content: Quote from: mojo-chan on April 02, 2015, 09:30:26 amThat's a poor way to do it, because humans can press buttons way faster than 10Hz, and see responses much faster than 100ms. You'll have buggy-feeling, laggy, sloppy interfaces doing it like that.I would say 30Hz is an absolute minimum (which is also the minimum speed of most video games), and 100-200Hz (which allows for suitable filtering down to an equivalent 50-100Hz bandwidth) as recommended.Tim

author: Kjelt
author_rank: Super Contributor
timestamp: April 03, 2015, 08:09:56 am
content: Quote from: mrkev on April 02, 2015, 09:54:16 pmOh absolutely, no argument about that.