Skip to content

Fix GPS stalls and charging icon; add replay viewer, v0.1 Qwiic pocket, Stone B2 case - #2

Merged
jewbetcha merged 5 commits into
mainfrom
gps-stall-charging-replay-stone
Oct 8, 2026
Merged

jewbetcha merged 5 commits into
mainfrom
gps-stall-charging-replay-stone

Conversation

@jewbetcha

Copy link
Copy Markdown
Member

Firmware

  • GPS stalls (laggy dial, missed clicks). The u-blox library sometimes misreads the module's bytes-available count and reads ~32 KB of junk, which freezes the loop for ~1 s every ~2 s. gps.h now wraps the I2C bus and clamps the count to 512 bytes. Measured on hardware: worst loop went from ~1000 ms to under 30 ms at 400 kHz, and every tap in a 32-press test registered.
  • Charging icon. It used only the fuel gauge's charge rate, which is slow and often hibernating. The gauge now stays awake while running (defaults are restored at power-off), is polled every 1 s, and plug/unplug is detected from the cell-voltage step. The charge rate is a fallback once it has settled. The host sim covers plug, unplug and a lagging charge rate.

Case

  • v0.1: a pocket bulges out of the top wall behind the GPS's top-edge Qwiic port, so it can take a plug. The zip-tie anchor moves to the other side of the SMA. shell.stl is re-exported.
  • case/concepts/: concepts A (Grip) and B (Stone), with a shared cart/strap mount, and Stone B2: a layered version at 63 x 75.5 x 32.6 mm. B2 has print-oriented STLs, fit checks that include screws and inserts, and a "Printing B2" README section. B2 hasn't been test-printed.

Tools

  • tools/replay/: a round replay viewer. Drop a geojson/csv export on it to step through a round on a satellite map, with a scorecard and club stats. Its built-in sample is synthetic, and personal exports in rounds/ are gitignored. Tests: node tools/replay/parse.test.mjs.

Testing

  • Host sim (make -C firmware/test): 0 failures. Firmware compiles for the Thing Plus ESP32-S3, and it's flashed and running on the device.
  • Replay parser tests pass, and the viewer was checked in headless Chrome.
  • B2 fit checks show zero overlap, and a deliberate-failure case trips them. All B2 STLs are manifold and slice cleanly in Bambu Studio's CLI.

🤖 Generated with Claude Code

jewbetcha and others added 5 commits October 8, 2026 10:00
The icon came only from the MAX17048's charge rate, polled every 10 s. That
estimate is heavily filtered, reads ~0 when plugged in near full, and the
gauge hibernates (45 s sampling) whenever |rate| < ~27 %/hr. Keep the gauge
awake while running (restore its default thresholds at power-off), poll every
1 s, and detect plug/unplug from the cell-voltage step, falling back to the
charge rate only once it has settled. Sim covers plug, unplug and lagging rate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The u-blox library occasionally misreads the module's bytes-available count
as tens of thousands of bytes and reads them all: about a second at 400 kHz,
during which nothing polls the dial or redraws, and the junk causes checksum
errors. Measured on hardware: worst loop ~1000 ms every ~2 s. Wrap the I2C bus
to clamp the count to 512 bytes (a real fix is ~100). Worst loop is now under
30 ms at full bus speed and every tap registers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
J4 sits beside the SMA, which pins the board 0.6 mm from the top wall, so the
second GPS port (needed for the Thing Plus -> GPS -> OLED chain) couldn't take
a plug. Add a pocket bulging out of the top wall behind J4 (5 mm from the board
edge, 45-degree underside so it prints without supports) and move the zip-tie
anchor to the other side of the SMA port. Re-export shell.stl.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tools/replay/index.html loads a geojson or csv export on a satellite map and
replays the round shot by shot with a scorecard and per-club stats. Works from
file://. The built-in sample is synthetic (a real round moved, rotated and
re-timed); personal exports in rounds/ are gitignored. Parser tests:
node tools/replay/parse.test.mjs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Concepts A (Grip) and B (Stone) with a shared TwistLock cart/strap mount, and
B2, a layered Stone (63 x 75.5 x 32.6 mm without the mount socket). B2 has
print-oriented STLs in case/concepts/stl_b2, fit checks for parts, screws and
inserts, and a Printing B2 section with hardware, assembly and items to
measure before printing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 8, 2026 17:03

