Skip to content

Release [1.1.0]#33

Closed
inflop wants to merge 12 commits into
masterfrom
develop
Closed

Release [1.1.0]#33
inflop wants to merge 12 commits into
masterfrom
develop

Conversation

@inflop

@inflop inflop commented Jul 5, 2026

Copy link
Copy Markdown
Owner

[1.1.0] - 2026-07-05

Fixed

  • Counting drift accumulating over long count times. The counter now advances by the
    real measured millis() delta instead of the nominal interval, and the time reference
    point is moved before user callbacks run. Previously, both the check overshoot
    (the loop rarely hits the interval boundary exactly) and the callback execution time
    (e.g. Serial.print at 9600 baud) were silently lost on every tick, so the error grew
    linearly with the count duration — easily tens of seconds per hour on a busy loop().
    Accuracy is now independent of count length and loop() load.
  • Paused time leaking into the count. start() now resets the time reference point
    when resuming, so time spent paused is no longer counted. Calling start() on every
    loop() iteration (the documented usage pattern) remains safe — the reset only happens
    on an actual stopped-to-running transition.
  • restart() while running. The counter now restarts from a fresh time reference
    point instead of inheriting the previous tick's remainder.
  • isCounterRunning() missing implementation. The method was declared in the header
    and documented in the README, but never defined — calling it failed at link time.
  • Potential crash when run() was called without setInterval() configured.
    The interval and completion callback pointers were uninitialized; they now default
    to NULL and are guarded before invocation.

