Skip to content

Xiaomi S400: use 50 kHz for estimation equations - #1508

Open
miszobi wants to merge 1 commit into
oliexdev:masterfrom
miszobi:s400-bia-frequency-fix
Open

Xiaomi S400: use 50 kHz for estimation equations#1508
miszobi wants to merge 1 commit into
oliexdev:masterfrom
miszobi:s400-bia-frequency-fix

Conversation

@miszobi

@miszobi miszobi commented Sep 3, 2026

Copy link
Copy Markdown

Problem

S400BodyComposition (added in #1367 / #1376, cc: @DanyPM ) feeds the high-frequency
impedance band to the Sun 2003 (TBW) and Janssen 2000 (SMM) equations. Both were
derived on 50 kHz single-frequency BIA, and the S400's high-frequency band is
250 kHz.

For my setup this caused FFM and TBW values to be pushed out of range and suppressed.

Change

compute() already computes rL (the corrected low-frequency band) for the
Hanai ECW step. This PR feeds rL to Sun 2003 and Janssen 2000 as well, instead
of rH.

Testing

./gradlew :app:testDebugUnitTest — full suite green. The new
usesLowFrequencyForPrediction test fails without the one-line fix.

Generated and reasoned through with AI. Validated and edited by a human.

The S400 is dual-frequency (50 / 250 kHz). Sun 2003 (TBW) and Janssen
2000 (SMM) were both derived on 50 kHz single-frequency BIA, but
S400BodyComposition.compute() fed them the high-frequency band — the
smaller of the two magnitudes after the Cole-Cole sort.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PzAUUMVb6dWAshRJ9U6RY5
@oliexdev

oliexdev commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Before I go further into this one, a few questions — I'd like to understand the change before judging it.

  1. After this change, does rHigh still feed any prediction? From reading compute() it looks like it's left with the Cole-Cole swap, the unreliableContact check and the empirical bone formula,
    which is why rH can be deleted. If that's right, TBW and ECW both come from the same resistance, and ICW = TBW - ECW is the difference of two equations on one input rather than something taken from
    the gap between the bands. How do you see that?

  2. ecwTbwRatio moves from 0.42–0.45 to 0.46–0.48 across all three reference subjects. Still inside the 0.30–0.55 guard, but what's your read on those values?

  3. Body fat rises by roughly 5 points for each reference subject (A 14.1 → 19.5 %, B 41.5 → 46.2 %, C 34.5 → 40.3 %), so every S400 user would see a step in their chart. Is that the intended magnitude?

  4. How did you arrive at the new §7.1–7.3 expected values — by running the modified code, or checked against the specification document from S400 : implement dual impedance measurements #1367/Mi scale 2 dual impedance #1376? I recomputed A and B by hand and they match the
    new implementation exactly (A: TBW 45.07, FFM 61.57, SMM 33.84; B: TBW 26.79), which is why I'm asking: the test docstring still describes them as "the spec's reference subjects".

  5. Can you say more about the case that triggered this — which values were suppressed, and what does the scale's own app report for the same weighing?

@DanyPM, since the pipeline and the spec are yours, your view on 1 and 4 would help a lot.

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