Skip to the content.

MycilaTaskManager

License: MIT Continuous Integration PlatformIO Registry

Arduino / ESP32 Task Manager Library

This is a simple task manager for Arduino / ESP32 to schedule tasks at a given frequency. Tasks are represented by anonymous functions, so they must be small, non-blocking and cooperative.

Table of Contents

Features

Installation

PlatformIO

lib_deps =
    mathieucarbou/MycilaTaskManager@^4.2.3

Arduino IDE

Search for “MycilaTaskManager” in the Library Manager and install it.

Usage

Please have a look at the examples for complete usage patterns.

Simple Task

#include <MycilaTaskManager.h>

Mycila::Task sayHello("sayHello", [](void* params) {
  Serial.println("Hello");
});

void setup() {
  Serial.begin(115200);

  sayHello.setEnabled(true);
  sayHello.setType(Mycila::Task::Type::FOREVER); // this is the default
  sayHello.setInterval(1000); // run every 1000ms
  sayHello.onDone([](const Mycila::Task& me, uint32_t elapsed) {
    ESP_LOGD("app", "Task '%s' executed in %" PRIu32 " us", me.name(), elapsed);
  });
}

void loop() {
  sayHello.tryRun();
}

With a TaskManager

A TaskManager helps organize multiple tasks and execute them together:

#include <MycilaTaskManager.h>

Mycila::TaskManager loopTaskManager("loop()");

Mycila::Task sayHello("sayHello", [](void* params) {
  Serial.println("Hello");
});

Mycila::Task sayGoodbye("sayGoodbye", [](void* params) {
  Serial.println("Goodbye");
});

void setup() {
  Serial.begin(115200);

  sayHello.setEnabled(true);
  sayHello.setType(Mycila::Task::Type::FOREVER);
  sayHello.setInterval(1000);
  sayHello.onDone([](const Mycila::Task& me, uint32_t elapsed) {
    sayGoodbye.resume(); // trigger the goodbye task
  });
  loopTaskManager.addTask(sayHello);

  sayGoodbye.setEnabled(true);
  sayGoodbye.setType(Mycila::Task::Type::ONCE); // runs once then pauses
  loopTaskManager.addTask(sayGoodbye);
}

void loop() {
  loopTaskManager.loop(); // executes all scheduled tasks
}

Async Mode

Run a task manager in a background FreeRTOS task:

void setup() {
  // ... configure tasks ...

  // Start async with custom parameters
  loopTaskManager.asyncStart(
    4096,  // stack size
    -1,    // priority (-1 = same as caller)
    -1,    // core ID (-1 = same as caller)
    10,    // delay in ms when no tasks execute
    false  // enable WDT for this task
  );
}

void loop() {
  // loop() is now free for other work, or can be deleted
  vTaskDelete(NULL); // delete loop task if not needed
}

See the AsyncTaskManager example for a complete implementation.

Task Types

Passing Data to Tasks

char* message = "Pong";

Mycila::Task ping("ping", [](void* params) {
  Serial.println((const char*)params);
});

void setup() {
  ping.setData(message);
  ping.setEnabled(true);
  ping.setType(Mycila::Task::Type::ONCE);
}

Conditional Task Execution

Use predicates to control task execution dynamically:

bool systemReady = false;

Mycila::Task conditionalTask("conditional", [](void* params) {
  Serial.println("System is ready!");
});

void setup() {
  conditionalTask.setEnabledWhen([]() {
    return systemReady; // only runs when systemReady is true
  });
  conditionalTask.setInterval(1000);
}

Profiling & Statistics

Enable profiling to track task execution times:

void setup() {
  // Enable profiling for all tasks in the manager
  loopTaskManager.enableProfiling(
    6,  // taskManagerBinCount - bins for manager profiling
    10, // taskBinCount - bins for individual tasks
    1   // unitDividerMillis - 1 for milliseconds, 1000 for microseconds
  );

  // Or enable for individual tasks
  sayHello.enableProfiling(10, 1);
}

void loop() {
  loopTaskManager.loop();

  // Log statistics periodically
  static unsigned long lastLog = 0;
  if (millis() - lastLog > 5000) {
    loopTaskManager.log(); // prints statistics to serial
    lastLog = millis();
  }
}

The statistics use power-of-2 bins to track execution times. For example, with 10 bins:

JSON Support

When compiled with MYCILA_JSON_SUPPORT defined, you can export task data to JSON:

#include <ArduinoJson.h>
#include <MycilaTaskManager.h>

void outputJson() {
  JsonDocument doc;
  loopTaskManager.toJson(doc.to<JsonObject>());
  serializeJson(doc, Serial);
  Serial.println();
}

See the TaskManagerJson example for details.

Watchdog Timer (WDT) Support

Protect against hung tasks using the ESP32 Task Watchdog Timer:

void setup() {
  // Configure global WDT
  Mycila::TaskManager::configureWDT(5, false); // 5 seconds, no panic

  // Start async task manager with WDT enabled
  taskManager.asyncStart(4096, -1, -1, 10, true); // last param enables WDT
}

See the Watchdog example for a complete demonstration.

Advanced Task Control

// Pause and resume individual tasks
myTask.pause();
myTask.resume();
myTask.resume(5000); // resume after 5 second delay

// Pause/resume all tasks in a manager
loopTaskManager.pause();
loopTaskManager.resume();

// Request early execution (skip waiting for interval)
myTask.requestEarlyRun();

// Force immediate execution
myTask.forceRun();

// Check task state
bool isRunning = myTask.running();
bool isPaused = myTask.paused();
bool isEnabled = myTask.enabled();
bool isScheduled = myTask.scheduled();
bool shouldRun = myTask.shouldRun();
uint32_t remaining = myTask.remainingTme(); // milliseconds until next run

API Reference

Task Class

Constructors

Task(const char* name, Function fn)
Task(const char* name, Type type, Function fn)

Task Configuration Methods

Task Control Methods

Task State Query Methods

Task Profiling Methods

Task JSON Methods

When MYCILA_JSON_SUPPORT is defined:

TaskManager Class

Constructor

TaskManager(const char* name)

Task Management Methods

Execution Methods

TaskManager Control Methods

TaskManager Query Methods

TaskManager Profiling Methods

TaskManager JSON Methods

When MYCILA_JSON_SUPPORT is defined:

Static Methods

BinStatistics Class

Used internally for profiling. Tracks execution times in power-of-2 bins.

Methods

Examples

The library includes several examples demonstrating different features:

Building and Testing

This library is designed for ESP32 using Arduino framework. It uses FreeRTOS features and ESP32-specific APIs.

Requirements

Compilation Flags

License

This library is licensed under the MIT License. See LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Author

Mathieu Carbou

Version

Current version: 4.2.3