Allow external battery packs to drive battery percentage on RAK boards - #3338
Open
MFornander wants to merge 2 commits into
Open
MFornander wants to merge 2 commits into
MFornander wants to merge 2 commits into
Conversation
MFornander
force-pushed
the
dev-mf/rak13302-battery-telemetry-ca3ae3
branch
from
September 1, 2026 20:53
34d0618 to
846093e
Compare
Author
|
Doing one more manual bench test before submitting PR:
|
Wrap PIN_VBAT_READ / ADC_MULTIPLIER and the PWRMGT_* defines in #ifndef guards so build flags can redirect battery telemetry to another analog pin, e.g. a Voltaic V25/V50/V75 pack's USB-C SBU output (1/2 cell voltage) wired to the base board J11 AIN1 pin. Remove the unused Meshtastic-leftover battery defines from the rak3401 variant.h: nothing in the MeshCore, framework, or library compile closure references them, and the unconditional ADC_MULTIPLIER there would defeat both the new #ifndef default and any -D build flag (variant.h is included via Arduino.h before the board headers). Add a documented RAK_3401_repeater_voltaic example env that reports the pack's true cell voltage and keeps nRF52 power management active with LPCOMP wake rerouted to the SBU pin: sleep below 3.4V cell, wake once the pack recharges past ~3.7V. The rak4631 hunks are byte-identical to PR meshcore-dev#3328 by @andyshinn, which this change incorporates and extends. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MFornander
force-pushed
the
dev-mf/rak13302-battery-telemetry-ca3ae3
branch
from
September 29, 2026 04:45
846093e to
d908a3e
Compare
Add the RAK3401 to the supported boards table and document the #ifndef-guarded battery sense and power management defines on rak4631/rak3401, with the Voltaic SBU env as a worked example.
MFornander
marked this pull request as ready for review
September 29, 2026 06:17
Author
This branch has not been deployed
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.

