ESP32 - Button - Long Press Short Press

We are going to learn how to:

  • How to detect the button's short press
  • How to detect the button's long press
  • How to detect both the button's long press and short press
  • Long press and short press with debouncing

In the first three parts, we learn how to detect in principle.

In the last part, we learn how to detect in practical use by applying the debounce. See why do we need to debounce for button.Without debouncing, we may detect wrong the button short press.

Video Tutorial

you can watch this video tutorial

Hardware Required

1×ESP-WROOM-32 Dev Module
1×Micro USB Cable
1×Button
1×Breadboard
n×Jumbers

Wiring Diagram

Breadboard Connections

ESP32 Button LED Wiring Diagram

Image is developed using Fritzing. Click to enlarge image

click to see ESP32 pin out

In this tutorial, we will use the internal pull-up resistor. Therefore, the state of the button is HIGH when normal and LOW when pressed.

How To Detect Short Press

We measure the time duration between the pressed and released events. If the duration is shorter than a defined time, the short press event is detected.

Let's see step by step:

  • Define how long the maximum of short press lasts
  • const int SHORT_PRESS_TIME = 500; // 500 milliseconds
  • Detect the button is pressed and save the pressed time
  • if(lastState == HIGH && currentState == LOW) 
       pressedTime = millis();             
  • Detect the button is released and save the released time
  • if(lastState == LOW && currentState == HIGH)
    releasedTime = millis();                   
  • Calculate press duration and
  • long pressDuration = releasedTime - pressedTime;
  • Determine the short press by comparing the press duration with the defined short press time.
  • if( pressDuration < SHORT_PRESS_TIME )
       Serial.println("A short press is detected");           

ESP32 Code for detecting the short press


const int BUTTON_PIN = 2;                                      // GIOP2 pin connected to button
const int SHORT_PRESS_TIME = 500;                              // 500 milliseconds

int lastState = LOW;                                           // the previous state from the input pin
int currentState;                                              // the current reading from the input pin
unsigned long pressedTime  = 0;
unsigned long releasedTime = 0;


void setup() {
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
}

void loop() {
  currentState = digitalRead(BUTTON_PIN);                      // read the state of the switch/button:

  if(lastState == HIGH && currentState == LOW)                 // button is pressed
    pressedTime = millis();
  else if(lastState == LOW && currentState == HIGH) {          // button is released
    releasedTime = millis();

    long pressDuration = releasedTime - pressedTime;

    if( pressDuration < SHORT_PRESS_TIME )
      Serial.println("A short press is detected");
  }

  lastState = currentState;                                    // save the the last state
}          

Quick Steps

  • Open Arduino IDE
  • Select the right board and port
  • Copy the above code and open with Arduino IDE
  • Click Upload button on Arduino IDE to upload code to ESP32
  • Press the button shortly several times.
  • See the result on Serial Monitor.

※ NOTE THAT:

The Serial Monitor may show several short press detection for one press. This is the normal behavior of the button. This behavior is called the “chattering phenomenon”. The issue will be solved in the last part of this tutorial.

How To Detect Long Press

There are two use cases for detecting the long press.

  • The long-press event is detected right after the button is released
  • The long-press event is detected during the time the button is being pressed, even the button is not released yet.

In the first use case, We measure the time duration between the pressed and released events. If the duration is longer than a defined time, the long-press event is detected.

In the second use case, After the button is pressed, We continuously measure the pressing time and check the long-press event until the button is released. During the time button is being pressed. If the duration is longer than a defined time, the long-press event is detected.

ESP32 Code for detecting long press when released


const int BUTTON_PIN = 21;                                         // GIOP21 pin connected to button
const int LONG_PRESS_TIME  = 1000;                                 // 1000 milliseconds

int lastState = LOW;                                               // the previous state from the input pin
int currentState;                                                  // the current reading from the input pin
unsigned long pressedTime  = 0;
unsigned long releasedTime = 0;


void setup() {
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(15, OUTPUT);

}

void loop() {
  currentState = digitalRead(BUTTON_PIN);                          // read the state of the switch/button:

  if(lastState == HIGH && currentState == LOW)                     // button is pressed
    pressedTime = millis();
  else if(lastState == LOW && currentState == HIGH) {              // button is released
    releasedTime = millis();

    long pressDuration = releasedTime - pressedTime;

    if( pressDuration > LONG_PRESS_TIME )
      Serial.println("A long press is detected");
  }

  lastState = currentState;                                        // save the the last state
}              

