0

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.

Code:

#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)
{
  pinMode(BUTTON_PIN, INPUT);

  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
      }
      else
      {
        buttonPressTime = 0;
      }
    }

    // save the reading. Next time through the loop, it'll be the lastButtonState:
    lastButtonState = reading;
    vTaskDelay(10);
  }
}

void setup()
{
  Serial.begin(115200);
  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);
  Serial.println(debug);
  delay(50);
  yield();
}
The Kaese
  • 419
  • 5
  • 15
  • The `guru mediation panic` usually happened when you have a buffer overflow. Looking into your code, I suspect that the `debug[]` is not terminated correctly with `\0`. – hcheung May 23 '21 at 00:56
  • BTW, The [Freertos used in ESP32](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html) is slightly different from standard Freertos, instead of using `xTaskCreate()`, `xTaskCreatePinnedToCore()` should be used. On the task function, if you are not passing in any params, it is advise to explicitly declare `(void) pvParameters;` within the task function. ESP32 comes with a simple [example](https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/FreeRTOS/FreeRTOS.ino) for task creation. – hcheung May 23 '21 at 00:57
  • **1)** I suggest you to use volatile keyword for your variables. **2)** ```buttonState == HIGH``` when "pressed" means that you connected button between vcc and pin, right? **3)** I do not see pullup/pulldown setup in your code so I think you use external resistor between pin and ground. is this correct? – Maxim Sagaydachny May 23 '21 at 04:02
  • @MaximSagaydachny, 1. Can you explain why this is important? Just curious. 2. Correct! 3. Also correct! – The Kaese May 23 '21 at 04:25
  • Using of volatile keyword instructs compiler to avoid optimisations and hints that variable can be changed by external actor , i.e. by code from different thread or interrupt handler. I doubt it will help in your case - but it is a good practice – Maxim Sagaydachny May 23 '21 at 04:43

0 Answers0