Skip to content

Release v2.2.0: rename to NewPingPlus, Teensy 4 support, yield() fix - #6

Open
jshaw wants to merge 3 commits into
masterfrom
claude/newpingplus-v2.2.0
Open

Release v2.2.0: rename to NewPingPlus, Teensy 4 support, yield() fix#6
jshaw wants to merge 3 commits into
masterfrom
claude/newpingplus-v2.2.0

Conversation

@jshaw

@jshaw jshaw commented Aug 13, 2026

Copy link
Copy Markdown
Owner

Renames the library from NewPingESP8266 to NewPingPlus and prepares it for submission to the Arduino Library Manager.

Verification

Check Before After
Host tests (make test) 52 pass 67 pass
Teensy 4.0 / 4.1 compile error OK
ESP8266 build 2 deprecation warnings 0 warnings
UNO / ESP32 / Teensy 3.2 OK OK, 0 warnings
Async example (ESP8266/ESP32) OK OK, 0 warnings
arduino-lint --library-manager submit clean clean

Rename + sync with NewPing v1.9.7

  • NewPingESP8266.{h,cpp}NewPingPlus.{h,cpp}; class and macros renamed
  • TRIGGER_WIDTH 12 µs, automatic one-pin mode detection, constructor drives the trigger pin LOW, protected members, PING_MEDIAN_DELAY 30000 µs
  • Examples converted .pde.ino, with 3.3 V divider and ESP8266 boot-pin warnings

Bug fixes found in pre-release review

yield() was compiled away on every platform. The header carried a #ifndef yield / #define yield() fallback, but every supported core declares yield() as a function, never a macro — so the guard was always taken and the empty macro replaced every yield() call in the library. The WDT/WiFi cooperation documented in v2.1.0 was silently inert. Verified on esp8266 3.1.2, esp32 3.3.8 and avr 1.8.8 with a #pragma message probe both before and after.

Teensy 4.x failed to compile. The i.MX RT1062 has 32-bit port registers that cannot be assigned to the volatile uint8_t* members the bitwise fast path uses (cannot convert 'volatile uint32_t*' to 'volatile uint8_t*'). Teensy 4 now uses the digitalWrite path; Teensy 3.x keeps the bitwise path.

ping_async() was non-functional in one-pin mode. The interrupt was attached before the trigger pulse, so with trigger_pin == echo_pin the library's own pulse fired the ISR, reported a bogus ~12 µs echo, and detached the interrupt before the real echo arrived. Two-pin behaviour is unchanged.

Also fixed:

  • ICACHE_RAM_ATTRIRAM_ATTR (deprecated on ESP8266 core 3.x), with a fallback for cores older than 2.5.0
  • set_temperature() shifted the configured range by 1 cm by recovering the max distance from _maxEchoTime instead of storing it
  • max_cm_distance + 1 overflowed 16-bit unsigned int on AVR, leaving the echo timeout at 0 so every ping returned NO_ECHO
  • Config macros are #ifndef-guarded so -D build flags apply. A sketch-level #define can never work across translation units — docs corrected (it also emitted a spurious "redefined" warning in user sketches)

Packaging

  • library.properties, .gitignore; examples/.DS_Store untracked
  • convert_mm() added to keywords.txt and the README API table; set_max_distance removed from keywords (it is protected)
  • CI workflow: host tests, arduino-lint, and a compile matrix over AVR, ESP8266, ESP32 and Teensy 3.2/4.0 — the Teensy 4 entry is what would have caught the blocker above

Testing

New regression tests cover the yield, set_temperature and clamping fixes. Each was mutation-tested: every fix was reverted in turn to confirm the suite actually fails. The first version of the clamping test passed against the broken code — the host's 32-bit unsigned int makes both orderings identical — so it was re-pointed at the now-observable _max_cm_distance member. The mock also counts yield() calls, so the compiled-away bug cannot return unnoticed.

Known limitation

ROUNDING_ENABLED=true remains an untested configuration — the test suite hardcodes truncation expectations and 11 tests fail under it. ping_mm() was made to honour the flag for consistency (it was the only converter ignoring it), but properly supporting the option needs the test expectations parameterized. The default (false) is unchanged and fully covered.

Not done here

  • No tag yet — the Library Manager requires a semver tag. Tag v2.2.0 after this merges so it points at the merge commit.
  • Hardware testing is incomplete. Only the Arduino UNO has been verified on real hardware; ESP8266, ESP32 and Teensy are compile-verified only. The yield() and one-pin ping_async() fixes are unverified on silicon.

🤖 Generated with Claude Code

jshaw and others added 3 commits August 13, 2026 10:13
Renames the library from NewPingESP8266 to NewPingPlus and prepares it for
submission to the Arduino Library Manager.

