Add Low-Power Sleep for nRF52 Boards#1562
Conversation
|
You may want to add periodically wakeup as in the repeater needs to do periodically adverts. So this is to use main loop to execeute these three commands infinitely. |
It's unnecessary, this will wake to do anything required. It wakes every second on tick as well. This is SYSTEMON "sleep", more accurately it is putting the CPU into low power idle state (not executing) when there is nothing to do, and there is no requirement to schedule wake or anything. You could achieve slightly more current reduction by disabling "unused" peripherals but it's probably not worth the added complexity and possible trade off in stability. |
|
I'm running with firmware like this for months now on my companion, I just added an sd_app_evt_wait(); with guarded IF-s for nRF to the bottom of the main loop. @oltaco told me two calls will work better so I experimented with it: One time: Two times: Three times: third time adds diminishing returns, so we are maybe taking away time from real work there indeed two times is the sweet spot. first call returns instantly maybe because the pending timer event so it adds a small amount of sleep only. |
I didn't have a chance to investigate but it could be that the reason sd_app_evt_wait() wakes so soon compared to SEV(); WFE(); WFE(); is that we are still polling for BLE RX instead of being event driven. sd_app_evt_wait() checks the SoftDevice queue first and if there are pending jobs it does them instead of sleeping. So calling it twice lets it process the SoftDevice queue, and then the next call sleeps straight away which gives us more time asleep before the next SoftDevice event gets queued. At least that's my theory. That's why I wonder if we could change SerialBLEInterface to be fully event driven for RX like it is for TX maybe we could achieve even more sleep. I have been running the sleep code in this PR on my companions for a couple of days now and haven't noticed any issues. To do it I just added this to the companion main.cpp loop(): |
After testing this on my home repeater for a few days, I haven't noticed anything out of the ordinary with regards to missing packets. I wouldn't expect to either, given that all this does is causes the CPU to go idle when there's nothing to do. If anyone else wants to test either repeater or companion with you can try this branch https://github.com/oltaco/MeshCore/tree/nrf52-lowpower |
|
do we know how much can be saved by this? |
Idle power consumption is down by around 20-25% so it's pretty substantial! |
yeah, that can defo add-up on repeaters |
|
Wow, congratulation for the quick merge. |

Note: Draft PR, Testing required - Please test this PR on your NRF52 repeaters, it seems to work well from my initial testing and in theory shouldn't cause packets to be dropped but thorough testing is still required.I'm no longer considering this a draft PR as it's working fine for me. It would still be nice if some others could test it out though.
This PR implements proper low-power sleep for repeater firmware on NRF52 boards, reducing idle power consumption:
Repeater firmware: 6-7mA down to 5mA at 3.6v (after first advert is sent).
Companion firmware: Not yet integrated (see below)
Added NRF52Board::sleep() which uses __WFE() (Wait For Event) to put the CPU into idle whenever possible. CPU will automatically wake on any interrupt so there should be no effect on serial/lora/clock etc. This drops the number of main loops during idle from ~25000+/sec to ~1000/loops per second, because it wakes for every rtc.tick().
Includes the workaround for errata 87 which probably isn't necessary for repeaters but seems to be required for companions to go into idle.
Note on companions: I haven't added
board.sleep()to the main loop for companions, although I did test it briefly and found it to drop idle current draw from ~8-9ma to ~6ma at 3.6v. More testing would be welcomed for this as well.