Arduino. Long Press. Short Press

Using short presses and long presses together adds versatility and gives extra function to a single button switch. No longer are you restricted to pressed or not pressed. No. Now you have pressed a bit, pressed for a bit more.

This guide expands on the previous guide about timing a button switch press and so I assume you have read it. If not you have some home work to do.

In this guide I look at determining if the key press was short or long.

Example 1: Short Press Long Press

I start with a fairly simple example; when a short press is detected “short press” is printed in the serial monitor, and when a long press is detected, you guessed it, “long press” is printed. Exciting times.

Circuit

Very simple circuit. A single button switch connected to an Arduino. The switch has a 10k pull down resistor. It’s the same circuit as in the previous guide.

Example 1 sketch

//  Sketch: Arduino - Long press. Short press 001
//  Determine if a key press was short or long
//  www.martyncurrey.com

//  Pins
//  D12 to push button switch with 10K ohm pull down resistor
const int PIN_PUSH_BUTTON_SWITCH = 12;
   
// variables 
boolean switchState = LOW;
boolean oldSwitchState = LOW;

long timer_timeStart = 0;
long timer_timeStop  = 0;

byte state = 0;
const byte CLOSEDtoOPEN = 1;
const byte OPENtoCLOSED = 2;

const byte SHORT_PRESS = 3;
const byte LONG_PRESS  = 4;

// the maximum a short short press is
const long SHORT_KEY_PRESS_MAX_DURATION = 1000;
byte pressType = 0;


void setup() 
{
    Serial.begin(9600);
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    Serial.print("Uploaded: ");   Serial.println(__DATE__);
    Serial.println(" ");

    pinMode(PIN_PUSH_BUTTON_SWITCH, INPUT); 
}

 
void loop()
{
    state = checkSwitch();
    if (state == OPENtoCLOSED) { startTimer(); }
    if (state == CLOSEDtoOPEN) { pressType = stopTimer();  }

    if (pressType == SHORT_PRESS) 
    {
        Serial.println("Short key press detected");
        pressType = 0;
    }
    if (pressType == LONG_PRESS) 
    {
        Serial.println("Long key press detected");
        pressType = 0;
    }
    
}  // loop
  

int checkSwitch()
{
    byte returnVal = 0;
    // simple debounce
    boolean newSwitchState1 = digitalRead(PIN_PUSH_BUTTON_SWITCH);      delay(1);
    boolean newSwitchState2 = digitalRead(PIN_PUSH_BUTTON_SWITCH);      delay(1);
    boolean newSwitchState3 = digitalRead(PIN_PUSH_BUTTON_SWITCH);
    
    if (  (newSwitchState1==newSwitchState2) && (newSwitchState1==newSwitchState3) )
    {
        if (newSwitchState1 != oldSwitchState)
       {
            //  OPEN => CLOSED
            if ( oldSwitchState == LOW && newSwitchState1 == HIGH )
            {
              returnVal = OPENtoCLOSED;
            }
         
            //  CLOSED => OPEN
            if ( oldSwitchState == HIGH && newSwitchState1== LOW )
            {
              returnVal = CLOSEDtoOPEN;
            }

            oldSwitchState = newSwitchState1;
       }
       
    } // if (  (newSwitchState1==newSwitchState2) && (newSwitchState1==newSwitchState3) )

    return returnVal;
} // int checkSwitch()



void startTimer()
{
    timer_timeStart = millis(); // start the timer
}

byte stopTimer()
{
    // stop the timer. Return a flag to indicate the duration of the key press
    timer_timeStop = millis();
    long timePressed = timer_timeStop - timer_timeStart;

    byte returnVal = 0;
    if (timePressed <= SHORT_KEY_PRESS_MAX_DURATION) { returnVal = SHORT_PRESS;}
    else                                             { returnVal = LONG_PRESS;}
    return returnVal;
} 

Upload the code, open the serial monitor, and press away.

So what are the bits I added?

This first thing to notice is that the stopTimer() function now returns a value. This value is used to tell the rest of the sketch which key press has been detected; short or long.

if (state == CLOSEDtoOPEN) { pressType = stopTimer(); }

pressType can have 2, 3 if count 0, values; SHORT_PRESS and LONG_PRESS.

    if (pressType == SHORT_PRESS) 
    {
        Serial.println("Short key press detected");
        pressType = 0;
    }
    if (pressType == LONG_PRESS) 
    {
        Serial.println("Long key press detected");
        pressType = 0;
    }

When pressType == SHORT_PRESS print “Short key press detected” and when pressType == LONG_PRESS print “Short key press detected” .

Behind the scenes SHORT_PRESS equals 3 and LONG_PRESS equals 4. Using descriptive names makes understanding the code a little easier.

The stopTimer() function has been expanded and now includes code to check to see if the key press time is less than or equal to the short press duration. Or, in other words, is it a short press or not.

byte stopTimer()
{
    // stop the timer. Return a flag to indicate the duration of the key press
    timer_timeStop = millis();
    long timePressed = timer_timeStop - timer_timeStart;

    byte returnVal = 0;
    if (timePressed <= SHORT_KEY_PRESS_MAX_DURATION) { returnVal = SHORT_PRESS;}
    else                                             { returnVal = LONG_PRESS;}
    return returnVal;
}

The short press duration is set at the start of the sketch. 1000 is 1000 milliseconds or 1 second. You can change this to suit your own tastes.

const long SHORT_KEY_PRESS_MAX_DURATION = 1000;

The sketch works quite well but there is no indicator to show when the button switch is pressed. You could add back the serial print statement or, alternatively, add an LED. Let’s try adding an LED.

Example 2: Short Press Long Press With LED

More of the same except different. Short press, long press but now with an LED!
When the button is pressed the LED comes on. When the button is released the LED goes off.

After the button is released, if a short press is detected the LED blinks once, if a long press is detected the LED blinks twice.

Circuit

Button switch (with a 10k pull down resistor) on D12.
LED (with 330 ohm resistor) on D4.

Example 2 sketch

Very similar to example 1. I have just added a little bit of code to turn an LED on and off.

//  Sketch: Arduino - Long press. Short press 002
//  Determine if a key press was short or long with added LED
//  www.martyncurrey.com

//  Pins
//  D12 to push button switch with 10K ohm pull down resistor
//  D4 LED with 330 ohm resitor to ground
const int PIN_PUSH_BUTTON_SWITCH = 12;
const int PIN_RED_LED = 4;
   
// variables 
boolean switchState = LOW;
boolean oldSwitchState = LOW;

long timer_timeStart = 0;
long timer_timeStop  = 0;

byte state = 0;
const byte CLOSEDtoOPEN = 1;
const byte OPENtoCLOSED = 2;

const byte SHORT_PRESS = 3;
const byte LONG_PRESS  = 4;

// the maximum a short short press is
const long SHORT_KEY_PRESS_MAX_DURATION = 1000;
byte pressType = 0;


void setup() 
{
    Serial.begin(9600);
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    Serial.print("Uploaded: ");   Serial.println(__DATE__);
    Serial.println(" ");

    pinMode(PIN_PUSH_BUTTON_SWITCH, INPUT); 
    pinMode(PIN_RED_LED, OUTPUT); 
    digitalWrite(PIN_RED_LED,LOW); // not really required but makes me feel better.
}

 
void loop()
{
    state = checkSwitch();
    if (state == OPENtoCLOSED) 
    { 
      startTimer();            
      digitalWrite(PIN_RED_LED,HIGH);
    }
    
    if (state == CLOSEDtoOPEN) 
    { 
      pressType = stopTimer(); 
      digitalWrite(PIN_RED_LED,LOW); 
    }

    if (pressType == SHORT_PRESS) 
    {
        delay(500);  digitalWrite(PIN_RED_LED,HIGH); delay(100); digitalWrite(PIN_RED_LED,LOW); 
        pressType = 0;
    }
    if (pressType == LONG_PRESS) 
    {
        delay(500); 
        for (int i = 0; i < 2; i++)
        {
          Serial.println(i);
          digitalWrite(PIN_RED_LED,HIGH); delay(100); 
          digitalWrite(PIN_RED_LED,LOW); delay(100); 
        }
        pressType = 0;
    }
    
}  // loop
  

int checkSwitch()
{
    byte returnVal = 0;
    // simple debounce
    boolean newSwitchState1 = digitalRead(PIN_PUSH_BUTTON_SWITCH);      delay(1);
    boolean newSwitchState2 = digitalRead(PIN_PUSH_BUTTON_SWITCH);      delay(1);
    boolean newSwitchState3 = digitalRead(PIN_PUSH_BUTTON_SWITCH);
    
    if (  (newSwitchState1==newSwitchState2) && (newSwitchState1==newSwitchState3) )
    {
        if (newSwitchState1 != oldSwitchState)
       {
            //  OPEN => CLOSED
            if ( oldSwitchState == LOW && newSwitchState1 == HIGH )
            {
              returnVal = OPENtoCLOSED;
            }
         
            //  CLOSED => OPEN
            if ( oldSwitchState == HIGH && newSwitchState1== LOW )
            {
              returnVal = CLOSEDtoOPEN;
            }

            oldSwitchState = newSwitchState1;
       }
       
    } // if (  (newSwitchState1==newSwitchState2) && (newSwitchState1==newSwitchState3) )

    return returnVal;
} // int checkSwitch()



void startTimer()
{
    timer_timeStart = millis(); // start the timer
}

byte stopTimer()
{
    // stop the timer. Return a flag to indicate the duration of the key press
    timer_timeStop = millis();
    long timePressed = timer_timeStop - timer_timeStart;

    byte returnVal = 0;
    if (timePressed <= SHORT_KEY_PRESS_MAX_DURATION) { returnVal = SHORT_PRESS;}
    else                                             { returnVal = LONG_PRESS;}
    return returnVal;
}



 

When the timer is started I now also turn on the LED, and when the timer is stopped, I turn off the LED. Simples.

    if (state == OPENtoCLOSED) 
    { 
      startTimer();            
      digitalWrite(PIN_RED_LED, HIGH);
    }
    
    if (state == CLOSEDtoOPEN) 
    { 
      pressType = stopTimer(); 
      digitalWrite(PIN_RED_LED, LOW); 
    }

Since I just want the LED to light up when the key is pressed, the first part of the LED code is not related to how long the key is pressed. At this point the LED doesn’t care how long you press the key. It’s just happy you did.

After the button is released though. If it was a short press then the LED blinks once. For a long press it blinks twice.

    if (pressType == SHORT_PRESS) 
    {
        delay(250);  digitalWrite(PIN_RED_LED,HIGH); delay(100); digitalWrite(PIN_RED_LED,LOW); 
        pressType = 0;
    }
    if (pressType == LONG_PRESS) 
    {
        delay(250); 
        for (int i = 0; i < 2; i++)
        {
          Serial.println(i);
          digitalWrite(PIN_RED_LED,HIGH); delay(100); 
          digitalWrite(PIN_RED_LED,LOW);  delay(100); 
        }
        pressType = 0;
    }

And that’s it for this session. You can now detect short and long key presses using a single button switch.

Leave a Comment