EEVblog Electronics Community Forum

Electronics => Microcontrollers => Topic started by: jancumps on December 12, 2013, 06:36:44 pm

Title: Listening for a long or short signal from button: what's your approach?
Post by: jancumps on December 12, 2013, 06:36:44 pm
When you use a pushbutton in a microcontroller managed user interface, what approach do you use?

- start a timer on the falling edge and measure count on the raising edge
- always keep a timer running and save the count on the falling edge?
- something else?

And do you stop other processing while the button is pressed or not?
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: Bored@Work on December 12, 2013, 07:31:53 pm
Continuously sampling the keyboard matrix. Effectively undersampling with respect to most key bouncing but fast enough to detect changes originating from human interaction. Storing (shifting in) the sampling results in a bit-array, one per key. The lengths of such a bit-array defines the longest key-press history available for a key. Then checking for a continuous sequence of ones (indicating a long key press) in such an array, starting from what constitutes "now" or "latest" in the array, back to whatever would be the key press duration for which I want to check.

E.g. sampling with 50 ms requires 20 bits (make it 24 bits = 3 bytes, or a single 32 bit variable) per key to keep a > 1 second history for a key. A simple test
Code: [Select]
if((value & 0x000FFFFF) == 0x000FFFFF) ...
then tells me if a button has been pressed for at least 1s.

For larger durations I accumulate e.g. 1s press-durations in a separate counting byte.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: nctnico on December 12, 2013, 08:17:57 pm
Use a timer and poll it. Never ever use interrupts for switches and buttons unless their signals are properly filtered and are run through buffers with schmitt-trigger inputs!
I usually choose the polling interval so I can see a button is pushed for several timer intervals without making the user wait too long. This involves a counter to count the number of intervals. The number of intervals can be used to detect how long a button was pushed when it was released and/or whether a button was pushed long enough.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: TheDirty on December 13, 2013, 01:32:37 pm
I usually have an interval timer that updates general purpose counters and will poll the button presses.  Then I have some hardcoded values to evaluate on button up.  value 1 is very small and means false trigger or possibly a bounce, Value two is timed for short button press, and value three is long button press.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: TMM on December 13, 2013, 04:11:41 pm
Use a timer and poll it. Never ever use interrupts for switches and buttons unless their signals are properly filtered and are run through buffers with schmitt-trigger inputs!
Why not? Debouncing isn't hard to implement in software - I usually just implement a hold-off timer. You'd only want hardware debouncing if the processor was doing something absolutely time critical and you needed to minimize the number of unnecessary interrupts.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: nctnico on December 13, 2013, 05:00:46 pm
Use a timer and poll it. Never ever use interrupts for switches and buttons unless their signals are properly filtered and are run through buffers with schmitt-trigger inputs!
Why not? Debouncing isn't hard to implement in software - I usually just implement a hold-off timer. You'd only want hardware debouncing if the processor was doing something absolutely time critical and you needed to minimize the number of unnecessary interrupts.
That is EXACTLY what I'm typing...  8)
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: mazurov on December 14, 2013, 12:16:17 am
I generate separate events on press and release. What is going to happen on each event depends on the state of the state machine the application is in. If I need to react to long press I start a timer in that state. If I don't, I do nothing (or react on release instead of a press).
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: dannyf on December 14, 2013, 12:25:05 am
Quote
Never ever use interrupts for switches and buttons...

Wow!

That's some advice we can do without, :)
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: Marco on December 14, 2013, 12:59:57 am
For what it's worth in the few (as in 2 and in college/internship, so not worth much) embedded systems I made I just had a big old interrupt routine running at fairly high frequency and polled all the buttons with software debouncing and kept a timer for some to see how long they had been pressed for velocity based controls.

I guess you could keep a separate counter for repeated button presses if you're interested in that and your UI code might not be fast enough to catch them.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: dannyf on December 14, 2013, 01:10:14 am
Quote
kept a timer for some to see how long they had been pressed

You actually don't need a timer in that case: you can run a counter in the isr to detect long vs. short presses.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: Marco on December 14, 2013, 01:14:32 am
Sorry I didn't make myself clear, that is what I meant.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: Rufus on December 14, 2013, 01:17:10 am
Quote
Never ever use interrupts for switches and buttons...

Wow!

That's some advice we can do without, :)

It is generally good advice. I have never wanted or needed to generate interrupts from switches or buttons except when required to wake up a sleeping processor.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: nctnico on December 14, 2013, 01:17:31 am
Quote
Never ever use interrupts for switches and buttons...

