Input Debounce
#1
Posted 30 August 2011 - 03:34 PM
#2
Posted 30 August 2011 - 03:45 PM
#3
Posted 30 August 2011 - 06:45 PM
- Rik P. likes this
-- H.L. Mencken, "What I Believe"
#4
Posted 31 August 2011 - 07:02 AM
#5
Posted 31 August 2011 - 06:43 PM
Stefan, you are right about the current peak, but it is very very short in time.
Supposing the switch equivalent resistance around 1 Ohm (it is surely lower), the capacitor will be discharged in less than one microsecond.
Within this short time an overheat is not possible, so nor any switch damage.
It is also valuable your tip about the software debounce filter, but I think it should be already present. Either it has been implemented and it works, or it has *NOT* been implemented and we must create our own.
Anyway, post the code of your solution: it may be useful sometime.
Cheers
I wrote a simple software de-bouncer today and it works great. I am a little surprised that we would have to do this since the glitch filter should provide this capability. I will post my code here tonight.
#6
Posted 31 August 2011 - 07:11 PM
If I remember it correctly, the current implementation of glitch filter on Netduino simply reads the input 3 or 4 times, so the period is a few microseconds (I have not measured how long takes GetPinState() function call, but my guess is somewhere around 3 µs). If you implemented the de-bouncer using polling (i.e. port.Read()), it takes tens of microseconds to execute the managed method, if you used interrupt, then hundreds of microseconds - so it would mean the button produces a lot of bouncing and the firmware glitch filter period is not long enough. For the RC filter, you'd need to calculate the appropriate value of the resistor for desired time constant (100 - 200 µs, or maybe more).I wrote a simple software de-bouncer today and it works great. I am a little surprised that we would have to do this since the glitch filter should provide this capability.
#7
Posted 31 August 2011 - 10:32 PM
public class Program { private static readonly InterruptPort Button1 = new InterruptPort(Pins.GPIO_PIN_D0, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow); private static DateTime Button1LastPushed; public static void Main() { Button1.OnInterrupt += Button1_OnInterrupt; // ... main loop } private static void Button1_OnInterrupt(uint data1, uint data2, DateTime time) { // glitch filter. events within 50 milliseconds of the first event are discarded if (Button1LastPushed.AddMilliseconds(50) > time) return; // Debug.Print("Button 1 Interrupt"); Button1LastPushed = time; // actions on interrupt here } }
Also, Mario, i definitively did read an application note for a microswitch that strongly advised against putting a "naked" capacitor across a switch because of damaging effects. If i can turn it up again (I don't recall where I found it ...) i'll link it here.
Also for the record, if someone wants to do the hardware debouncing "cleanly" it should be probably done like in this article (german text, the schematic should be understandable though) using a RC filter with a schmitt trigger. However, as software debouncing is so easy and doesn't require additional components, i just do that Another useful bit of information in that (german) article is that switches usually bounce for up to 10ms, so the time constants for the debouncing (software or hardware) should be chosing according to that (and no human operates a switch 100 times a second anyway)
- Mark Anderson likes this
-- H.L. Mencken, "What I Believe"
#8
Posted 01 September 2011 - 01:39 AM
static long lastDebounceTime = DateTime.Now.Ticks; static long debounceDelay = 100000; //adjust as necessary public static void Main() { InterruptPort input = new InterruptPort(Pins.GPIO_PIN_D4, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeBoth); input.OnInterrupt += new NativeEventHandler(input_OnInterrupt); } static void input_OnInterrupt(uint data1, uint data2, DateTime time) { if ((System.DateTime.Now.Ticks - lastDebounceTime) > debounceDelay) { lastDebounceTime = DateTime.Now.Ticks; // do stuff } }
Thanks everyone for the help.
#9
Posted 01 September 2011 - 05:18 AM
Also, Mario, i definitively did read an application note for a microswitch that strongly advised against putting a "naked" capacitor across a switch because of damaging effects. If i can turn it up again (I don't recall where I found it ...) i'll link it here.
You weren't wrong. That's surely right for electrolytic capacitors, or relatively high capacitance (i.e. over 10uF).
Since the electrolytic caps are working chemically, and excessive current may overheat the capacitor itself.
For a cap under 0.5uF there's no need of limiting resistor.
I'll take advantage to remember some "must" about the electrolytic capacitors involving enough current:
- never ever reverse polarity;
- never ever apply a voltage above the marked limit;
- never ever use for AC;
- never ever overheat, or expose at temps higher than those marked (may be missing);
- if you feel is warmer than the environment temp, shut immediately the circuit off;
- if you're unsure, keep wearing the safety glasses.
It happened to me many times, and a friend of mine almost was losing an eye.
The Schmitt-Trigger is absolutely the best choice, but it is a hardware pattern. Typically a software filter is preferred, and anyone can write it.Also for the record, if someone wants to do the hardware debouncing "cleanly" it should be probably done like in this article (german text, the schematic should be understandable though) using a RC filter with a schmitt trigger. However, as software debouncing is so easy and doesn't require additional components, i just do that Another useful bit of information in that (german) article is that switches usually bounce for up to 10ms, so the time constants for the debouncing (software or hardware) should be chosing according to that (and no human operates a switch 100 times a second anyway)
From my viewpoint the hardware filter would be better, because it is pretty simple to build, and frees the Netduino from heavy computations. The posted code for debouncing is good, but it takes a lot of time of CPU, compared to the basic task it has to do.
Anyway, all that was a good point to highlight.
Cheers
#10
Posted 01 September 2011 - 08:34 AM
I'd prefer the hardware approach too - once the hardware filter is in the circuit it's there for good and a programmer can't remove it by mistake.The Schmitt-Trigger is absolutely the best choice, but it is a hardware pattern. Typically a software filter is preferred, and anyone can write it.
From my viewpoint the hardware filter would be better, because it is pretty simple to build, and frees the Netduino from heavy computations. The posted code for debouncing is good, but it takes a lot of time of CPU, compared to the basic task it has to do.
Regards,
Mark
Edit: corrected spelling error.
Edited by Nevyn, 01 September 2011 - 08:35 AM.
To be or not to be = 0xFF
Blogging about Netduino, .NET, STM8S and STM32 and generally waffling on about life
Follow @nevynuk on Twitter
#11
Posted 07 June 2013 - 07:01 AM
I set up my software debounce like this:
static long lastDebounceTime = DateTime.Now.Ticks; static long debounceDelay = 100000; //adjust as necessary public static void Main() { InterruptPort input = new InterruptPort(Pins.GPIO_PIN_D4, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeBoth); input.OnInterrupt += new NativeEventHandler(input_OnInterrupt); } static void input_OnInterrupt(uint data1, uint data2, DateTime time) { if ((time.Ticks - lastDebounceTime) > debounceDelay) { lastDebounceTime = time.Ticks; // do stuff } }Thanks everyone for the help.
Some micro optimisation The exact time the interrupt occured is already given, no need to call DateTime.Now.
#12
Posted 03 January 2014 - 01:54 AM
In case someone is searching for this in the future, this is the very simple software glitch filter i talked about:
public class Program { private static readonly InterruptPort Button1 = new InterruptPort(Pins.GPIO_PIN_D0, false, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow); private static DateTime Button1LastPushed; public static void Main() { Button1.OnInterrupt += Button1_OnInterrupt; // ... main loop } private static void Button1_OnInterrupt(uint data1, uint data2, DateTime time) { // glitch filter. events within 50 milliseconds of the first event are discarded if (Button1LastPushed.AddMilliseconds(50) > time) return; // Debug.Print("Button 1 Interrupt"); Button1LastPushed = time; // actions on interrupt here } }Also, Mario, i definitively did read an application note for a microswitch that strongly advised against putting a "naked" capacitor across a switch because of damaging effects. If i can turn it up again (I don't recall where I found it ...) i'll link it here.
Also for the record, if someone wants to do the hardware debouncing "cleanly" it should be probably done like in this article (german text, the schematic should be understandable though) using a RC filter with a schmitt trigger. However, as software debouncing is so easy and doesn't require additional components, i just do that Another useful bit of information in that (german) article is that switches usually bounce for up to 10ms, so the time constants for the debouncing (software or hardware) should be chosing according to that (and no human operates a switch 100 times a second anyway)
Thanks Stefan
Helped me out with my project
0 user(s) are reading this topic
0 members, 0 guests, 0 anonymous users