Main Site Documentation

Timing Button Presses


#1

I am thinking of using a timed button press to determine which branch of code to enter (I want to make a secret menu that appears on the screen after a button is held for 5 seconds).

What is the best way to accomplish this? I saw an old post about this but am not sure:

  1. where to put the timer/how to capture the time (the example link in the old post was broken)
  2. if interrupt driven DateTime.Now differences are better than a timer
  3. if there is a better way to accomplish entering my “secret menu”

I have 5 buttons on my device, all are interrupt low driven. If I did an interrupt timer, would I have to sacrifice one of these buttons to set it to both edges? I can always add another dedicated menu button if this turns out to be unreliable/a pain.


#2

Poll the button’s pin at 1 second intervals. Increment counter on each poll, if button is 0 then clear counter. If exactly 5 then trigger event. Otherwise let the counter keep counting.


#3

To access secret menu:

  1. On the secret button, make it interrupt on rise and falling edge.
  2. When the button is depressed, and the interrupt is entered, save the time, which is passed as one of the interrupt parameters.
  3. When the button is released, and the interrupt is entered, calculate the elapsed time by subtracting saved time from passed time.
  4. If the elapsed time is less than secret delay, execute primary function of button. If greater than secret delay, execute secret menu…

The state of the button, at time of interrupt, is also passed as a parameter. Don’t read the port directly, use the passed parameter.


#4

Except that is something goes wrong and the button is never released, what happens? Nothing?


#5

I should note: preference given to solution that does not require an additional interrupt. I would like to be able to piggy back all this on an existing one and not have to dispose of configurations. I currently have 5 edge low interrupts. If I have to configure one as both edges, it will be hard to maintain functionality in the other stages of my program


#6

Call emergency services since the user has had a heart attack, and is slumped over the device? :grinning:

Give me a use case for this situation, where doing nothing is incorrect.


#7

Holding down a power button.


#8

Hard to come up with a solution with incomplete/changing requirements.

Should be easy to do, but only you have the in-depth knowledge of your applications necessary to accomplish.


#9

True, but not a power button situation.


#10

OK here are complete, unchanging requirements:

rig one of my existing interrupt edge low buttons so that if it is held instead of quickly pressed, a flag is raised to enter a secret branch of code. Must stay away from having to switch the button type/configuration because this button needs to work throughout the whole program (like in places where edgelow is needed)


#11

Why would my solution not work throughout your program?

You are measuring the elapsed time between two events. Hard to do without recognizing both events.


#12

Because later in the program that same button will be needed as interrupt edge low while still maintaining the ability to access the menu. But it is seems to be overly complicated as I anticipated, I am just going to add an extra button dedicated to accessing the menu. This whole menu concept on a 20x2 character display is quite a challenge lol


#13

The sequence I described would allow a single button to both access the secret menu and its normal functionality. Just that button would need interrupts on rising and falling edges. Does not seem complicated to me.

Try a sample program, and see if it works for you.


#14

*** This compiled, but I did not test on actual hardware

using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Threading;

namespace DoublePurposeButton
{
public class Program
{
static DateTime buttonDownTime;
static TimeSpan secretMenuHoldSecs = new TimeSpan(0, 0, 5);

    public static void Main()
    {
        InterruptPort IntButton = new InterruptPort(Cpu.Pin.GPIO_Pin1, false,
                                                Port.ResistorMode.PullUp,
                                                Port.InterruptMode.InterruptEdgeBoth);

        IntButton.OnInterrupt += IntButton_OnInterrupt;


        Thread.Sleep(Timeout.Infinite);
    }

    static void IntButton_OnInterrupt(uint port, uint state, DateTime time)
    {
        if (state == 0)
        {
            // button down. record time
            buttonDownTime = DateTime.Now;
        }
        else
        {
            // calculate elapsed time
            TimeSpan elapsed = DateTime.Now - buttonDownTime;
            if (elapsed >= secretMenuHoldSecs)
            {
                // activate secret menu
            }
            else
            {
                // call normal functionality
            }
        }
    }
}

}


#15

@Mike In your code, won’t that button count 1 press as 2 presses during normal functionality since it is interrupt edge both? That is why I said I didn’t think it would work.

Also, can you please explain to me how the interrupt inputs work? I never fully understood that part and have never seen port or state inputs like that…might be useful for me


#16

Busy right now… Will explain interrupt handler later.

There should not be a problem with two interrupts per press/release since you know there are two interrupts per press, and should be able to handle it. From the state variable, you should be able to recognize press or release.

Play with the code and see how it works.

As for port and state… this is actually what the passed parameters of the interrupt mean. It appears in the GHI document on InterruptPorts.


#17

What if “Secret Menu” is an understatement and if the wrong eyes were to fall upon this menu we could risk global economic collapses like the world has never seen?

Then you have back up fail-safe solutions I suppose. I have never had a device I can recall (that I used often) with which I did not get an unregistered button state change at least once.

I’m still Team Polling anyway. If you aren’t absolutely sure interrupts are better for your app than polling then you should IMO poll for better performance (of the buttons) and easier development. I know there are major advantages to interrupts (or these psuedo-interrupts) but weigh them against the ease of polling!