ESP32 Simple button hold for 3 seconds example. Output doesn’t seem to make sense?

  arduino, arduino-esp32, c++, esp32

Hoping someone can see what I’m missing as it’s gotta be right there staring at me in the face..

I’ve got this code (below) set up on an ESP32 to spawn a thread that simply monitors the state of a pin connected to a switch. Essentially this code is supposed to wait for the button to be held for 3 seconds and then do something important. The actual input seems to read fine, but for some reason once I’ve pressed the button, the button state is stuck for like 15 seconds after un-pressing the switch.

For example,

  1. Press the switch, the actualBtnState reads 1, buttonState reads 1 (after 50us),and btnPressTime increments as expected.
  2. Release switch, actualBtnState reads 0, btnState reads 1, and btnPressTime stops incrementing.
  3. After 50us, expecting to see btnState read 0 and then trigger the else or elseif blocks (depending on how long the button was held). Actual results continue to read btnState = 1 and btnPressTime = [whatever the last held time was] for a solid 15 seconds or more. actuyalBtnState reads correctly at 0 this entire time and for some reason lastDebounceTime keeps incrementing?

I should note that this is part of a much larger project, hence the threading. I also can’t seem to print anything within the resetBtnCB function as I immediately get a "guru mediation error kernel panic whatever-the-error-is" error and the esp reboots.


#include <Arduino.h>
#define BUTTON_PIN 27

// Variables will change:
int buttonState;           // the current reading from the input pin
int lastButtonState = LOW; // the previous reading from the input pin

unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50;   // the debounce time; increase if the output flickers
unsigned long buttonPressTime = 0; //Amount of time the button has been held down
unsigned long actualBtnState = 0; //The actual reading from the pin without noise filtering

void resetBtnCB(void *pvParameters)

  while (true)
    // read the state of the switch into a local variable:
    int reading = digitalRead(BUTTON_PIN);
    actualBtnState = reading;

    // If the switch changed, due to noise or pressing:
    if (reading != lastButtonState)
      // reset the debouncing timer
      lastDebounceTime = millis();

    unsigned long timeSinceDebounce = millis() - lastDebounceTime;
    if (timeSinceDebounce > debounceDelay)
      // whatever the reading is at, it's been there for longer than the debounce
      // delay, so take it as the actual current state:
      buttonState = reading;

      if (buttonState == HIGH)
        buttonPressTime += timeSinceDebounce;
      else if (buttonPressTime > 300)
        buttonPressTime = 0;
        // SUCCESS! Do something important here as we've held the button for x seconds
        buttonPressTime = 0;

    // save the reading. Next time through the loop, it'll be the lastButtonState:
    lastButtonState = reading;

void setup()
  xTaskCreate(resetBtnCB, "reset_button", 1024, NULL, 10, NULL);

void loop()
  char debug[512];
  sprintf(debug, "button state %u, lastD %u, buttonPressTime %u, actualBtnState %u, lastBtnState %u", buttonState, lastDebounceTime, buttonPressTime, actualBtnState, lastButtonState);

Source: Windows Questions C++