Page 1 of 1

Timer library and one-shot timers

Posted: Mon Apr 10, 2023 10:00 pm
by eposse
Hi, I'm trying to define a one-time timer on ESP32 using the Arduino-ESP32 Timer library from Espressif (https://espressif-docs.readthedocs-host ... timer.html) but I don't get the behaviour that I'm expecting.

The main idea is to start a timer for a given amount of time (say 5 seconds) whenever an external button is pushed. After this time, the interrupt callback is executed. See the full code below.

According to the docs, the third parameter of `timerAlarmWrite(timer, DELAY * 1000 * 1000, false)` is a boolean that specifies whether the timer will auto-reload or not, and should be set to true for a periodic alarm, and false otherwise.

Now, if you see the code below, the alarm is enabled when the button is pressed, and disabled when pressed again.

The problem is that the interrupt callback function `onTimeout` is called *immediately* after pressing the button, instead of waiting the 5 second delay. Why is this the case? How do you make it trigger the alarm only after the delay has passed?

Thanks

Full code:

Code: Select all

#include <Arduino.h>
#include <time.h>

#define LED 21
#define DELAY 3
#define BUTTON 5
 
hw_timer_t *timer = NULL;
unsigned int count = 0;

String getTimeStr() {
  char time_of_day_sec[20];
  char microseconds[8];
  char full_timestamp[30];
  struct tm timeinfo;
	struct timeval tv;
	gettimeofday(&tv, NULL);
  time_t now_sec = tv.tv_sec;
  suseconds_t now_usec = tv.tv_usec;
  localtime_r(&now_sec, &timeinfo);
  strftime(time_of_day_sec, sizeof(time_of_day_sec), "%Y-%m-%dT%H:%M:%S", &timeinfo);
  sprintf(microseconds, "%06d", now_usec);
  sprintf(full_timestamp, "%s.%sZ", time_of_day_sec, microseconds);
  return String(full_timestamp);
}

// void IRAM_ATTR onTimeout()
void ARDUINO_ISR_ATTR onTimeout()
{
  Serial.println("timeout alt");
  digitalWrite(LED, !digitalRead(LED));
}
void setup()
{
  Serial.begin(115200);
  Serial.println("setup");
  pinMode(LED, OUTPUT);
  timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, &onTimeout, true);
  timerAlarmWrite(timer, DELAY * 1000 * 1000, false);
}

void loop()
{
  Serial.printf("%s - loop iteration #%u\n", getTimeStr().c_str(), ++count);
  static bool active = false;
  static bool timerEnabled = false;
  static int lastButtonState = 1;
  int buttonState = digitalRead(BUTTON);
  if (!buttonState && lastButtonState) {
    Serial.println("button pressed");
    active = !active;
  }
  if (active) {
    Serial.println("active");
    if (!timerEnabled) {
      Serial.println("enabling timer");
      timerAlarmEnable(timer);
      timerEnabled = true;
    }
  }
  else {
    Serial.println("inactive");
    if (timerEnabled) {
      Serial.println("disabling timer");
      timerAlarmDisable(timer);
      timerEnabled = false;
    }
  }
  delay(1000);
}