Summary
Makes the RAK4631/RAK3401 battery sense overridable from build flags, so nodes powered by an external pack can report the pack's real charge instead of the (meaningless) on-board charger float voltage.
The motivating setup: a Voltaic V25/V50/V75 pack reports its charge level on the USB-C SBU pins as 1/2 of its internal cell voltage (Voltaic write-up). Wire that SBU pin to the RAK19007 J11 header pin 1 (AIN1 = P0.31), build with
-D PIN_VBAT_READ=31 -D ADC_MULTIPLIER=7200, and the node reports the pack's true cell voltage (~3.2V empty to ~4.2V full) through every existing path (stats-core, telemetry LPP voltage, companion app).Incorporates and supersedes #3328 — the
variants/rak4631hunks here are byte-identical to that PR. Credit to @andyshinn for the override mechanism; this PR extends it to the RAK3401 (1W Booster Kit) variant, where it needs one extra fix to work at all (see below), and adds a power-management escape hatch plus a documented example env.What changed
variants/rak4631/RAK4631Board.h,variants/rak3401/RAK3401Board.h—PIN_VBAT_READ/ADC_MULTIPLIERwrapped in#ifndefguards (same pattern as the rak3112 / heltec_v3 variants). Defaults unchanged.ADC_MULTIPLIERsemantics: reported millivolts at ADC full scale (3.6V), so3600reports the pin voltage as-is and7200doubles it for half-scale sources like the SBU pin.variants/rak4631/variant.h,variants/rak3401/variant.h—PWRMGT_VOLTAGE_BOOTLOCK,PWRMGT_LPCOMP_AIN,PWRMGT_LPCOMP_REFSELwrapped in#ifndefguards (the bootlock guard makes the already-documented "set to 0 to disable" actually settable per-env), plus a comment block decoding the LPCOMPREFSELregister values (0-6 = n/8 VDD, 7 = AREF, 8-15 = odd sixteenths).PWRMGT_LPCOMP_AINguard is load-bearing on currentdev:NRF52Board::configureVoltageWake()now selects the comparator input from thePWRMGT_LPCOMP_AINmacro directly rather than itsain_channelargument, so without the guardvariant.hwould silently overwrite a-D PWRMGT_LPCOMP_AIN=7build flag back to 3, and the wake comparator would keep watching the unused AIN0 divider instead of the pin actually being measured.variants/rak3401/variant.h— removed the unused Meshtastic-leftover battery block (BATTERY_PIN,BATTERY_SENSE_RESOLUTION*,AREF_VOLTAGE,VBAT_AR_INTERNAL,ADC_MULTIPLIER 1.73). This is required, not cosmetic — see the safety analysis below.variants/rak3401/platformio.ini— new documentedRAK_3401_repeater_voltaicexample env.docs/nrf52_power_management.md— adds the RAK3401 to the Supported Boards table (its power management was already implemented but not listed) and a "Build-Flag Overrides (RAK4631, RAK3401)" section documenting the five overridable defines, the rule thatPWRMGT_LPCOMP_AINmust move withPIN_VBAT_READ, and the Voltaic env as a worked example.Why deleting the rak3401 variant.h battery block is safe (and necessary)
variant.his included viaArduino.hbefore the board header in every translation unit, and its unconditional#define ADC_MULTIPLIER 1.73therefore wins against both the new#ifndefdefault (stock battery reads would becomeraw × 1.73 / 4096≈ 2mV) and any-D ADC_MULTIPLIER=...build flag (an in-file#defineoverrides a command-line define; the redefinition warning is hidden by the project-wide-w). Pre-PR the same shadowing existed harmlessly in the other direction — the board header's unconditional define silently replaced 1.73.-Hinclude trace on the real build command shows exactly onevariant.hopened —variants/rak3401/variant.h(the pinned meshcore-dev Adafruit_nRF52 framework fork contains no RAK variant to shadow it).cores/+libraries/, every library in.pio/libdeps/, and the repo'ssrc/+examples/finds nothing. The only occurrences anywhere are other variants' own copies (t1000-e, xiao, ikoka, heltec) in their own directories, never in a rak3401 build's include path.rak4631/variant.hnever had it; removing it restores parity.RAK_3401_repeaterfirmware built before and after this PR differs by exactly 3 bytes — RTClib's embedded__DATE__ __TIME__compile timestamp, which differs between any two builds of identical source. Section sizes and the full symbol table are identical.The example env
RAK_3401_repeater_voltaicextendsRAK_3401_repeaterand keeps nRF52 power management enabled, rerouted to the SBU input: below 3.4V pack cell voltage the node enters SYSTEMOFF instead of boot-flapping on a drained pack (weak morning sun → boot → 1W TX sags the pack → brownout → repeat), and LPCOMP wakes it once the pack recharges past ~3.7V cell (9/16 VDD at the pin; ~half charge, not full — the only usable REFSEL step between 3.3V and 4.1V given the SBU's ÷2 scaling).configureVoltageWakealso arms USB-detect, so plugging in wakes it for maintenance. Note the boot-voltage check only engages whenisExternalPowered()is false, i.e. when the node is not powered via USB VBUS (true for e.g. the RAK13302 external-5V input).The env is opt-in only: release builds select environments ending in
_repeater(build.sh get-repeater-firmwares-to-build), soRAK_3401_repeater_voltaicis not published as an official firmware.Testing
RAK_3401_repeater,RAK_3401_repeater_voltaic, andRAK_4631_repeaterall build clean ondev@5d266dcb;pio run -t envdumpconfirms every override lands inCPPDEFINES.NRF52Board.cppshows the LPCOMPPSELchannel resolves to 7 (the SBU input) inRAK_3401_repeater_voltaicand 3 (the stock divider) inRAK_3401_repeater.repeater,repeater_bridge_rs232_serial1/2,room_server,sensor,kiss_modem) produce firmware byte-identical to stockdevapart from the compile timestamp. The other six (companion_radio_usb/ble/ethernet,terminal_chat,repeater_ethernet,room_server_ethernet) only add libraries (base64, RAK13800-W5100S), and no build flag or source insrc/,examples/orlib/defines any of the five guarded names, so every guard takes its default there too.stats-corereportsbattery_mv≈ 2× the SBU voltage measured with a meter, i.e. the pack's cell voltage (> 4 V on a charged pack), where the stock build reports the charger float voltage (4321 mV with no LiPo). The SYSTEMOFF / LPCOMP wake cycle has not yet been exercised on hardware.