Skip to content

FNK0104B: charging state inference is unvalidated on this charger #74

Description

@iamankushpandit

The battery percentage on the Freenove FNK0104B is believed correct: the divider is confirmed (GPIO9, ×2.0, from Freenove's own Sketch_05.1_Battery_Voltage) and GPIO9 is ADC1_CH8, so Wi-Fi does not disturb it.

The charging / discharging verdict is not validated. getChargingState() infers it from cell voltage alone — this board, like the E32R28T-1, brings no charge-status line out to a GPIO — and every constant it infers with was measured against a different charger.

Why the existing constants are suspect here

From src/hal/BoardPower.cpp, tuned on the E32R28T-1's TP4054:

  • V_CHARGER_HELD = 4.21 V — "no resting cell reaches this"
  • CHARGE_STEP_V — the per-sample step that makes the icon respond to a cable within ~2 s
  • CHARGE_WINDOW_MS = 45000 — the low-pass window for everything in between
  • CHARGE_FULL_V — guards the flat-window fallback

Measured on the FNK0104B so far:

Condition Reading
USB, no pack 4.09 – 4.16 V
USB + 3000 mAh pack fitted 3.93 V

At 3.93 V, V_CHARGER_HELD never fires, so the verdict falls through to the 45-second trend. Whether that produces the right answer on this charger is unknown. The icon may simply be wrong.

The one thing that must NOT be done

Do not add an isBatteryPresent(). It existed once, as a constant true. On the E32R28T-1 it was disproved by measurement (recorded in src/hal/BoardPower.cpp): pack+USB 4.224 V, USB with no pack 4.159 V, pack alone 4.066 V — the no-pack case sits between the other two, because the charger holds BAT at float voltage with or without a cell.

The same inversion is already visible on this board: 4.09–4.16 V with no pack against 3.93 V with one. No threshold separates them in either direction. Do not reintroduce the question in a new form or retune a constant to answer it.

V_SENSOR_MAX (4.50 V) means the ADC is faulty, not "no pack".

What needs doing

  1. Port env:batdiag to the ESP32-S3. It currently extends [esp32_common] (board = esp32dev), so it cannot be flashed to an S3 at all — the image carries a chip ID esptool refuses. A new [env:batdiag_fnk0104b] extending [esp32s3_common] with ${board_fnk0104b.build_flags} is the starting point. Note batdiag needs ARDUINO_USB_MODE=1 and ARDUINO_USB_CDC_ON_BOOT=1 on this board — it has no USB-UART bridge, so without them serial output goes nowhere.
  2. Work the pages it already has: NO-BATT (resolve what this charger does with no cell), CALIBRATE (confirm the ×2.0 divider against a meter) and LOG (CSV ms,raw,adc_mv,cell_mv,pct,state over a full discharge — the 3000 mAh pack makes this a long run).
  3. If the constants need to differ per board, they move into BatteryProfile and get filled in for all four boards in the same commit; tools/check_boards.py enforces that. If they turn out to be the same, say so in a comment with the measurements, so the next person does not re-ask.
  4. battery_diag.cpp keeps a deliberate copy of the charge-inference constants so that what it shows is what the product will do. CLAUDE.md is explicit: change one, change both.
  5. Update the FNK0104B limitations note in README.md and the battery section of src/hal/CLAUDE.md with whatever is measured.

Reference

  • Dev pack in use: 3000 mAh / 11.1 Wh, single-cell LiPo (3.7 V nominal), MX1.25 connector.
  • The E32R28T-1 measurements and the reasoning behind every existing constant are in the comment block at the top of src/hal/BoardPower.cpp. Read it before changing anything there.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is neededpriority: P3Wave 3 - features that need the wave-2 layout work first

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions