FastCron: A zero-allocation cron library perfect for esp_deep_sleep()
Posted: Fri May 29, 2026 1:23 am
Hi everyone,
I know many of you have probably solved cron scheduling on your own in your projects one way or another, but I felt the need for an open, well-validated library purely for this purpose (since I couldn't find a zero-allocation one, I decided to build and open-source it: FastCron).
The idea is to take the heavy lifting of traditional cron libraries out of the microcontroller. The architecture completely decouples string parsing from the execution on the MCU. You can generate a 24-byte payload externally (using an included Python script) for OTA/MQTT, or assemble it locally using simple C setters.
The ESP32 only receives this tiny 24-byte struct and uses pure integer math to calculate the exact microsecond until the next event. This completely avoids malloc and prevents FreeRTOS heap fragmentation.
Here is how seamlessly it integrates with the ESP-IDF:
Quick Technical Specs:
Any suggestions (or pull requests) are very welcome!
I know many of you have probably solved cron scheduling on your own in your projects one way or another, but I felt the need for an open, well-validated library purely for this purpose (since I couldn't find a zero-allocation one, I decided to build and open-source it: FastCron).
The idea is to take the heavy lifting of traditional cron libraries out of the microcontroller. The architecture completely decouples string parsing from the execution on the MCU. You can generate a 24-byte payload externally (using an included Python script) for OTA/MQTT, or assemble it locally using simple C setters.
The ESP32 only receives this tiny 24-byte struct and uses pure integer math to calculate the exact microsecond until the next event. This completely avoids malloc and prevents FreeRTOS heap fragmentation.
Here is how seamlessly it integrates with the ESP-IDF:
Code: Select all
#include "fastcron.h"
#include "esp_sleep.h"
// ... inside your app_main ...
// Calculate microseconds until the next event
uint64_t sleep_us = fastcron_sleep_us(&schedule, now.tv_sec, (uint32_t)now.tv_usec);
// Go straight back to deep sleep
esp_deep_sleep(sleep_us);
- Memory: 24 bytes of RAM (the payload) and ~1.5 KB of Flash.
Performance: ~142 ns resolution time using O(1) bit-scans.
Design: Zero malloc, no <string.h> dependency, focused on MISRA C.
Any suggestions (or pull requests) are very welcome!