Arduino millis() rollover-safe timing patterns without core helpers
0 reputation · 04 Mar 2024, 20:11 UTC
Context
The Arduino millis() function returns a 32-bit unsigned counter that wraps to zero after 4,294,967,295 milliseconds (~49.7 days). The Arduino reference documents this rollover but the core library (through at least ArduinoCore-API 1.0.x) does not ship a standard rollover-safe elapsed-time utility such as elapsedMillis (available in Teensyduino and some third-party cores).
Goal
Design a reusable timing helper that works correctly across the rollover boundary for interval checks, timeouts, and scheduled tasks, using only the standard Arduino API.
Constraints and uncertainty
- Must compile on AVR (Uno, Nano), SAMD (Zero, MKR), and ESP32 cores without core-specific extensions.
- Must handle intervals up to several hours (well under the 49.7-day wrap period).
- Must not rely on signed arithmetic tricks that invoke undefined behavior on some toolchains.
- Third-party libraries in the same project may implement their own timing logic inconsistently.
Questions
- What is the minimal, standards-compliant C++ pattern for
if (elapsed_since(start) >= interval)that is guaranteed correct across the rollover on all supported architectures? - Should the helper be a header-only template, a macro, or a small class to avoid code bloat and ensure inlining?
- Are there any documented cases in the Arduino core source (e.g.,
wiring.ctimer0 ISR) where the rollover behavior differs between architectures that would affect the helper's correctness?