Added

  • Millisecond precision. setCounter() now has overloads accepting a milliseconds
    (0-999) argument, so counts can be configured with sub-second precision (e.g. a 1.5 s
    countdown).
    (How to use 0.1 second #22)
  • New getCurrentMilliseconds() and getCurrentTimeWithMillis() (formatted
    HH:MM:SS.mmm) read it back. Existing overloads and getCurrentTime() are unchanged.
    (How to show millisecond #15)
  • setCalibration(float factor) — optional one-time, per-board correction of hardware
    millis() drift (e.g. ceramic resonator tolerance, up to ~0.5% on many Uno/Nano
    clones). Measure factor = real_elapsed_time / timer_indicated_time against a
    reference clock; default 1.0 means no correction. Fractional milliseconds are
    carried between ticks, so the correction itself introduces no rounding drift.
  • "Accuracy and calibration" section in the README.
  • LICENSE file (MIT).
  • GitHub Actions CI: arduino-lint (strict, library-manager mode) plus example
    compilation for arduino:avr:uno and esp32:esp32:esp32.
  • "Installation" and "License" sections in the README.
  • keywords.txt: CountType (KEYWORD1) and COUNT_NONE/COUNT_UP/COUNT_DOWN
    (LITERAL1) for Arduino IDE highlighting.
  • library.properties: real library description in paragraph and the includes field.
  • examples/Basic — minimal count-down sketch for getting started.
  • examples/Advanced — count-up with pause/resume over serial, state queries,
    re-programming the count time and calibration.
  • CONTRIBUTING.md — bug report / pull request guidelines, API sync checklist,
    build-and-test instructions and release steps.
  • Claude Code project skills in .claude/skills/: verify-examples (bootstrap
    arduino-cli and compile all examples locally), check-api-sync (audit public API
    consistency across the header, cpp, README and keywords.txt) and release
    (release preconditions and tagging procedure).

Changed

  • README rewritten to current library standards: badges (release, license, Library
    Manager), feature list, quick start, per-mode usage snippets, a full API reference
    table matching the header signatures, examples/compatibility/contributing sections.
    The quick-start sketch now calls start() once in setup() instead of conditionally
    on every loop() iteration.
  • keywords.txt updated with setInterval and setCalibration for Arduino IDE
    highlighting.
  • Non-breaking code cleanups: getters are now const, nullptr instead of NULL,
    snprintf instead of sprintf in getCurrentTime(), simplified
    getCurrentSeconds() arithmetic, in-class member initialization (empty constructor
    and destructor removed), single include guard instead of guard + #pragma once,
    removed redundant Arduino.h include from the .cpp.
  • Example sketch: includes the library with <Countimer.h>, uses LED_BUILTIN and
    configures it with pinMode() in setup().
  • Completion timing semantics: a countdown now completes on the tick where the remaining
    time no longer exceeds the measured delta (up to one interval early), instead of one
    full tick after reaching zero (up to one interval late). Either way the boundary error
    is below one interval and does not accumulate.

- advance the counter by the real measured millis() delta and move the
  time reference before callbacks run, so neither check overshoot nor
  callback duration accumulates as drift (accuracy is now independent
  of count length and loop() load)
- stop paused time from leaking into the count: start() resets the time
  reference only on a stopped-to-running transition
- restart() no longer inherits the previous tick's remainder
- define isCounterRunning() (was declared and documented, but failed at
  link time when called)
- guard uninitialized interval/callback pointers in run()
- add setCalibration(float): optional per-board correction of hardware
  millis() drift, with fractional milliseconds carried between ticks
- sync keywords.txt with the public API
- README brought to current library standards: badges, feature list,
  quick start, per-mode usage snippets, full API reference table,
  examples/compatibility/contributing sections
- add CONTRIBUTING.md, CHANGELOG.md (Keep a Changelog format), MIT
  LICENSE and CLAUDE.md
- add examples/Basic (minimal count-down) and examples/Advanced
  (count-up, pause/resume over serial, state queries, re-programming
  the count time, calibration); clean up CountimerTest
- GitHub Actions: arduino-lint (strict, library-manager mode) plus
  compilation of all examples for arduino:avr:uno and esp32:esp32:esp32
- Claude Code project skills: verify-examples, check-api-sync, release
- library.properties: bump version to 1.1.0, real description in
  paragraph and the includes field
PR #30 (master) added a non-const isCounterRunning() independently of
the const version added on dev in 1d6daaa. Merging master into dev
(b64b41c) kept both as non-conflicting additions, leaving a stray
definition that doesn't match the const-qualified declaration in
Countimer.h and breaks compilation. Keep the const version, which
also correctly excludes completed counters.
The skill only documented installing arduino-cli on Windows. Add the
official install script for Linux, noting that BINDIR must be set
explicitly or the binary lands in ./bin instead of on PATH. Verified
end-to-end in WSL (Debian): install, AVR core install, and compiling
all three examples all succeed with the same output sizes as on
Windows.
Generic ESP32 boards (esp32:esp32:esp32 FQBN) don't define LED_BUILTIN
in the core, unlike AVR, causing the compile-sketches CI job to fail.
setCounter() gains overloads accepting a milliseconds (0-999)
argument, and getCurrentMilliseconds()/getCurrentTimeWithMillis()
read the sub-second remainder back. Existing overloads and
getCurrentTime() are unchanged, so no existing call site needs to
change.

Closes #22 (sub-second count time), closes #15 (displaying
milliseconds).
Resolves #17. reset() restores the counter to its initial time and leaves
the timer stopped (not completed), ready to be started again with start() —
filling the gap between restart() (reset + start) and stop() (reset + mark
completed). Behaves uniformly across COUNT_UP / COUNT_DOWN / COUNT_NONE.

restart() is now expressed as reset() + start(), removing the duplicated
"return to start time" logic.

Sync the public API across all four surfaces (header, cpp, README,
keywords.txt) and add an 'E' key to the CountimerTest example.
Copilot AI review requested due to automatic review settings July 5, 2026 14:02
@inflop inflop closed this Jul 5, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Releases Countimer 1.1.0 by improving timer accuracy and robustness (elapsed-time based ticking, pause/restart semantics, missing method implementation), adding millisecond support + calibration, and modernizing the project with updated docs, examples, and CI for linting/compilation.

Changes:

  • Fixes long-run drift by advancing the counter using measured millis() deltas and resetting the time reference before callbacks.
  • Adds millisecond precision APIs (setCounter(..., milliseconds), getCurrentMilliseconds(), getCurrentTimeWithMillis()) plus setCalibration().
  • Adds/updates packaging and contributor tooling: README rewrite, examples, build scripts, changelog/license, and GitHub Actions CI.

Reviewed changes

Copilot reviewed 25 out of 26 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/Countimer.h Public API updates (ms precision, calibration, reset), const-correct getters, member initialization.
src/Countimer.cpp Implements new APIs and fixes timing logic (elapsed-based ticks, pause/resume/restart behavior).
scripts/build-examples.sh Bash helper to compile examples with arduino-cli.
scripts/build-examples.ps1 PowerShell helper to compile examples with arduino-cli.
README.md Modernized documentation + API reference + new feature descriptions.
LICENSE Adds MIT license text.
library.properties Bumps version to 1.1.0 and improves metadata (paragraph/includes).
keywords.txt Updates Arduino IDE keyword highlighting for new API surface.
examples/CountimerTest/wokwi.toml Wokwi configuration for simulator runs.
examples/CountimerTest/diagram.json Wokwi diagram for simulator runs.
examples/CountimerTest/CountimerTest.ino Updates example to new API + ESP32 compatibility + sub-second demo.
examples/Basic/wokwi.toml Wokwi configuration for simulator runs.
examples/Basic/diagram.json Wokwi diagram for simulator runs.
examples/Basic/Basic.ino New minimal countdown example aligned with README quick start.
examples/Advanced/wokwi.toml Wokwi configuration for simulator runs.
examples/Advanced/diagram.json Wokwi diagram for simulator runs.
examples/Advanced/Advanced.ino New advanced serial-controlled example covering state queries + calibration.
CONTRIBUTING.md Adds contribution guidelines, API sync checklist, and build/verify instructions.
CLAUDE.md Adds agent-oriented repo guidance and architecture notes.
CHANGELOG.md Adds changelog with 1.1.0 notes and prior release entry.
.gitignore Ignores example build outputs and common embedded tooling dirs.
.github/workflows/ci.yml Adds CI: arduino-lint and example compilation for AVR + ESP32.
.gitattributes Uses export-ignore to keep Library Manager archives minimal.
.claude/skills/verify-examples/SKILL.md Documents example compilation verification procedure.
.claude/skills/release/SKILL.md Documents release preconditions/tagging procedure.
.claude/skills/check-api-sync/SKILL.md Documents API consistency audit across header/cpp/README/keywords.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/Countimer.h
Comment on lines 125 to +127
char _formatted_time[10];
CountType _countType;
char _formatted_time_ms[13];
CountType _countType = COUNT_NONE;
Comment thread src/Countimer.cpp
Comment on lines 163 to +165
// timer is running only if is not completed or not stopped.
if (_isCounterCompleted || _isStopped)
{
Comment thread src/Countimer.cpp
Comment on lines +216 to 219
void Countimer::countUp(uint32_t elapsed)
{
if (_currentCountTime < _countTime)
if (_currentCountTime + elapsed < _countTime)
{
Comment thread CLAUDE.md

## What this is

Countimer is a single-class Arduino library (`category=Timing`) for non-blocking timers and counters. The entire implementation is `src/Countimer.h` / `src/Countimer.cpp`. There is no host-side build, test runner, or CI — it is consumed as an Arduino IDE library.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f62fdd34aa

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/Countimer.h
bool _isStopped = true;
char _formatted_time[10];
CountType _countType;
char _formatted_time_ms[13];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Resize the millisecond time buffer

When the timer is configured for 100 hours or more, getCurrentTimeWithMillis() needs 13 visible characters plus the NUL terminator (for example, 100:00:00.123), but this buffer only has 13 bytes. Because hours are allowed up to 999, the new millisecond formatter truncates valid values such as 100:00:00.123 to 100:00:00.12; make the buffer at least 14 bytes.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants