Skip to content

power saving: enable DCDC, reduce clock speeds and voltage#1539

Open
thomasabbott wants to merge 2 commits intomeshcore-dev:devfrom
thomasabbott:rp2040_powersave
Open

power saving: enable DCDC, reduce clock speeds and voltage#1539
thomasabbott wants to merge 2 commits intomeshcore-dev:devfrom
thomasabbott:rp2040_powersave

Conversation

@thomasabbott
Copy link

Power saving for the waveshare Pico hat. In my tests this reduces the Rx current into the pico Vsys from 32 mA to about 10 mA, and Tx current from 99 mA to 85 mA. (Measured at Vsys = 5 V. At 3.6 V all the currents are higher)

  1. use the lower power PFM mode of the pico SMPS.

  2. enable the SX1262 switching DC-DC converter. The board has the necessary inductor fitted. (rpi_picow circuit)

  3. detect USB power present and lower clock to 48 MHz.
    Otherwise, if on battery:
    system clock to 18 MHz
    move ADC to system PLL
    disable USB clock and PLL
    lower core voltage to 0.95 V

Futher possible savings:

  • Physically disabling the red power LED saves another 1.2 mA.
  • Adding __asm volatile ("wfi"); at the end of Dispatcher::loop() lets it sleep for a short time, but only saves another 0.5 mA. I've left this out as it requires a processor-specific change to Dispatcher.cpp.

The waveshare_rp2040_lora variant would also benefit from some of these changes, but it lacks USB power detection, so we couldn't go below 48 MHz. (waveshare_rp2040_lora circuit)

@fschrempf
Copy link
Contributor

@thomasabbott Just a quick question: Where does SX126X_REGULATOR get evaluated? I don't see it either in the Meshcore code nor in the RadioLib code. What am I missing?

Removed the DCDC regulator definition for SX1262. It's not used, not passed to Radiolib. DCDC is the default.
@thomasabbott
Copy link
Author

I'm sorry, it seems to be completely unused. DCDC is the default in Radiolib and this parameter isn't passed to it.

I thought I saw a modest power reduction when adding this, but I was in the middle of fighting a different (hardware) problem, and the radio wasn't starting successfully, and I didn't isolate this change.

  • Radiolib already defaults to using the DCDC converter. in Sx126x.h:
/*!  \param useRegulatorLDO Whether to use only LDO regulator (true) or DC-DC regulator (false). Defaults to false. */
int16_t begin(uint8_t cr, uint8_t syncWord, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO = false);
  • Meshcore doesn't pass the 9th parameter to radiolib. CustomSX1262.h:
int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo);

Now measuring just this change by forcing useLDO=true: the board uses 23.6 mA before clocks are adjusted, 5.8 mA afterwards. As the radio starts it jumps up to 9.4 mA (DCDC) or 13 mA (LDO).

So Meshcore's wrapper doesn't support the parameter, and Radiolib defaults to using DCDC. I'll remove it.

@JDat
Copy link

JDat commented Jan 31, 2026

Looks good as experimental/sample code, but not ready to push into production/dev branch yet. There should be configuration options in .ini file to disable this and run normally without power saving or other detection stuff.

@IoTThinks
Copy link
Contributor

@JDat We can share the same CLI "powersaving on/off" among MCUs.

@JDat
Copy link

JDat commented Feb 3, 2026

@JDat We can share the same CLI "powersaving on/off" among MCUs.

Exactly! There are common things for all platforms/variants and at the same time totally different hardware details (display/no display; BT/no BT etc). Things. I would like to see that hardware/platform/variant code stay in variants and meshcore specific code stay in src folder.

Power saving command in example repeater or companion, that commands call functions/classes for variants and detailed implementations stay in variants or platforms.
I am already considering to add things like Board.loop() into main loop, refactor "file system/config" stuff so no platform dependent code (for example #ifdef ES32 etc) exist in src and examples folder or at least it it exist in separate helper files. I experienced with this when I wanted to move from SPI1 to SPI0 and from Wire1 to Wite0 hardware on my MCU.

@thomasabbott
Copy link
Author

The changes are pretty specific to this variant.

  • While they'd work on the other RP2040 it lacks the USB detection pin, so it would be risky to drop the clock down below 48 MHz.
  • though I think it's possible to detect whether there's an active USB connection, but this would need lots of careful testing.
  • My code only checks for USB once, so if you plug in USB after powerup, you have to reboot the pico to see it.
  • The savings don't matter when USB is connected, so this is really only useful for a battery powered repeater.
  • I don't think there's any performance impact even at 12 MHz, and no real benefit going slower than that.

What do you suggest is the next step here?

  1. I could wrap the clock changes in an #ifdef and add a flag to the .ini file. Then at least it's available for experiments in an easy-to-use form.

  2. it could become an OTA console command for both RP2040 variants, switching to slow clocks (and back). Needs persistent storage. possible to "brick" your device, unless it has a recovery mode or USB detection or a startup delay or something. This would be nice but it's beyond me to implement.

(2) would be a continuation of (1) - shall I just do (1) to get started?

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.

4 participants