Single Double Click and Long Press Detection

Solving Approach

How do you plan to solve it?

 
 

 

 

 

Code

/*Paste your code her

// C++ code
//
// Fixed button gestures: single click, double click, long press
// Wiring: button between pin and GND. Use INPUT_PULLUP.

const uint8_t BUTTON_PIN = 2;         // change if needed
const unsigned long DEBOUNCE_MS = 50;    // debounce interval
const unsigned long DOUBLE_CLICK_MS = 400; // max gap to accept second click
const unsigned long LONG_PRESS_MS = 1000;  // hold time for long press

// runtime state
bool lastRaw = HIGH;           // last raw reading from pin
bool stable = HIGH;            // debounced state
unsigned long lastBounce = 0;  // timestamp of last raw change

bool pressed = false;          // currently pressed (debounced)
unsigned long pressStart = 0;  // when press started
bool longReported = false;     // long press reported for this hold

uint8_t clickCount = 0;        // number of short releases seen
unsigned long lastRelease = 0; // time of last release (for double-click timeout)

void setup() {
 Serial.begin(115200);
 pinMode(BUTTON_PIN, INPUT_PULLUP);
 Serial.println(F("Ready: single / double / long press detection"));
}

void loop() {
 // --- read & debounce (non-blocking) ---
 bool raw = digitalRead(BUTTON_PIN); // HIGH when not pressed (INPUT_PULLUP)
 if (raw != lastRaw) {
   lastBounce = millis(); // input changed: reset debounce timer
   lastRaw = raw;
 }

 if (millis() - lastBounce > DEBOUNCE_MS) {
   // reading has been stable for debounce time
   if (raw != stable) {
     // debounced edge
     stable = raw;

     if (stable == LOW) {
       // press (active low)
       pressed = true;
       pressStart = millis();
       longReported = false;
       // do not increment clickCount here
     } else {
       // release
       pressed = false;
       unsigned long dur = millis() - pressStart;
       if (dur >= LONG_PRESS_MS) {
         // long press (if not already reported while holding)
         if (!longReported) Serial.println(F("Long press detected"));
         // long press consumes the gesture; clear click tracking
         clickCount = 0;
         lastRelease = 0;
       } else {
         // short press -> candidate for single/double click
         clickCount++;
         lastRelease = millis();
       }
     }
   }
 }

 // --- detect long press while still holding (report once immediately) ---
 if (pressed && !longReported) {
   if (millis() - pressStart >= LONG_PRESS_MS) {
     Serial.println(F("Long press detected"));
     longReported = true;
     // clear click tracking
     clickCount = 0;
     lastRelease = 0;
   }
 }

 // --- classify single vs double click ---
 if (clickCount == 1) {
   // wait for possible second click
   if (millis() - lastRelease > DOUBLE_CLICK_MS) {
     Serial.println(F("Single click detected"));
     clickCount = 0;
     lastRelease = 0;
   }
 } else if (clickCount == 2) {
   Serial.println(F("Double click detected"));
   clickCount = 0;
   lastRelease = 0;
 }

 // loop runs fast; no delay()
}
 

 

Output

Video

Add a video of the output (know more)

 

 

 

Upvote
Downvote

Submit Your Solution

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