Skip to content

Integrated scale support for Bengle - #2

Open
ChampionDesigns wants to merge 1 commit into
ben/bengle-shot-samplefrom
ben/integrated-scale
Open

ChampionDesigns wants to merge 1 commit into
ben/bengle-shot-samplefrom
ben/integrated-scale

Conversation

@ChampionDesigns

Copy link
Copy Markdown
Owner

Filed inside the fork so the diff shows only this PR's own changes.
It will be re-filed against decentespresso/de1app once its base has merged there.

merges. 160 insertions, 9 files.

Summary

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.

The important detail

_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 estimates, 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 — which an earlier draft did — 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.

Changes

device_scale.tclis_connected returns true when the v2 protocol is active, which
is the honest answer: the scale is present and reporting, and there is no handle because
there is no peripheral. And ::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). That 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".

de1_comms.tclset_bengle_scale_tare, and set_end_of_shot_weight, which writes
the per-profile target to EndOfShotWeight (0x00803864, grams ×100, clamped 0–1000000)
on every frame upload. Writing 0 clears one left on disk by a previous profile.

gui.tcl, utils.tcl, shot.tcl, vars.tcl — three chart vectors recording the
integrated series beside the existing ones, and the weight readouts and pour-timer text so
the volumetric fallback applies only when there is no scale at all.

skins/default/de1_skin_settings.tcl — the stop-at-weight block is shown for a Bengle
as well as for a paired BLE scale.

Visualizer payload

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.

One value is not verified

::device::scale::sensor_lag selects on scale_type, so a Bengle falls to the 0.38 s
default meant for a BLE scale. An integrated scale reporting on the machine's own sample
stream should be lower. Left at the default rather than guessed. TODO (Ben): measure it.

Checked against decaid

decentespresso/decaid implements the same feature and agrees on the wire: the
EndOfShotWeight register, scale and clamp are identical, and ScaleTare takes the same
value at the same address. It reaches the result differently — it exposes the integrated
scale as a real Scale device, so the pipeline runs with no special case. This PR keeps the
app's existing shape and joins the pipeline at process_weight_update.

Impact on a DE1

is_connected falls through to the handle test. The bridge never runs. The tare branch is
not taken. The three vectors stay empty. set_end_of_shot_weight returns early. The
Visualizer key set is identical to main's.

Test plan

  • The v1 Visualizer payload key set is unchanged against main.
  • Pull a shot on a DE1 with a BLE scale paired. Confirm weight, flow-by-weight and
    stop-at-weight behave as before.
  • TODO (Ben): pull a shot on a Bengle with no BLE scale. Confirm the weight readout is
    live, the slider is shown, and the shot stops on target.
  • TODO (Ben): pull a shot on a Bengle with a BLE scale also paired.
  • TODO (Ben): put a cup on during warm-up. Confirm the automatic tare fires.
  • TODO (Ben): with scale_stop_at_half_shot on, confirm the reading doubles.
  • TODO (Ben): measure the integrated scale's sensor lag.

Testing

Manual verification only. There is no automated test coverage for these Tcl paths in the
repo.

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>
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