Copilot AI 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.

🟡 Changes recommended

Charging error handling, hard-off power behavior, replay autoplay, and STL export failure propagation need correction.

5 open findings
What changed in this PR

Improves firmware responsiveness and charging detection, adds a browser-based round replay viewer, and expands enclosure designs.

Changes:

  • Clamps faulty GPS I²C byte counts and revises charging detection.
  • Adds GeoJSON/CSV replay parsing, visualization, samples, and tests.
  • Adds the Qwiic pocket and Stone/Grip enclosure concepts with B2 exports.
File Description
.gitignore Ignores local round exports.
firmware/​README.md Documents the replay viewer.
firmware/​shot_tracker/​app.cpp Implements charging detection and gauge power handling.
firmware/​shot_tracker/​config.h Adds charging thresholds and polling intervals.
firmware/​shot_tracker/​gps.h Clamps GNSS I²C reads.
firmware/​test/​sim.cpp Tests charging transitions.
firmware/​test/​stubs/​SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library.h Extends fuel-gauge simulation.
firmware/​test/​stubs/​SparkFun_u-blox_GNSS_v3.h Supports the custom GNSS bus.
tools/​replay/​index.html Implements the replay viewer and parser.
tools/​replay/​parse.test.mjs Tests replay parsing and statistics.
tools/​replay/​README.md Documents viewer usage.
tools/​replay/​samples/​sample-round.csv Adds a synthetic CSV round.
tools/​replay/​samples/​sample-round.geojson Adds a synthetic GeoJSON round.
case/​README.md Documents the Qwiic pocket.
case/​cad/​shot_tracker_case.scad Models the v0.1 Qwiic pocket.
case/​concepts/​README.md Documents enclosure concepts and B2 printing.
case/​concepts/​concept_a_grip.scad Models the Grip concept.
case/​concepts/​concept_b_stone.scad Models the Stone concept.
case/​concepts/​concept_b2_stone.scad Models print-ready Stone B2 parts.
case/​concepts/​export_b2.sh Exports B2 STLs.
case/​concepts/​lib/​components.scad Defines component geometry.
case/​concepts/​lib/​mount.scad Defines the TwistLock mount.
case/​concepts/​lib/​shape.scad Adds shared shape helpers.
case/​concepts/​lineup.scad Builds enclosure comparison views.
case/​concepts/​mount_kit.scad Builds mount-kit views.
case/​concepts/​render_all.sh Regenerates renders and STLs.
case/​concepts/​result.json Records slicer output.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +9 to +10
"$OS" --backend=manifold -D "part=\"$p\"" "$@" -o "stl_b2/$p.stl" concept_b2_stone.scad 2>&1 \
| grep -E "Status|Genus|Volumes|WARNING|ERROR" | sed "s/^/ $p: /"
Comment on lines +737 to +739
// By default the gauge hibernates whenever |charge rate| < ~27 %/hr, which is
// nearly always on this load, and then only samples every 45 s.
if (fuelOk) fuel.disableHibernate();
lastFuel = now;
batteryPct = constrain((int)lround(fuel.getSOC()), 0, 100);
charging = fuel.getChangeRate() > 0.5f;
updateCharging(now, fuel.getVoltage(), fuel.getChangeRate());
Comment thread tools/replay/index.html
Comment on lines +967 to +969
var n = parseInt(hash.get('shot'), 10);
if (n > 1) goTo(n - 1, { instant: true });
if (hash.has('play')) play();
Comment on lines +15 to +17
// Lens section: straight sides from the back up to a shoulder just above the boards, then
// the sides lean 6 mm inward (40.6 deg) to a smaller face (left, right, bottom; not the top,
// where the SMA sits). Plan corners limited by the pouch corners (8.5 mm inside radius).
@jewbetcha
jewbetcha merged commit 219757d into main Oct 8, 2026
3 checks passed
@jewbetcha
jewbetcha deleted the gps-stall-charging-replay-stone branch October 8, 2026 19:41
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