Quick Steps

  • Open Arduino IDE
  • Select the right board and port
  • Copy the above code and open with Arduino IDE
  • Click Upload button on Arduino IDE to upload code to ESP32
  • Press and release the button after one second.
  • See the result on Serial Monitor.

The long-press event is only detected right after the button is released

ESP32 Code for detecting long press during pressing


const int BUTTON_PIN = 21;                                  // GIOP21 pin connected to button
const int LONG_PRESS_TIME  = 1000;                          // 1000 milliseconds

int lastState = LOW;                                        // the previous state from the input pin
int currentState;                                           // the current reading from the input pin
unsigned long pressedTime  = 0;
bool isPressing = false;
bool isLongDetected = false;

void setup() {
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
}

void loop() {
  currentState = digitalRead(BUTTON_PIN);                   // read the state of the switch/button:

  if(lastState == HIGH && currentState == LOW) {            // button is pressed
    pressedTime = millis();
    isPressing = true;
    isLongDetected = false;
  } else if(lastState == LOW && currentState == HIGH) {     // button is released
    isPressing = false;
  }

  if(isPressing == true && isLongDetected == false) {
    long pressDuration = millis() - pressedTime;

    if( pressDuration > LONG_PRESS_TIME ) {
      Serial.println("A long press is detected");
      isLongDetected = true;
    }
  }

  lastState = currentState;                                 // save the the last state
}          

Quick Steps

  • Open Arduino IDE
  • Select the right board and port
  • Copy the above code and open with Arduino IDE
  • Click Upload button on Arduino IDE to upload code to ESP32
  • Press and release the button after one second.
  • See the result on Serial Monitor.

The long-press event is only detected when the button is not released yet

How To Detect Both Long Press and Short Press

Short Press and Long Press after released

Copy

const int BUTTON_PIN = 21;                                  // GIOP21 pin connected to button
const int SHORT_PRESS_TIME = 1000;                          // 1000 milliseconds
const int LONG_PRESS_TIME  = 1000;                          // 1000 milliseconds

int lastState = LOW;                                        // the previous state from the input pin
int currentState;                                           // the current reading from the input pin
unsigned long pressedTime  = 0;
unsigned long releasedTime = 0;


void setup() {
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
}

void loop() {
  currentState = digitalRead(BUTTON_PIN);                   // read the state of the switch/button:

  if(lastState == HIGH && currentState == LOW)              // button is pressed
    pressedTime = millis();
  else if(lastState == LOW && currentState == HIGH) {       // button is released
    releasedTime = millis();

    long pressDuration = releasedTime - pressedTime;

    if( pressDuration < SHORT_PRESS_TIME )
      Serial.println("A short press is detected");

    if( pressDuration > LONG_PRESS_TIME )
      Serial.println("A long press is detected");
  }

  lastState = currentState;                                 // save the the last state
}              

Quick Steps

  • Open Arduino IDE
  • Select the right board and port
  • Copy the above code and open with Arduino IDE
  • Click Upload button on Arduino IDE to upload code to ESP32
  • Long and short press the button.
  • See the result on Serial Monitor.

※ NOTE THAT:

The Serial Monitor may show several short press detection for one press. This is the normal behavior of the button. This behavior is called the “chattering phenomenon”. The issue will be solved in the last part of this tutorial.

Short Press and Long Press During pressing


const int BUTTON_PIN = 21;                                      // GIOP21 pin connected to button
const int SHORT_PRESS_TIME = 1000;                              // 1000 milliseconds
const int LONG_PRESS_TIME  = 1000;                              // 1000 milliseconds

int lastState = LOW;                                            // the previous state from the input pin
int currentState;                                               // the current reading from the input pin
unsigned long pressedTime  = 0;
unsigned long releasedTime = 0;
bool isPressing = false;
bool isLongDetected = false;

void setup() {
  Serial.begin(9600);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
}

void loop() {
  currentState = digitalRead(BUTTON_PIN);                       // read the state of the switch/button:

  if(lastState == HIGH && currentState == LOW) {                // button is pressed
    pressedTime = millis();
    isPressing = true;
    isLongDetected = false;
  } else if(lastState == LOW && currentState == HIGH) {         // button is released
    isPressing = false;
    releasedTime = millis();

    long pressDuration = releasedTime - pressedTime;

    if( pressDuration < SHORT_PRESS_TIME )
      Serial.println("A short press is detected");
  }

  if(isPressing == true && isLongDetected == false) {
    long pressDuration = millis() - pressedTime;

    if( pressDuration > LONG_PRESS_TIME ) {
      Serial.println("A long press is detected");
      isLongDetected = true;
    }
  }

  lastState = currentState;                                     // save the the last state
}           

