Timer APIs
Timer
The Timer component provides a cross-platform API for executing callback functions with a specified period. The timer can be started, stopped, and restarted, and the timer can have an optional initial delay before the first callback is executed. The timer can be configured to run once or repeatedly.
The timer API is implemented using the Task component, and the timer callback is executed in the context of the timer task.
Code examples for the task API are provided in the timer example folder.
API Reference
Header File
Classes
-
class Timer : public espp::BaseComponent
A timer that can be used to schedule tasks to run at a later time.
A timer can be used to schedule a task to run at a later time. The timer will run in the background and will call the task when the time is up. The timer can be canceled at any time. A timer can be configured to run once or to repeat.
The timer uses a task to run in the background. The task will sleep until the timer is ready to run. When the timer is ready to run, the task will call the callback function. The callback function can return true to cancel the timer or false to keep the timer running. If the timer is configured to repeat, then the callback function will be called again after the period has elapsed. If the timer is configured to run once, then the callback function will only be called once.
The timer can be configured to start automatically when it is constructed. If the timer is not configured to start automatically, then the timer can be started by calling start(). The timer can be canceled at any time by calling cancel().
Timer Example 1
auto timer_fn = []() { static size_t iterations{0}; fmt::print("[{:.3f}] #iterations = {}\n", elapsed(), iterations); iterations++; // we don't want to stop, so return false return false; }; auto timer = espp::Timer({.name = "Timer 1", .period = 500ms, .callback = timer_fn, .log_level = espp::Logger::Verbosity::DEBUG});
Timer Watchdog Example
static constexpr bool panic_on_watchdog_timeout = false; espp::Task::configure_task_watchdog(300ms, panic_on_watchdog_timeout); auto timer_fn = []() { static size_t iterations{0}; fmt::print("[{:.3f}] #iterations = {}\n", elapsed(), iterations); iterations++; // we don't want to stop, so return false return false; }; auto timer = espp::Timer({.name = "Timer 1", .period = 500ms, .callback = timer_fn, .log_level = espp::Logger::Verbosity::DEBUG}); timer.start_watchdog(); // start the watchdog timer for this timer std::this_thread::sleep_for(500ms); std::error_code ec; std::string watchdog_info = espp::Task::get_watchdog_info(ec); if (ec) { fmt::print("Error getting watchdog info: {}\n", ec.message()); } else if (!watchdog_info.empty()) { fmt::print("Watchdog info: {}\n", watchdog_info); } else { fmt::print("No watchdog info available\n"); } // NOTE: the timer and the watchdog will both automatically get stopped when // the task goes out of scope and is destroyed.
Timer Delay Example
auto timer_fn = []() { static size_t iterations{0}; fmt::print("[{:.3f}] #iterations = {}\n", elapsed(), iterations); iterations++; // we don't want to stop, so return false return false; }; auto timer = espp::Timer({.name = "Timer 1", .period = 500ms, .delay = 500ms, .callback = timer_fn, .auto_start = false, // don't start the timer automatically, we'll call start() .log_level = espp::Logger::Verbosity::DEBUG}); timer.start(); std::this_thread::sleep_for(2s); logger.info("Cancelling timer for 2 seconds"); timer.cancel(); std::this_thread::sleep_for(2s); timer.start(); std::this_thread::sleep_for(2s); logger.info("Cancelling timer for 2 seconds"); timer.cancel(); std::this_thread::sleep_for(2s); timer.start(1s);
Oneshot Timer Example
auto timer_fn = []() { static size_t iterations{0}; fmt::print("[{:.3f}] #iterations = {}\n", elapsed(), iterations); iterations++; // we don't want to stop, so return false return false; }; auto timer = espp::Timer({.name = "Timer 1", .period = 0ms, // one shot timer .delay = 500ms, .callback = timer_fn, .log_level = espp::Logger::Verbosity::DEBUG});
Timer Cancel Itself Example
auto timer_fn = []() { static size_t iterations{0}; fmt::print("[{:.3f}] #iterations = {}\n", elapsed(), iterations); iterations++; // cancel the timer after 3 iterations if (iterations == 3) { fmt::print("[{:.3f}] auto-cancelling timer\n", elapsed()); return true; } return false; }; auto timer = espp::Timer({.name = "Timer 1", .period = 500ms, .callback = timer_fn, .stack_size_bytes = 6192, .log_level = espp::Logger::Verbosity::DEBUG});
Oneshot Timer Cancel Itself Then Start again with Delay Example
auto timer_fn = []() { static size_t iterations{0}; fmt::print("[{:.3f}] #iterations = {}\n", elapsed(), iterations); iterations++; // we want to stop, so return true return true; }; auto timer = espp::Timer({.name = "Timer 1", .period = 0ms, // one shot timer .delay = 500ms, .callback = timer_fn, .stack_size_bytes = 4096, .log_level = espp::Logger::Verbosity::DEBUG}); std::this_thread::sleep_for(2s); timer.cancel(); // it will have already been cancelled by here, but this should be harmless timer.start(1s); // restart the timer with a 1 second delay
Timer Update Period Example
auto timer_fn = []() { static size_t iterations{0}; fmt::print("[{:.3f}] #iterations = {}\n", elapsed(), iterations); iterations++; // we don't want to stop, so return false return false; }; auto timer = espp::Timer({.name = "Timer 1", .period = 500ms, .callback = timer_fn, .stack_size_bytes = 4096, .log_level = espp::Logger::Verbosity::DEBUG}); std::this_thread::sleep_for(2s); logger.info("Updating period to 100ms"); timer.set_period(100ms);
Timer AdvancedConfig Example
auto timer_fn = []() { static size_t iterations{0}; fmt::print("[{:.3f}] #iterations = {}\n", elapsed(), iterations); iterations++; // we don't want to stop, so return false return false; }; auto timer = espp::Timer({.period = 500ms, .callback = timer_fn, .task_config = { .name = "Advanced Config Timer", .stack_size_bytes = 4096, .priority = 10, .core_id = 1, }, .log_level = espp::Logger::Verbosity::DEBUG});
Note
The timer uses a task to run in the background, so the timer callback function will be called in the context of the task. The timer callback function should not block for a long time because it will block the task. If the timer callback function blocks for a long time, then the timer will not be able to keep up with the period.
Public Types
-
typedef std::function<bool()> callback_fn
The callback function type. Return true to cancel the timer.
Public Functions
-
explicit Timer(const Config &config)
Construct a new Timer object.
- Parameters
config – The configuration for the timer.
-
explicit Timer(const AdvancedConfig &config)
Construct a new Timer object.
- Parameters
config – The configuration for the timer.
-
void start()
Start the timer.
Starts the timer. Does nothing if the timer is already running.
-
void start(const std::chrono::duration<float> &delay)
Start the timer with a delay.
Starts the timer with a delay. If the timer is already running, this will cancel the timer and start it again with the new delay. If the timer is not running, this will start the timer with the delay. Overwrites any previous delay that might have been set.
- Parameters
delay – The delay before the first execution of the timer callback.
-
void cancel()
Cancel the timer.
Cancels the timer.
-
bool start_watchdog()
Start the task watchdog for the timer.
See also
See also
See also
Note
This function is only available on ESP
Note
This function will do nothing unless CONFIG_ESP_TASK_WDT_EN is enabled in the menuconfig. Default is y (enabled).
- Returns
true if the watchdog was started, false otherwise.
-
bool stop_watchdog()
Stop the task watchdog for the timer.
See also
See also
See also
Note
This function is only available on ESP
Note
This function will do nothing unless CONFIG_ESP_TASK_WDT_EN is enabled in the menuconfig. Default is y (enabled).
- Returns
true if the watchdog was stopped, false otherwise.
-
void set_period(const std::chrono::duration<float> &period)
Set the period of the timer.
Sets the period of the timer.
Note
If the period is 0, the timer will run once.
Note
If the period is negative, the period will not be set / updated.
Note
If the timer is running, the period will be updated after the current period has elapsed.
- Parameters
period – The period of the timer.
-
bool is_running() const
Check if the timer is running.
Checks if the timer is running.
- Returns
true if the timer is running, false otherwise.
-
inline const std::string &get_name() const
Get the name of the component
Note
This is the tag of the logger
- Returns
A const reference to the name of the component
-
inline void set_log_tag(const std::string_view &tag)
Set the tag for the logger
- Parameters
tag – The tag to use for the logger
-
inline espp::Logger::Verbosity get_log_level() const
Get the log level for the logger
See also
See also
- Returns
The verbosity level of the logger
-
inline void set_log_level(espp::Logger::Verbosity level)
Set the log level for the logger
See also
See also
- Parameters
level – The verbosity level to use for the logger
-
inline void set_log_verbosity(espp::Logger::Verbosity level)
Set the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls set_log_level
- Parameters
level – The verbosity level to use for the logger
-
inline espp::Logger::Verbosity get_log_verbosity() const
Get the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls get_log_level
- Returns
The verbosity level of the logger
-
inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)
Set the rate limit for the logger
See also
Note
Only calls to the logger that have _rate_limit suffix will be rate limited
- Parameters
rate_limit – The rate limit to use for the logger
-
struct AdvancedConfig
Advanced configuration for the timer.
Public Members
-
std::chrono::duration<float> period
The period of the timer. If 0, the timer callback will only be called once.
-
std::chrono::duration<float> delay = std::chrono::duration<float>(0)
The delay before the first execution of the timer callback after start() is called.
-
espp::Timer::callback_fn callback
The callback function to call when the timer expires.
-
bool auto_start = {true}
If true, the timer will start automatically when constructed.
-
espp::Task::BaseConfig task_config
The task configuration for the timer.
-
std::chrono::duration<float> period
-
struct Config
The configuration for the timer.
Public Members
-
std::string_view name
The name of the timer.
-
std::chrono::duration<float> period
The period of the timer. If 0, the timer callback will only be called once.
-
std::chrono::duration<float> delay = std::chrono::duration<float>(0)
The delay before the first execution of the timer callback after start() is called.
-
espp::Timer::callback_fn callback
The callback function to call when the timer expires.
-
bool auto_start = {true}
If true, the timer will start automatically when constructed.
-
size_t stack_size_bytes = {4096}
The stack size of the task that runs the timer.
-
size_t priority = {0}
Priority of the timer, 0 is lowest priority on ESP / FreeRTOS.
-
int core_id = {-1}
Core ID of the timer, -1 means it is not pinned to any core.
-
std::string_view name
-
typedef std::function<bool()> callback_fn
High Resolution Timer
The HighResolutionTimer component provides an esp-idf specific API to create managed high resolution timer objects using the esp_timer API. The timer can be started, stopped, and restarted, and it can be configured as a one-shot timer or a periodic timer.
API Reference
Header File
Classes
-
class HighResolutionTimer : public espp::BaseComponent
High resolution timer This class provides a high resolution timer using the ESP-IDF esp_timer API. The timer can be started in oneshot or periodic mode. The timer period can be set and queried. The timer can be started, stopped, and restarted. The timer can be queried to check if it is running.
High Resolution Timer Example
logger.set_rate_limit(100ms); auto timer_fn = [&]() { static size_t iterations{0}; iterations++; logger.info_rate_limited("High resolution timer callback: {}", iterations); // we don't want to stop, so return false return false; }; auto high_resolution_timer = espp::HighResolutionTimer({.name = "High Resolution Timer", .callback = timer_fn, .log_level = espp::Logger::Verbosity::DEBUG}); uint64_t period_us = 100; bool started = high_resolution_timer.start(period_us); logger.info("High resolution timer started: {}", started); std::this_thread::sleep_for(500ms); logger.info("Updating period to 100ms"); period_us = 1000 * 100; high_resolution_timer.set_period(period_us); logger.info("Periodic timer period: {}us", high_resolution_timer.get_period()); // NOTE: only if CONFIG_ESP_TIMER_PROFILING is enabled will this show more // than address, period and alarm. esp_timer_dump(stdout); // dump timer stats std::this_thread::sleep_for(500ms); logger.info("High resolution timer is running: {}", high_resolution_timer.is_running()); logger.info("Stopping timer"); high_resolution_timer.stop(); std::this_thread::sleep_for(500ms); logger.info("Starting oneshot to expire in 100ms"); started = high_resolution_timer.oneshot(period_us); logger.info("Oneshot timer started: {}", started); logger.info("Oneshot timer expiry: {}us", high_resolution_timer.get_period());
High Resolution Timer Watchdog Example
logger.set_rate_limit(100ms); auto timer_fn = [&]() { static size_t iterations{0}; iterations++; logger.info_rate_limited("High resolution timer callback: {}", iterations); // we don't want to stop, so return false return false; }; auto high_resolution_timer = espp::HighResolutionTimer({.name = "High Resolution Timer 1", .callback = timer_fn, .log_level = espp::Logger::Verbosity::DEBUG}); uint64_t period_us = 100; bool started = high_resolution_timer.start(period_us); logger.info("High resolution timer 1 started: {}", started); // make another HighResolutionTimer auto timer2_fn = [&]() { // sleep here to ensure watchdog triggers std::this_thread::sleep_for(350ms); // we don't want to stop, so return false return false; }; auto high_resolution_timer2 = espp::HighResolutionTimer({.name = "High Resolution Timer 2", .callback = timer2_fn, .log_level = espp::Logger::Verbosity::DEBUG}); // configure the task watchdog static constexpr bool panic_on_watchdog_timeout = false; espp::Task::configure_task_watchdog(300ms, panic_on_watchdog_timeout); // start the watchdog timer for this timer high_resolution_timer2.start_watchdog(); // ensure we can run the watchdog on a oneshot timer which is started after // we start the watchdog period_us = 1000 * 100; started = high_resolution_timer2.oneshot(period_us); logger.info("High resolution timer 2 started: {}", started); std::this_thread::sleep_for(400ms); std::error_code ec; std::string watchdog_info = espp::Task::get_watchdog_info(ec); if (ec) { fmt::print("Error getting watchdog info: {}\n", ec.message()); } else if (!watchdog_info.empty()) { fmt::print("Watchdog info: {}\n", watchdog_info); } else { fmt::print("No watchdog info available\n"); } // now stop the watchdog timer high_resolution_timer2.stop_watchdog(); // delay some more so we can see the watchdog timer has stopped std::this_thread::sleep_for(500ms);
Note
Since this uses the esp-timer API, you cannot set different stack sizes for differnt timers like you can with espp::Timer and espp::Task. Instead, you may need to adjust the stack size via the menuconfig
CONFIG_ESP_TIMER_TASK_STACK_SIZE
.Public Types
-
typedef std::function<void()> Callback
Callback type for the timer.
Public Functions
-
explicit HighResolutionTimer(const Config &config)
Constructor
- Parameters
config – Configuration of the timer
-
~HighResolutionTimer()
Destructor.
-
bool start(uint64_t period_us = 0, bool oneshot = false)
Start the timer
- Parameters
period_us – Period of the timer in microseconds, or timeout if oneshot is true
oneshot – True if the timer should be oneshot, false if periodic
- Returns
True if the timer was started successfully, false otherwise
-
bool oneshot(uint64_t timeout_us = 0)
Start the timer in oneshot mode
- Parameters
timeout_us – Timeout of the timer in microseconds
- Returns
True if the timer was started successfully, false otherwise
-
bool periodic(uint64_t period_us = 0)
Start the timer in periodic mode
- Parameters
period_us – Period of the timer in microseconds
- Returns
True if the timer was started successfully, false otherwise
-
void stop()
Stop the timer.
-
bool start_watchdog()
Start the watchdog timer
Note
This function will do nothing unless CONFIG_ESP_TASK_WDT_EN is enabled in the menuconfig. Default is y (enabled).
- Returns
True if the watchdog timer was started successfully, false otherwise
-
bool stop_watchdog()
Stop the watchdog timer
Note
This function will do nothing unless CONFIG_ESP_TASK_WDT_EN is enabled in the menuconfig. Default is y (enabled).
- Returns
True if the watchdog timer was stopped successfully, false otherwise
-
bool is_running() const
Check if the timer is running
- Returns
True if the timer is running, false otherwise
-
bool is_oneshot() const
Is the timer oneshot?
- Returns
True if the timer is a oneshot timer, false if it is perioic.
-
bool is_periodic() const
Is the timer periodic?
- Returns
True if the timer is a periodic timer, false if it is oneshot.
-
void set_period(uint64_t period_us)
Set the period of the timer in microseconds
Note
This function will restart the timer if it is running
- Parameters
period_us – Period of the timer in microseconds
-
uint64_t get_period()
Get the period of the timer in microseconds
Note
This function will return 0 if the timer is not running
Note
This function will return the period of the timer, not the remaining time
- Returns
Period of the timer in microseconds
-
inline const std::string &get_name() const
Get the name of the component
Note
This is the tag of the logger
- Returns
A const reference to the name of the component
-
inline void set_log_tag(const std::string_view &tag)
Set the tag for the logger
- Parameters
tag – The tag to use for the logger
-
inline espp::Logger::Verbosity get_log_level() const
Get the log level for the logger
See also
See also
- Returns
The verbosity level of the logger
-
inline void set_log_level(espp::Logger::Verbosity level)
Set the log level for the logger
See also
See also
- Parameters
level – The verbosity level to use for the logger
-
inline void set_log_verbosity(espp::Logger::Verbosity level)
Set the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls set_log_level
- Parameters
level – The verbosity level to use for the logger
-
inline espp::Logger::Verbosity get_log_verbosity() const
Get the log verbosity for the logger
See also
See also
See also
Note
This is a convenience method that calls get_log_level
- Returns
The verbosity level of the logger
-
inline void set_log_rate_limit(std::chrono::duration<float> rate_limit)
Set the rate limit for the logger
See also
Note
Only calls to the logger that have _rate_limit suffix will be rate limited
- Parameters
rate_limit – The rate limit to use for the logger
-
struct Config
Configuration of the timer.
-
typedef std::function<void()> Callback