Renamed and synced with NewPing v1.9.7:
- NewPingESP8266.{h,cpp} -> NewPingPlus.{h,cpp}; class and macros renamed
- TRIGGER_WIDTH 12us, automatic one-pin mode detection, constructor drives
  the trigger pin LOW, protected members, PING_MEDIAN_DELAY 30000us
- Examples converted from .pde to .ino, with 3.3V divider and ESP8266
  boot-pin warnings

Bug fixes found in pre-release review:
- yield() was compiled away on every platform. The header carried a
  `#ifndef yield / #define yield()` fallback, but every supported core
  declares yield() as a function, never a macro, so the guard was always
  taken and the empty macro replaced every yield() call in the library.
  The WDT/WiFi cooperation documented in v2.1.0 was silently inert.
- Teensy 4.x failed to compile. The i.MX RT1062 has 32-bit port registers
  that cannot be assigned to the volatile uint8_t* members the bitwise
  path uses. Teensy 4 now uses the digitalWrite path; 3.x is unchanged.
- ping_async() was non-functional in one-pin mode: the interrupt was
  attached before the trigger pulse, so the library's own pulse on the
  shared pin fired the ISR, reported a bogus ~12us echo, and detached the
  interrupt before the real echo arrived.
- ICACHE_RAM_ATTR is deprecated on ESP8266 core 3.x; use IRAM_ATTR with a
  fallback for cores older than 2.5.0.
- set_temperature() shifted the configured range by 1cm by recovering the
  max distance from _maxEchoTime instead of storing it.
- max_cm_distance + 1 overflowed 16-bit unsigned int on AVR, leaving the
  echo timeout at 0 so every ping returned NO_ECHO. Clamp comes first now.
- Config macros are #ifndef-guarded so -D build flags apply. A sketch-level
  #define can never work across translation units; docs corrected.

Packaging:
- library.properties, .gitignore; examples/.DS_Store untracked
- convert_mm() added to keywords.txt and the README API table
- CI: host tests, arduino-lint, and a compile matrix over AVR, ESP8266,
  ESP32 and Teensy 3.2/4.0

Testing: 67 host tests pass (was 52); new regression tests cover the yield,
set_temperature and clamping fixes and were mutation-tested against the
broken code. Compiles warning-free on arduino:avr:uno,
esp8266:esp8266:nodemcuv2, esp32:esp32:esp32 and teensy:avr:teensy31,
teensy40 and teensy41. arduino-lint --library-manager submit reports no
errors or warnings.

Known limitation: ROUNDING_ENABLED=true remains an untested configuration;
the test suite hardcodes truncation expectations. Default is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The lint job failed with LP018 "Library name NewPingPlus not found in the
Library Manager index". The cause was `library-manager: update`, which
asserts the library is already indexed. NewPingPlus has not been submitted
yet, so `submit` is the correct mode -- it applies the rules for a new
submission instead.

Confirmed the name is genuinely unsubmitted rather than misnamed: neither
NewPingPlus nor NewPingESP8266 appears in library_index.json (only Tim
Eckel's NewPing), and arduino/library-registry lists no repository under
this account for it. So the rename does not violate the "names cannot
change after being added to the index" rule -- the old name was never in
the index. Added a comment to switch this back to `update` once the
registry PR merges.

Verified locally against the committed tree:
  arduino-lint --library-manager submit --compliance strict --project-type all
reports no errors or warnings.

Also bumped actions to Node 24 runtimes to clear the deprecation warning:
arduino-lint-action v1 -> v3 (same inputs, runs: node24), checkout v4 -> v5.
compile-sketches stays at v1; that is still its current major.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The Uno job failed inside the action itself:

  File "compilesketches.py", line 363, in sort_dependency_list
    if dependency[self.dependency_source_url_key].rstrip("/")...
  AttributeError: 'NoneType' object has no attribute 'rstrip'

The matrix assembled the platforms block from separate `platform` and
`url` keys. arduino:avr ships with arduino-cli and needs no source-url, so
that entry carried url: '' -- which renders as `source-url:` with a null
value. The action dereferences source-url unconditionally, so null crashes
it. Omitting the key entirely is the only way to express "no source-url",
which means the whole YAML block has to live in the matrix.

Every entry's rendered block is now parsed and asserted non-null in review;
the other five boards were unaffected because they all supply a real URL.

Also adds Teensy 4.1 to the compile matrix. The previous commit message
listed teensy41 among the verified targets, but only teensy31 and teensy40
were actually compiled. Teensy 4.1 is now verified locally (clean, no
warnings) and covered in CI.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

1 participant