Wraparound-safe millisecond tick helpers and heartbeat scheduling for CircuitPython, MicroPython, and CPython.
Project description
chumicro-timing
Cross-runtime millisecond tick helpers and periodic timing utilities for CircuitPython, MicroPython, and CPython.
All timing is non-blocking — nothing in this library calls time.sleep(). Capture ticks_ms() once per loop iteration and pass the shared timestamp to Heartbeat.poll().
Installation
CircuitPython (circup)
Register the ChuMicro bundle (remove the other channel first if switching):
circup bundle-remove ChuMicro/ChuMicro-Bundle-Experimental # skip if never added
circup bundle-add ChuMicro/ChuMicro-Bundle
circup install chumicro-timing
MicroPython (mip)
mpremote mip install github:ChuMicro/ChuMicro-Bundle/chumicro_timing
CPython (pip)
pip install chumicro-timing
Experimental (pre-release) versions
Pre-release builds are published automatically when a library version is bumped. Do not register both bundles simultaneously — circup may pick either version for a given package.
# CircuitPython
circup bundle-remove ChuMicro/ChuMicro-Bundle # skip if never added
circup bundle-add ChuMicro/ChuMicro-Bundle-Experimental
circup install chumicro-timing
# MicroPython
mpremote mip install github:ChuMicro/ChuMicro-Bundle-Experimental/chumicro_timing
# CPython
pip install chumicro-timing-experimental
Quick example
from chumicro_timing import Heartbeat, ticks_ms
heartbeat = Heartbeat(period_ms=1000)
while True:
now = ticks_ms()
if heartbeat.poll(now):
print("one second elapsed")
# ... do other work ...
What's included
Tick functions
| Symbol | Description |
|---|---|
ticks_ms() |
Monotonic millisecond counter, wraps every ~6.2 days |
ticks_diff(end, start) |
Wraparound-safe signed difference |
ticks_add(ticks, delta) |
Wraparound-safe addition |
Heartbeat
| Symbol | Description |
|---|---|
Heartbeat(period_ms, ticks=None) |
Periodic timer that fires once per elapsed period |
Heartbeat.poll(now_ms) |
Returns True once per period and advances the timer |
Heartbeat.is_due(now_ms) |
Check whether the period has elapsed (without advancing) |
Heartbeat.reset(now_ms) |
Restart the timer from the given timestamp |
Heartbeat.period_ms |
The configured period (read-only property) |
Testing
| Symbol | Description |
|---|---|
FakeTicks(start_ms=0) |
Deterministic tick source for host-side tests |
FakeTicks.advance(amount_ms) |
Move the fake clock forward |
Platform support
The tick source is selected automatically at import time:
| Priority | Source | Runtime |
|---|---|---|
| 1 | supervisor.ticks_ms |
CircuitPython 7+ |
| 2 | time.ticks_ms |
MicroPython, some CircuitPython builds |
| 3 | time.monotonic_ns |
CPython, some CircuitPython boards |
| 4 | time.monotonic |
Final fallback (float seconds → int ms) |
All sources are masked to a 2²⁹ ms period, so behavior is identical regardless of which source is used.
Testing your code
The chumicro_timing.testing module provides FakeTicks for deterministic host-side tests — no wall-clock waits:
from chumicro_timing import Heartbeat
from chumicro_timing.testing import FakeTicks
fake = FakeTicks()
heartbeat = Heartbeat(period_ms=100, ticks=fake)
now = fake.ticks_ms()
assert heartbeat.poll(now) is False
fake.advance(100)
now = fake.ticks_ms()
assert heartbeat.poll(now) is True
Examples
| Example | What it shows |
|---|---|
heartbeat_blink.py |
Basic periodic timer loop |
multiple_heartbeats.py |
Multiple heartbeats at different rates |
timeout_check.py |
One-shot timeout using is_due |
debounce.py |
Simulated button debounce |
periodic_tick.py |
Manual periodic loop (what Heartbeat does under the hood) |
circuitpython_blink.py |
LED blink on CircuitPython hardware |
circuitpython_debounce.py |
GPIO button debounce on CircuitPython |
micropython_blink.py |
LED blink on MicroPython hardware |
micropython_debounce.py |
GPIO button debounce on MicroPython |
Docs
📖 Stable docs · Experimental docs
Browse on GitHub:
- User guide — getting started, usage patterns, platform notes
- API reference — full API documentation
- Testing helpers — using
FakeTicksin your tests
Find this library
PyPI: chumicro-timing Bundle: ChuMicro-Bundle (CircuitPython & MicroPython) Source: ChuMicro/ChuMicro — cross-runtime Python libraries for ESP32, RP2040, and other microcontrollers.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file chumicro_timing-0.1.13.tar.gz.
File metadata
- Download URL: chumicro_timing-0.1.13.tar.gz
- Upload date:
- Size: 5.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5048a8d6f26c6f45b12c86f9e4aeba6ca35a3514e7f2c2ff8db9a0eb008df15a
|
|
| MD5 |
64e5b2e58c52ef7203d4ff4e690d1d11
|
|
| BLAKE2b-256 |
f17ed231ab3967c346d2aa7979cf108538b1377777aabaa23a8582b6539af020
|
Provenance
The following attestation bundles were made for chumicro_timing-0.1.13.tar.gz:
Publisher:
release.yml on ChuMicro/ChuMicro
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
chumicro_timing-0.1.13.tar.gz -
Subject digest:
5048a8d6f26c6f45b12c86f9e4aeba6ca35a3514e7f2c2ff8db9a0eb008df15a - Sigstore transparency entry: 1245268849
- Sigstore integration time:
-
Permalink:
ChuMicro/ChuMicro@dd340f989088f8224e89bcf4a58f05fe86a29ac1 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/ChuMicro
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@dd340f989088f8224e89bcf4a58f05fe86a29ac1 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file chumicro_timing-0.1.13-py3-none-any.whl.
File metadata
- Download URL: chumicro_timing-0.1.13-py3-none-any.whl
- Upload date:
- Size: 6.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dbc740cb8b71f6aaea5f4414954f23a412610dd803eb843c3fd348241604f298
|
|
| MD5 |
e14da9e14b00becb7cc914f508b8e4c7
|
|
| BLAKE2b-256 |
8ba0caeb501c56b20f2274ee86b5916d431314502227dfe38350545623697cd4
|
Provenance
The following attestation bundles were made for chumicro_timing-0.1.13-py3-none-any.whl:
Publisher:
release.yml on ChuMicro/ChuMicro
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
chumicro_timing-0.1.13-py3-none-any.whl -
Subject digest:
dbc740cb8b71f6aaea5f4414954f23a412610dd803eb843c3fd348241604f298 - Sigstore transparency entry: 1245268874
- Sigstore integration time:
-
Permalink:
ChuMicro/ChuMicro@dd340f989088f8224e89bcf4a58f05fe86a29ac1 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/ChuMicro
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@dd340f989088f8224e89bcf4a58f05fe86a29ac1 -
Trigger Event:
workflow_dispatch
-
Statement type: