Repository navigation
Fix GPS stalls and charging icon; add replay viewer, v0.1 Qwiic pocket, Stone B2 case - #2
Merged
Merged
Conversation
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>
There was a problem hiding this comment.
🟡 Changes recommended
Charging error handling, hard-off power behavior, replay autoplay, and STL export failure propagation need correction.
5 open findings
Preserve OpenSCAD failures through the export pipeline · New Ensure gauge hibernate configuration survives hard-off power loss · New Reject transient zero-voltage readings before updating charging state · New Fix autoplay deep links skipping the requested sample · New Update header geometry summary to match implemented design · New
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 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). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Firmware
gps.hnow 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.Case
shell.stlis 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 inrounds/are gitignored. Tests:node tools/replay/parse.test.mjs.Testing
make -C firmware/test): 0 failures. Firmware compiles for the Thing Plus ESP32-S3, and it's flashed and running on the device.🤖 Generated with Claude Code