Skip to content

Piezo buzzer, settings-clash guards, and brownout crash fix (v2.7.0)#1

Merged
bitbarista merged 4 commits into
masterfrom
feature/settings-clash-guards
Jun 8, 2026
Merged

Piezo buzzer, settings-clash guards, and brownout crash fix (v2.7.0)#1
bitbarista merged 4 commits into
masterfrom
feature/settings-clash-guards

Conversation

@bitbarista

Copy link
Copy Markdown
Owner

Brings the piezo buzzer feature, the settings-clash/auto-start hardening, and the buzzer brownout crash fix to master. Bumps version to 2.7.0.

Piezo buzzer

  • Non-blocking LEDC tone player with per-event toggles (master + per-event), persisted to NVS, exposed via /api/buzzer and Settings → Sound.
  • Differential (BTL) drive for higher volume; BUZZER_DIFFERENTIAL toggle for a single-ended A/B test without rewiring.
  • New Bottom - Piezo.3mf enclosure (base with a piezo cutout) — optional.

Brownout crash fix

Crashes at beep time were brownout resets — the bare ceramic disc is a near-short to the GPIOs on each edge of the differential drive, sagging the regulator. Fixes:

  • Hardware: 150 Ω series resistor per piezo lead (documented; validated on hardware — no crashes since).
  • Firmware: trigger() is now thread-safe (defer-only) so the async web task and loop() never touch the LEDC peripheral concurrently; null-pattern guard in update().
  • Diagnostics: esp_reset_reason() captured at boot, a 12-deep history persisted to NVS and surfaced via /api/device/info (survives the S3 USB-serial reset that would otherwise mask the cause).

Settings-clash guards & auto-start hardening

  • Manual tare now latches auto-tare's one-shot lock (fixes the milk-workflow double-tare).
  • Armed auto-start ignores jug placement (single-cycle weight step) so only real coffee flow starts the timer.
  • Auto-Tare ↔ Auto-Re-arm mutual exclusion (server + UI), dependency warnings, mobile-friendly tooltips, and improved first-run defaults (18 g dose, 1:2 ratio, auto-stop on).

Docs

  • USER_GUIDE: piezo wiring table + ASCII schematic block (150 Ω resistors + brownout rationale) and BOM entries, all marked optional.
  • README: new enclosure row (optional); softened the ".step for each .3mf" claim. ATTRIBUTION: piezo base flagged as a CC BY-NC-SA derivative.
  • flash.html: refreshed stale version fallback.

Release follow-ups (after merge)

  1. Tag v2.7.0 to trigger build-release.yml (regenerates the flash-page manifests/binaries).
  2. Manually run deploy-pages.yml — bot-push does not auto-trigger the Pages deploy.

🤖 Generated with Claude Code

bitbarista and others added 4 commits June 6, 2026 10:31
Audible feedback via a piezo disc on GPIO2/GPIO1. New Buzzer class is a
non-blocking LEDC tone player with NVS-persisted master + per-event enables,
surfaced as a "Sound (Buzzer)" settings card (GET/POST /api/buzzer) with
per-event toggles and tooltips rendered dynamically from the firmware list.

Events wired: target yield reached, smart-switch fired, armed, BLE
connect/disconnect, battery low, boot chime, and tare (fires on every
tap/hold/web tare, not just the first arm).

Differential (BTL) drive: the same LEDC channel is routed to GPIO1 inverted
via the GPIO matrix, so the disc sees ~6.6Vpp instead of 3.3Vpp (clearly
louder). Matrix is attached on play and detached/parked low on silence so the
disc idles at 0V (no standing DC bias).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Behavioural fixes:
- Manual tare (tap/web) now latches the auto-tare one-shot lock when a vessel
  is present, so auto-tare no longer re-fires as a manually-tared jug's milk
  crosses the threshold.
- Armed auto-start ignores vessel placement: a single-cycle weight step >=8g
  (impossible for espresso flow) is treated as a placement and blocked until
  the scale returns to baseline, so weighing milk while armed won't start the
  timer. Real coffee flow (gradual rise) still auto-starts.

Settings clash prevention:
- Auto-Tare on Placement and Cup-Weight Auto Re-arm are now mutually exclusive
  (they both manipulate the zero reference). Enforced server-side in the POST
  handlers and reflected in the UI (toggling one disables the other, with an
  inline explanation).
- Dependency feedback: Smart Switch warns when Target Yield Ratio is 0 or no
  dose is set; Target Yield Ratio warns when no dose is set. Previously these
  silently did nothing.

First-run experience / defaults (fresh install or settings reset only):
- Dose defaults to 18g, Target Yield Ratio to 1:2, Auto-Stop on Flow Cessation
  to ON, so the hands-free pipeline works out of the box.
- First-run OLED hint (only when no cup weight saved) explains the hold-tare
  gesture; armed screen shows "Set dose" instead of "Ready!" if yield isn't
  configured.

UI:
- Settings tooltips now work on mobile (tap) as well as desktop (hover),
  replacing native title= which didn't show on touch.
- /api/reset-nvs now clears all settings namespaces (preserving WiFi by
  default; wifi=yes to also clear credentials).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Armed beep polled isArmed() for a false->true edge, but a re-arm while
already armed (true->true) has no edge, so re-arming via the auto-re-arm path
or a second hold-tare was silent even though the OLED showed "ARMED".

Mirror the tare-beep fix: Display::arm() sets an armJustHappened strobe,
polled via wasArmCompleted() in the main loop, so every arm/re-arm beeps
regardless of prior state.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Crashes since the piezo was added were brownout resets: the bare ceramic
disc presents a near-short to the GPIOs on each edge of the differential
drive, sagging the regulator. The hardware fix is a 150R series resistor
per lead; this commit covers the firmware and documentation side.

Firmware:
- Buzzer: make trigger() thread-safe (defer-only) so the async web task
  and loop() never touch the LEDC peripheral concurrently, and guard
  against a null pattern in update(). Add a BUZZER_DIFFERENTIAL toggle
  for a single-ended A/B test without rewiring.
- Capture esp_reset_reason() at boot, persist a 12-deep history to NVS,
  and surface it via /api/device/info (survives the S3 USB-serial reset
  that would otherwise mask the real reason).

Docs / hardware:
- USER_GUIDE: piezo wiring table + schematic block (150R resistors and
  brownout rationale) and BOM entries, all marked optional.
- README: list the new Bottom - Piezo enclosure (optional) and soften
  the ".step for each .3mf" claim. ATTRIBUTION: note the piezo base is a
  derivative (CC BY-NC-SA change indication).
- flash.html: refresh the stale v2.2.0 fallback.

Bump version to 2.7.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@bitbarista bitbarista merged commit 05d3ebd into master Jun 8, 2026
4 checks passed
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