All submissions

Single Double Click and Long Press Detection

Solving Approach

How do you plan to solve it?

I will connect a button to a microcontroller pin and write code that measures how long the button is pressed and the time between presses to tell the difference between a single click, a double click, and a long press, then print each one to the serial monitor.
 

 

 

 

Code

// Pin Definitions
const int buttonPin = 2; // The button is on Pin 2

// Timing Constants (Milliseconds)
const unsigned long DEBOUNCE_TIME = 50;   // Ignore tiny button jitters
const unsigned long LONG_PRESS_TIME = 500;     // Hold for 0.5s for Long Press
const unsigned long MAX_DOUBLE_CLICK_TIME = 250; // Max time between two clicks

// State Variables
int buttonState = HIGH;
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
unsigned long pressStartTime = 0;
bool waitForRelease = false;
bool singleClickRegistered = false;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP); // Crucial: use internal pull-up
  Serial.begin(9600); // Start communication
  Serial.println("Ready! Press the button.");
}

void loop() {
  unsigned long currentTime = millis(); // Get the current time
  int reading = digitalRead(buttonPin); // Read the button

  // DEBOUNCE: If the reading changed, reset the debounce timer
  if (reading != lastButtonState) {
    lastDebounceTime = currentTime;
  }
  lastButtonState = reading; // Save the reading for next time

  // Only proceed if the reading has been stable for DEBOUNCE_TIME
  if ((currentTime - lastDebounceTime) > DEBOUNCE_TIME) {
    // If the stable reading is different from our saved state...
    if (reading != buttonState) {
      buttonState = reading; // Update the stable state

      // Button was PRESSED (went from HIGH to LOW)
      if (buttonState == LOW) {
        pressStartTime = currentTime; // Record the start time of the press
        Serial.println("Button pressed (start timing)");

        // If we were already waiting for a 2nd click, this is a DOUBLE CLICK!
        if (waitForRelease) {
          Serial.println(">> DOUBLE CLICK");
          waitForRelease = false;
          singleClickRegistered = true;
        }
      }
      // Button was RELEASED (went from LOW to HIGH)
      else {
        unsigned long pressDuration = currentTime - pressStartTime;
        Serial.print("Button released. Held for: "); Serial.println(pressDuration);

        // Was it a short press? And not part of a double click?
        if (pressDuration < LONG_PRESS_TIME && !singleClickRegistered) {
          waitForRelease = true; // It might be a single click, wait for double
          lastDebounceTime = currentTime; // Reset the double-click timer
          Serial.println("Waiting to see if double-click...");
        }
        // Was it a long press?
        else if (pressDuration >= LONG_PRESS_TIME) {
          Serial.println(">> LONG PRESS");
          waitForRelease = false;
        }
        singleClickRegistered = false; // Reset the double-click flag
      }
    }
  }

  // If we're waiting for a double-click and the time runs out, it's a SINGLE CLICK
  if (waitForRelease && (currentTime - lastDebounceTime) > MAX_DOUBLE_CLICK_TIME) {
    Serial.println(">> SINGLE CLICK");
    waitForRelease = false;
  }
}

 

 

 

Output

Video

https://wokwi.com/projects/442621117817103361

 

 

 

Submit Your Solution

Note: Once submitted, your solution goes public, helping others learn from your approach!