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 follows on from the previous post about timing a button switch press and 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(); }
else if (state == CLOSEDtoOPEN) { pressType = stopTimer(); }
if (pressType == SHORT_PRESS)
{
Serial.println("Short key press detected");
pressType = 0;
}
else 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, if the press was short then the LED goes off. If, however, the press was long, the LED stays on.
Because of how the short press works, when the LED is on, a short press will turn the LED off.
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 02
// Turn on an LED with a long press
// 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 time for a short press
const long SHORT_KEY_PRESS_MAX_DURATION = 1000; // 1000ms is 1 second
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();
turnOnLED();
}
else if (state == CLOSEDtoOPEN)
{
pressType = stopTimer();
if (pressType == SHORT_PRESS)
{
turnOffLED();
pressType = 0;
}
if (pressType == LONG_PRESS)
{
// leave the LED on.
}
}
} // 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;
}
void turnOnLED()
{
digitalWrite(PIN_RED_LED,HIGH);
}
void turnOffLED()
{
digitalWrite(PIN_RED_LED,LOW);
}
Not really required for this small example but I have moved the turn led on and turn led off to their own functions.
First, the button switch is checked.
state = checkSwitch();
If the switch has gone from OPEN to CLOSED the LED is turned on and the timer is started.
Since I want the LED to light up when the key is first pressed, the first part of the LED code is not related to how long the button switch is pressed. At this point the LED doesn’t care how long you pressed the button. It’s just happy you did.
if (state == OPENtoCLOSED)
{
startTimer();
turnOnLED();
}
If the switch has gone from CLOSED to OPEN, IE the button switch is no longer being pressed, the timer is stopped, the time the button switch was pressed is calculated and either SHORT_PRESS or LONG_PRESS is returned.
If the press was short, the LED is turned off.
|If the press was long, the LED is left on.
else if (state == CLOSEDtoOPEN)
{
pressType = stopTimer();
if (pressType == SHORT_PRESS)
{
turnOffLED();
pressType = 0;
}
if (pressType == LONG_PRESS)
{
// leave the LED on.
}
}
And that’s it for this session. You can now detect short and long key presses using a single button switch.