The delay() function is a lie. It blocks the CPU, burns power, and destroys responsiveness. Moving beyond it — into an actual scheduler — is one of the most clarifying journeys an embedded developer can take.
The Limits of Super-Loops
A typical Arduino sketch is a super-loop: poll every sensor, update every display, repeat. It works until three tasks want the CPU at the same time. Then you get flickering displays, missed button presses, and a hum of wasted cycles.
MicroTaskX started as an attempt to answer one question: what is the smallest codebase that can honestly call itself a real-time scheduler?
Scheduling Without the Scheduler
The kernel is deliberately tiny:
- Compile-time task bounds via
MicroTaskXKernel<MAX_TASKS>— C++ templates, so the memory allocation cost is zero at runtime. - Macro timers (
MTX_EVERY) that token-paste into non-blocking intervals — no callback registration, no heap objects. - Runtime controls — pause, resume, and reschedule tasks while they run.
The Two Hardest Parts
Power management. The kernel sleeps toward the next scheduled task instead of sleeping on a fixed interval. On ESP32, that means Light Sleep aligned to the exact timing need; on AVR, Idle Sleep. Power draws get measured, not guessed.
CPU profiling. You cannot know how much headroom you have unless you measure free idle-loop cycles. The profiler runs on the samples that nobody else would bother counting — and it changes how you tune your firmware.
What I'd Tell a Beginner
Scheduling is not an exotic topic. It is the difference between firmware that frustrates you and firmware that feels alive. Build a small scheduler, run three tasks, watch them interleave. You will never write a blocking delay() the same way again.
MicroTaskX is open source — the whole kernel fits in one header file, which is the best documentation a library can have.