Bengle integrated scale calibration wizard - #6
Open
ChampionDesigns wants to merge 5 commits into
Open
ChampionDesigns wants to merge 5 commits into
ChampionDesigns wants to merge 5 commits into
Conversation
A Bengle exposes an extra BLE characteristic carrying a superset of ShotSample at higher precision, plus a milk probe and integrated-scale fields the stock packet has no room for. 28 bytes, big-endian, matching the firmware's T_BengleShotSample and decodeBengleShotSample in decentespresso/decaid. ShotSample (0xA00D) keeps its stock v1 layout on every machine, a Bengle included, so a stock build talking to a Bengle still works and this app talking to a DE1 still works, with no negotiation on the shared packet. Weight is SIGNED (S16P4). It is net of tare, so an unloaded platform after a tare reads negative; clamping at zero would hide a real reading. from_shotvalue splits into from_shotvalue / from_bengleshotvalue and a shared _apply_shotvalue. The stale-frame guard added by decentespresso#343 moves into the shared body, so it now protects the 0xA013 path too. The superset-only fields are picked up with [info exists]. On a Bengle the 0xA00D dispatch is gated off: it still streams, but charting both would double-sample with broken intersample timing. Receiving 0xA013 pins the protocol to v2 immediately, closing the window between connect and the model MMR read. The enable is gated on the characteristic being present in ::cinstance. That gate is load-bearing: on a DE1 the enable would throw on the unset instance, and the vital-retry path re-runs a failed vital command every 500 ms WITHOUT advancing the FIFO, stalling the whole BLE queue. gui.tcl normalises sample-to-sample deltas to their 5 Hz-equivalent magnitude using the measured intersample time. The chart math was implicitly tuned for 5 Hz; without this the delta trace and the diff_flow_rate_text readout scale with the notify rate. Falls back to the raw delta when the event carries no intersample time. The milk probe lands here too: ::de1(milk_temperature), a steam_milk_temperature chart vector, and milktemp / milktemp_text. 0 means no probe. set_target_milk_temp is gated and clamped to 0-85 C, matching BengleSteamMmr.targetMilkTemp in decaid. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The machine only wakes, sleeps and pre-warms while the tablet app is running and connected. A Bengle can do all of it itself. This gives the firmware what it needs. CupWarmerMode 0x008038AC RAM only, re-sent every connect MatHeaterDrivePct 0x008038B4 read-only MatTempFault 0x008038B8 read-only InactivitySleepTimeout 0x008038BC minutes, 0-240 SetLocalTimeOfWeek 0x008038C0 seconds since Sunday, 0-604800 ScheduleEntry 0x008038C4 packed (dow<<22)|(start<<11)|end ScheduleControl 0x008038C8 0 clear+disable, 1 enable MatPreheatEnable 0x008038D0 persisted MatPreheatLeadMin 0x008038D4 persisted, 0-120 Every address, clamp and the schedule packing match decentespresso/decaid. There is no battery-backed RTC. The firmware keeps a software wall clock, seeded on connect and re-sent every 30 minutes. A power cut loses it and the next connection re-seeds it; until then only the inactivity timer runs, so the machine can still sleep itself but cannot wake on schedule. Schedule sources are the D_Scheduler plugin's per-weekday wake times and the built-in scheduler's keep-warm window. They cannot double up: the plugin clears scheduler_enable. Pre-warm is the firmware's job. With MatPreheatEnable set it runs the mat from MatPreheatLeadMin minutes before a scheduled wake with no tablet connected. Write order follows decaid: enabling sends the lead first so the firmware never acts on a stale one; disabling clears the enable first. CupWarmerMode is deliberately sent as 0 on every connect. The warmer turns on only when the user asks or the pre-warm fires -- a machine does not start heating by itself after a blackout. utils.tcl resets the flag at app start for the same reason. Adds the cup warmer page as page 4 of the calibration flow, with live status from MatHeaterDrivePct and MatTempFault. Nothing requested those two reads before, so that status could never update; get_cupwarmer_status now asks for them on connect. Corrects four addresses in the page's header comment, each of which named the register one slot below the real one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A Bengle has a scale in the machine, with no BLE peripheral and no handle. Its weight and gravimetric flow arrive on 0xA013. Every scale check in the app is really a check for a paired BLE address, so on a Bengle the weight readouts return empty, the stop-at-weight slider is hidden, and the timer falls back to volumetric text while a working scale streams the whole time. _apply_shotvalue feeds Weight into ::device::scale::process_weight_update, the same entry point all fourteen BLE scale drivers use. That pipeline owns the weight history, the filtered weight and flow, the scale_stop_at_half_shot two-cup scaling, tare-completion detection, the watchdog, the app-side stop-at-weight check and drink-weight recording. Setting ::de1(scale_weight) directly instead writes the pipeline's outputs and skips all of it. GFlow, the firmware's own gravimetric flow, is NOT used for scale_weight_rate. The pipeline derives flow from the weight history as it does for every other scale. GFlow is kept on ::de1(integrated_scale_flow) for the comparison chart; switching to the firmware estimate wants a bench comparison first. ::device::scale::tare selects on scale_type, which a Bengle does not have, so the Bengle case is handled before the switch and writes ScaleTare (0x0080388C). This matters more than a tare button: tare is called automatically before every espresso and hot-water pour when a cup is on the platform, from the HotWater state handler, and from any profile step whose message contains "tare". set_end_of_shot_weight writes the per-profile target to EndOfShotWeight (0x00803864, grams x100, clamped 0-1000000) on every frame upload, so the machine-side target follows the loaded profile. Writing 0 clears one left on disk by a previous profile. Three chart vectors record the integrated series beside the existing ones so the two sources can be compared. On a DE1 they stay empty. The Visualizer payload maps by protocol. On v1 nothing changes. On v2 the integrated series fill by_weight and weight, and a paired BLE scale is emitted as by_weight_external / weight_external rather than dropped. by_weight_raw is emitted on both, as today. sensor_lag selects on scale_type, so a Bengle falls to the 0.38 s BLE default. An integrated scale should be lower. Left at the default rather than guessed; it needs measuring. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
# Conflicts: # de1plus/de1_comms.tcl
Seven-step wizard driving the firmware's calibration state machine over MMR, plus the calibrate4 page that presents it. ScaleCalCmd W 0x00803880 0 abort, 1 zero, 2 latch ScaleCalState R 0x00803884 packed U32 ScaleCalWeight RW 0x00803888 grams x10 ScaleCalState packs Step(31:24) DetectedCell(23:20) SubState(19:16) SecondsRemaining(15:8) Status(7:0). Step values are 0,1,2,4,5,6 -- there is no step 3. Addresses, packing, command values and every enum match decentespresso/decaid, the only other implementation of this word. Steps 3 and 4 do not ask which cell is which: the firmware reports DetectedCell from where the weight was placed. ScaleTare is not added here. It lives in de1_comms.tcl as set_bengle_scale_tare, added by the integrated-scale PR, because the ordinary scale tare path needs it whether or not this wizard ships. The reference mass is bounded to 1 g - 10 kg, matching decaid and both reaprime skins. All nine firmware status codes map to distinct messages. The tare step polls for the firmware's own completion rather than declaring success a fixed delay after the write. Leaving via Ok aborts a run in progress rather than leaving the poll timer armed. This branch sits on both the integrated-scale PR (for the tare write) and the machine-autonomy PR (for the calibration-flow navigation). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
ben/machine-autonomy. Retarget tomainonce both have merged. 882 insertions, 10 files.Summary
The Bengle scale uses two load cells and needs a per-cell calibration. This adds a
seven-step wizard driving the firmware's calibration state machine over MMR, and the
calibrate4page that presents it.0x008038800x008038840x00803888There is no step 3. The set is 0, 1, 2, 4, 5, 6.
Addresses, packing, command values and every enum match
decentespresso/decaid, which isthe only other implementation of this word — the two reaprime skins reach the flow through
decaid's REST API rather than decoding it themselves.
The seven steps
Remove platform, zero cells, calibrate first cell, calibrate second cell, replace platform,
tare, verify.
Steps 3 and 4 do not ask which cell is which: the firmware reports
DetectedCellfromwhere the weight was placed, so the user puts it on one side and then the other in either
order.
Changes
scale_calibration.tcl— new file. The::scale_calnamespace: step state, firmwarestate from the last poll, a one-second poll timer that runs only while a measurement is
active, status and progress bound to the page, and validation of the reference mass.
pkgIndex.tcl,gui.tcl,de1_comms.tcl— package registration and requires.de1_comms.tclandbluetooth.tcl— decodeScaleCalStateandScaleCalWeightinboth MMR-read paths, since a read can arrive on either.
skins/default/— thecalibrate4page as page 5 of the calibration flow, and itsregistration in
standard_includes.tcl.ScaleTareis not added here. It lives inde1_comms.tclasset_bengle_scale_tare,added by the integrated-scale PR, because the ordinary scale tare path needs it whether or
not this wizard ships.
Bounds and status handling
The reference mass is bounded to 1 g – 10 kg, matching decaid and both reaprime skins.
All nine firmware status codes map to distinct messages. The tare step polls for the
firmware's own completion rather than declaring success a fixed delay after the write.
Leaving via Ok aborts a run in progress.
Known issues, not fixed here
Raised by a review of the series, recorded rather than fixed. Not reproduced on hardware.
abort_if_running, andenter_pagedoes notstop_polling. The 2 Hzupdate_verify_displaytimer may survive page exit and can beduplicated, each new loop orphaning the previous
poll_after_id. Exiting via Ok doesabort correctly.
is_bengle_modelis evaluated at skin-load time, so on a first-ever connect the pagemay not be registered. Same root cause as in the LED and autonomy PRs.
Impact on a DE1
The package loads and defines a namespace.
calibrate4is reachable only from the Benglecalibration flow. The two decode branches match addresses a DE1 never reports.
Test plan
scale_calibration.tclsources and runs end to end against stubs: page entry,reference-mass validation at both bounds and past them, state-word decode, every
error code, and the tare step.
are detected in either order.
this is the known issue above.
Testing
Manual verification and a stub harness. There is no automated test coverage for these Tcl
paths in the repo.