Wow!

That's some advice we can do without, :)
People using interrupts for stuff like uncontrolled signals (usually) attached to long wires will crash and burn at a some point. I've seen it happen several times with damages into 6 figures behind a € sign as a result in some cases... Better be safe than sorry!
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: c4757p on December 14, 2013, 01:25:08 am
I have never, ever needed to interrupt on a user input, except for the aforementioned case of waking from sleep (in which case I implement a policy of disabling that interrupt immediately after wake and not returning to sleep for at least a second). The amount of time it takes a human to interact with a device is aeons in microcontroller time! It's too easy to screw up and too useless to bother.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: jancumps on December 14, 2013, 10:14:43 am
Texas Instruments give this advice on the e2e forum:
http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/54539.aspx (http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/54539.aspx)

Quote
Ideally all port pin inputs should be handled with interrupts. Actually, all internal & external events should be interrupt-driven to achieve real-time responses & minimize CPU active time which consumes much more current than low power modes
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: nctnico on December 14, 2013, 01:12:50 pm
Texas Instruments give this advice on the e2e forum:
http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/54539.aspx (http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/54539.aspx)

Quote
Ideally all port pin inputs should be handled with interrupts. Actually, all internal & external events should be interrupt-driven to achieve real-time responses & minimize CPU active time which consumes much more current than low power modes
Major  :palm:
Make a note of the author and put that name on your 'these people are complete idiots' list. Its probably a software guy/girl who thinks hardware always does what its supposed to do, a button doesn't bounce or a signal can't contain noise.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: jancumps on December 14, 2013, 01:20:38 pm
He has given the debounce logic too in that same forum post.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: dannyf on December 14, 2013, 01:31:13 pm
Quote
'these people are complete idiots' list.

It is the drunk who always insist that others are drunk.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: arcom on December 14, 2013, 03:34:47 pm
I use a counter for each button along with rising/falling edge detection to handle button states. In addition to that, each button has it's own status variable and entire processing is inside a single function which is called in 10-20ms intervals. That function does something like this:

1. reset button status variable
2. detect rising and falling edges
3. on rising edge
3.1. reset counter
3.2. set "pressed" bit
4. on falling edge
4.1. set "released" bit
4.2. if counter <= short_press_limit, set "short press" bit
5. if button is pressed
5.1. if counter >= long_press_limit, set "long press" bit
5.2. else increment counter

"Short press" state will be triggered only on button release and "long press" state will be set as long as the button is held pressed which is handy for scrolling purposes (eg. incrementing/decrementing a value by holding a button pressed). Good thing about this approach is that there are no delays or waiting loops so that the rest of the code can run. Also, calling the function in regular intervals debounces the buttons quite effectively.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: Rufus on December 14, 2013, 03:44:49 pm
Texas Instruments give this advice on the e2e forum:
http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/54539.aspx (http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/54539.aspx)

Quote
Ideally all port pin inputs should be handled with interrupts. Actually, all internal & external events should be interrupt-driven to achieve real-time responses & minimize CPU active time which consumes much more current than low power modes
Major  :palm:
Make a note of the author and put that name on your 'these people are complete idiots' list.

The second line of code associated with that post says

"// Go to sleep, wait for port pin interrupt"

So he was quoted without the context of minimizing power consumption.


Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: JohnnyGringo on December 14, 2013, 04:21:13 pm
Texas Instruments give this advice on the e2e forum:
http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/54539.aspx (http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/54539.aspx)

Quote
Ideally all port pin inputs should be handled with interrupts. Actually, all internal & external events should be interrupt-driven to achieve real-time responses & minimize CPU active time which consumes much more current than low power modes
Major  :palm:
Make a note of the author and put that name on your 'these people are complete idiots' list. Its probably a software guy/girl who thinks hardware always does what its supposed to do, a button doesn't bounce or a signal can't contain noise.
:palm:  :palm: Hardware shouldn't be bouncing or noisy before it gets to the software guy/girl.  That's a problem that should be taken care of in the hardware design.  You don't really want your average coder having to worry about piss-poor hardware.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: nctnico on December 14, 2013, 05:20:18 pm
And make the bean counters come downstairs saying the competition is making a cheaper product with a PCB which contains 10 times less components than yours?
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: jancumps on December 14, 2013, 06:22:29 pm
...

The second line of code associated with that post says

"// Go to sleep, wait for port pin interrupt"

So he was quoted without the context of minimizing power consumption.

My excuses if my quote is incomplete. I did quote this part of his text though:
Quote
... minimize CPU active time which consumes much more current than low power modes

I'm not looking for consensus on the solution on the internet :). I'm going to try out all the approaches mentioned above and see how each of them performs.

Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: Bored@Work on December 14, 2013, 06:41:45 pm
:palm:  :palm: Hardware shouldn't be bouncing or noisy before it gets to the software guy/girl.  That's a problem that should be taken care of in the hardware design.

Hello?
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: madires on December 14, 2013, 07:55:40 pm
I use whatever fits the requirements and the program flow. If I have a battery powered device with an one-button interface I'd use an interrupt. It doesn't make much sense to have the MCU wasting power for waiting hours, days or weeks for the user to press the button. There's no this-is-the-right-method-and-everything-else-is-BS method.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: JohnnyGringo on December 14, 2013, 08:02:24 pm
:palm:  :palm: Hardware shouldn't be bouncing or noisy before it gets to the software guy/girl.  That's a problem that should be taken care of in the hardware design.

Hello?
Listening.  And quite frankly, I'm rather ignorant when it comes to hardware issues (obviously).  But I don't see the point of the "Hello?".  What am I missing?
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: Neverther on December 14, 2013, 08:19:58 pm
I run the input with interrupts mainly due to the instant need for shutoff.
The interrupt waits couple milliseconds before sampling the input port (poor mans debounce) and the functions are processed in priority order.
Long/short press for last two buttons is simply while loop for input state and counter to add up and break the loop if it gets too high.
If the loop is not broken, it was a short press.
And the fact it is running in avr pin change interrupt means that keeping the buttons pressed does not affect the control loop after the first run, where the maximum time is known.
Would not work on fast systems but on mine the control response is only required within 0.5s to 1s so it does not matter.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: nctnico on December 14, 2013, 08:36:18 pm
Yet one of the problems of using interrupts for wake-up is that when the battery lifetime is based on 1 push per day a bad switch and/or moisture could easely cause several false presses (interrupts) per second. That would shorten the lifetime significantly. A couple of months ago I designed a battery (coin cell) powered gadget. I simply poll the buttons a few times per second. This solution exceeded the battery lifetime requirement more than twice (worst case) AND I can guarantee it will meet the battery lifetime under any circumstance.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: Bored@Work on December 14, 2013, 09:29:16 pm
Listening.  And quite frankly, I'm rather ignorant when it comes to hardware issues (obviously).  But I don't see the point of the "Hello?".  What am I missing?

E.g. because even quality switches bounce. You can now waste money on hardware debouncing or handle it with a few lines of code. More hardware does not come for free, and it adds more potential failure points. Further, your hardware does not run in an ideal world. You need to be prepared for spurious events.  You can sort them out in software the same way you sort out bounces - in fact, it is the same code, killing two birds with one stone.

And you can never make hardware idiot-proof for the software guy. If the software guy is an idiot he'll find other ways to code stupid things. Like using interrupts or setting all outputs to the fastest rise time.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: JohnnyGringo on December 14, 2013, 11:27:14 pm
Listening.  And quite frankly, I'm rather ignorant when it comes to hardware issues (obviously).  But I don't see the point of the "Hello?".  What am I missing?

E.g. because even quality switches bounce. You can now waste money on hardware debouncing or handle it with a few lines of code. More hardware does not come for free, and it adds more potential failure points. Further, your hardware does not run in an ideal world. You need to be prepared for spurious events.  You can sort them out in software the same way you sort out bounces - in fact, it is the same code, killing two birds with one stone.

And you can never make hardware idiot-proof for the software guy. If the software guy is an idiot he'll find other ways to code stupid things. Like using interrupts or setting all outputs to the fastest rise time.
Yes, I see your point. But, wouldn't that mostly apply to microprocessor world? I.e. Systems/Designs with no device drivers?

