The number in the app is not
what the scale's own LCD shows, and that is deliberate. This BLE kitchen scale has a
faulty load cell that reads a steady ~16% low. Because calories scale
linearly with weight, we correct it in software before it ever reaches a
calorie figure. Here is exactly what we measured and the formula we derived.
We fit on 10 reference masses (21-1062 g), 5 reads each, centred on a spreader plate, scoring each
candidate by mean absolute error MAE = (1/n)Σ|ŷ − true|, n=10:
• raw (no fix): MAE 50.7 g (16.1%)
• two-parameter line ŷ = a + b·raw: a = +2.846 g, b = 1.1728 → MAE 4.9 g
• through-origin ŷ = k·raw: k = Σ(raw·true)/Σ(raw²) = 1 775 157 / 1 506 877 = 1.178 → MAE 5.1 g
The two are tied on MAE, but the line's +2.846 g intercept over-reads light items (a load-cell span error
is multiplicative), so we ship the through-origin model corrected_g = 1.178 · raw.
Validation: applying the unchanged 1.178 to 10 unseen objects (phone, battery, glass, remote,
cardboard, camera, toys) predicts them to 1.9 g mean error, so it captures the scale's real span, not a
water-specific fit; refitting on all 20 barely moves the slope (1.17804 → 1.17825).
Result: mean error 16% → ~3%, max error ~13 g; the residual is now the scale's own repeatability
(~10 g spread), i.e. the hardware noise floor. The app shows this corrected value; the LCD shows the raw one.
Hard limit ~5 g: a 3 g object read 0 on all 5 tries - below a ~4 g
detection floor the scale outputs zero, which no multiplicative correction can recover. So sub-5 g weights (and
their calories) are flagged as unreliable.
Source: scripts/eval/weights_cal.csv ·
fit by scripts/eval/weight_calibration.py (in the main CalEyeZ repo).