Quick Steps

  • Open Arduino IDE
  • Select the right board and port
  • Copy the above code and open with Arduino IDE
  • Click Upload button on Arduino IDE to upload code to ESP32
  • Press and release the button after one second.
  • See the result on Serial Monitor.

※ NOTE THAT:

The Serial Monitor may show several short press detection for one press. This is the normal behavior of the button. This behavior is called the “chattering phenomenon”. The issue will be solved in the last part of this tutorial.

Long Press and Short Press with Debouncing

It is very important to debounce the button in many applications.

Debouncing is a little complicated, especially when using multiple buttons. To make it much easier for beginners, we created a library, called ezButton.

We will use this library in below codes

Short Press and Long Press with debouncing after released

Copy

#include <ezButton.h>

const int SHORT_PRESS_TIME = 1000;                                  // 1000 milliseconds
const int LONG_PRESS_TIME  = 1000;                                  // 1000 milliseconds

ezButton button(21);                                                // create ezButton object that attach to pin GIOP21

unsigned long pressedTime  = 0;
unsigned long releasedTime = 0;

void setup() {
  Serial.begin(9600);
  button.setDebounceTime(50);                                       // set debounce time to 50 milliseconds
}

void loop() {
  button.loop();                                                    // MUST call the loop() function first

  if(button.isPressed())
    pressedTime = millis();

  if(button.isReleased()) {
    releasedTime = millis();

    long pressDuration = releasedTime - pressedTime;

    if( pressDuration < SHORT_PRESS_TIME )
      Serial.println("A short press is detected");

    if( pressDuration > LONG_PRESS_TIME )
      Serial.println("A long press is detected");
  }
}             

Quick Steps

  • Open Arduino IDE
  • Select the right board and port
  • Copy the above code and open with Arduino IDE
  • Click Upload button on Arduino IDE to upload code to ESP32
  • Long and short press the button.
  • See the result on Serial Monitor.

※ NOTE THAT:

The Serial Monitor may show several short press detection for one press. This is the normal behavior of the button. This behavior is called the “chattering phenomenon”. The issue will be solved in the last part of this tutorial.

Short Press and Long Press with debouncing During Pressing


#include <ezButton.h>

const int SHORT_PRESS_TIME = 1000;                                  // 1000 milliseconds
const int LONG_PRESS_TIME  = 1000;                                  // 1000 milliseconds

ezButton button(21);                                                // create ezButton object that attach to pin GIOP21

unsigned long pressedTime  = 0;
unsigned long releasedTime = 0;
bool isPressing = false;
bool isLongDetected = false;

void setup() {
  Serial.begin(9600);
  button.setDebounceTime(50);                                       // set debounce time to 50 milliseconds
}

void loop() {
  button.loop();                                                    // MUST call the loop() function first

  if(button.isPressed()){
    pressedTime = millis();
    isPressing = true;
    isLongDetected = false;
  }

  if(button.isReleased()) {
    isPressing = false;
    releasedTime = millis();

    long pressDuration = releasedTime - pressedTime;

    if( pressDuration < SHORT_PRESS_TIME )
      Serial.println("A short press is detected");
  }

  if(isPressing == true && isLongDetected == false) {
    long pressDuration = millis() - pressedTime;

    if( pressDuration > LONG_PRESS_TIME ) {
      Serial.println("A long press is detected");
      isLongDetected = true;
    }
  }
}            

Quick Steps

  • Open Arduino IDE
  • Select the right board and port
  • Copy the above code and open with Arduino IDE
  • Click Upload button on Arduino IDE to upload code to ESP32
  • Press and release the button after one second.
  • See the result on Serial Monitor.

※ NOTE THAT:

The Serial Monitor may show several short press detection for one press. This is the normal behavior of the button. This behavior is called the “chattering phenomenon”. The issue will be solved in the last part of this tutorial.

Why Needs Long Press and Short Press

  • To save the number of buttons. A single button can keep two or more functionalities. For example, short press for changing operation mode, long press for turn off the device.
  • Use of long press to reduce the short press by accident. For example, some kinds of devices use the button for factory reset. If the button is pressed by accident, it is dangerous. To avoid it, the device is implemented to be factory reset only when the button is long-press (e.g over 5 seconds).

Book Tutorial

We are considering to make the book tutorials. If you think the book tutorials are essential, you can download it. download book

References

※ NOTE THAT:

Some components works on 3.3v and others works on 5v!