If I'm coding on a device with an OS, I'd certainly expect hardware malfunctions to be handled by the hardware or device drivers.  Having a crappy-hardware design with the expectation that the device drivers will sort it all out, is still just a crappy-hardware design.  NOT THAT YOU would personally design crappy-hardware.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: nctnico on December 15, 2013, 11:30:59 am
If I'm coding on a device with an OS, I'd certainly expect hardware malfunctions to be handled by the hardware or device drivers.  Having a crappy-hardware design with the expectation that the device drivers will sort it all out, is still just a crappy-hardware design.
That is a pretty naive approach which could get you (and your boss) in serious trouble. Hardware (silicon bugs!) and their drivers have short deadlines so they have bugs by definition when they are just released. Every now and then I do development for embedded Linux systems and I usually have to fix some bugs in the kernel (and drivers) to get the platform running reliably. If you are writing software which interacts with hardware you need an embedded software engineer with a strong electronics background. One who knows how to use an oscilloscope. And even then you might run into trouble.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: JohnnyGringo on December 15, 2013, 01:53:28 pm
If I'm coding on a device with an OS, I'd certainly expect hardware malfunctions to be handled by the hardware or device drivers.  Having a crappy-hardware design with the expectation that the device drivers will sort it all out, is still just a crappy-hardware design.
That is a pretty naive approach which could get you (and your boss) in serious trouble. Hardware (silicon bugs!) and their drivers have short deadlines so they have bugs by definition when they are just released. Every now and then I do development for embedded Linux systems and I usually have to fix some bugs in the kernel (and drivers) to get the platform running reliably. If you are writing software which interacts with hardware you need an embedded software engineer with a strong electronics background. One who knows how to use an oscilloscope. And even then you might run into trouble.
+1 nctnico!  Fortunately for me, I have no boss <grin>. Yea, I've had my fair share of embedded device drivers, and it always drove me nuts when just a few simple parts would had made my job simpler.  That is why this was such a hot-button topic for me.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: Jeroen3 on December 15, 2013, 07:40:50 pm
If you are on a 32 bit platform...
Sample button status every 20 ms and perform this:
Code: [Select]
history = (history<<1) | ((bool)button & 1)
Then you can check the amount of cleared bits (buttons always go low when pressed) and detect short press (0xFFFFFFF0), long press (0x00000000), medium press (0xFFFF0000), double press (0xFF00FF00) you name it.
All in the software, I've only used long and short press, double and medium are a lot more effort to program.

But now I have a flawless relay control button with mode select when you hold it.

Tip, use the setbits instruction to prevent useless comparisons... If you target has such instruction.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: NiHaoMike on December 16, 2013, 12:11:58 am
You could have the buttons trigger an interrupt, but mask the interrupt in its ISR. Then use a timer interrupt to unmask the button interrupt. That way, it can still respond almost instantly but if noise tries to cause an interrupt storm, it would be self limiting. Using low priority interrupts on a processor that supports it also works.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: dannyf on December 16, 2013, 12:20:23 am
Quote
You could have the buttons trigger an interrupt, but mask the interrupt in its ISR. Then use a timer interrupt to unmask the button interrupt.

I have a lot of trouble trying to figure out how that might work.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: nctnico on December 16, 2013, 02:00:36 am
You could have the buttons trigger an interrupt, but mask the interrupt in its ISR. Then use a timer interrupt to unmask the button interrupt. That way, it can still respond almost instantly but if noise tries to cause an interrupt storm, it would be self limiting. Using low priority interrupts on a processor that supports it also works.
I see the idea. The problem is that when dealing with noise you could get a false positive if you sample only once after a delay. IMHO you should sample a signal from a button/switch a few times so you know it is a stable signal and not noise.
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: jancumps on December 16, 2013, 11:00:34 am
What about
?

In that case the processor does no have to reside to endless polling, it gets a wake up from the button, and I deal with the remarks from other posters here about noisy interrupts because polling is done with a timer.

Thought?
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: nctnico on December 16, 2013, 01:00:33 pm
The problem is that every time you get a pulse you have the clock running for a relatively long period. You could setup a scheme where you poll the buttons for a short period of time with a timer interrupt but then again your battery life estimates can be way off. If you really need ultra low power I'd use hardware filtering using ultra low power CMOS logic (maybe even the 4000 series).
Title: Re: Listening for a long or short signal from button: what's your approach?
Post by: jancumps on December 16, 2013, 01:38:10 pm
When I used the word clock I should have used Timer with interrupt.
If the gio interrupt was a glitch then the timer can stop after the first tick because it would find immediately when polling that the button is not pressed and that it was a glitch?

Wouldn't the battery last longer because I only have a timer running when needed, and for the shortest possible period?

The real polling would still happen on timer interrupts as explained by you, but the timer and its interrupt would only be activated if a button trigger occurs, and stop polling if all handling is processed.

Am I looking too far?