-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Low power detection sensor module for nRF52 & ESP32 #8778
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
46fa108 to
a6dd7d8
Compare
Using low power polling during intervaled wake ups (state_broadcast_secs set) or Nordics GPIO sense feature in shutdown mode if state_broadcast_secs unset (=0). Using free values of GPREGRET to distinguish between wakeup from timeout, GPIO event and cold boot. Fixing a potentially failing setting of GPREGRET before shutdown.
- fixed broken state message. it was reporting isDetected() instead of the actual state, so it was always '0' - added battery percentage to state messages - cleanup. shortened unnecessary long strings and debug/info messages
|
@rbomze Just FIY - I think NRF52 power consumption (in any mode) can be greatly reduced on many boards by enabling on-chip voltage regulators to work in DC-DC mode instead of LDO mode. AFAIK T114 board has LC filter onboard that allows to run REG1 in DC-DC mode (REG0 is not supported in that design) Worth trying - I'm planning to research that but no earlier than in a month as I other work in progress for NRF52. Also - I learned about it only today - many ESP32 models have "ultra low power CPU core" that may be a nice research area for stuff like Meshtastic. |
| // We booted fresh. Enforce sending on first detection event. | ||
| lastSentToMesh = -Default::getConfiguredOrDefaultMs(moduleConfig.detection_sensor.minimum_broadcast_secs); | ||
| } | ||
| if (!(sd_power_gpregret_clr(0, 0xFF) == NRF_SUCCESS)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some reason SD is initialized only on Bluetooth enable sequence. I will be fixing that in #8793 but maybe a quick workaround would be to init soft device early on boot to have one common API across firmware to avoid need to checking that constantly.
| // Choose the minimum wakeup time (config.power.min_wake_sec) depending to your needs. | ||
| // The least time should be 5s to send just the detection message. | ||
| // Choose 45s+ for comfortable connectivity via BLE or USB. | ||
| // Device Telemetry is sent after ~62s. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will it improve power usage if for example we sent also telemetry message (if needed of course given time periods elapsed) in the minimum (5s-10s) wakeup windows instead of keeping device up for whole minute just for the telemetry timer to trigger the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I question if device telemetry data (i mean the radio metrics) is any worth on a device which is sleeping most of the time, because no useful radio statistic can be acquired during that time.
When speaking about telemetry data in general (temperature sensors, etc), sure. It does help a lot. See my updated text on the PR description.
What would make a lot of sense is to have battery voltage information in every telemetry data, a single byte would be enough and the receiver can track the nodes battery state, instead clogging the airtime with an additional message.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Radio statistics of course not - but either environment statistics or device battery is useful. I know battery stats are part of the detection message but it can not be used with monitoring software looking for generic telemetry frames.
On device boot we already send NodeInfo - if the boot reason is wakeup and node is sensor, maybe it would be worth to send telemetry packet too instead of wasting battery to just wait for arbitrary number of seconds. This could be configurable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are 2 great use cases for the detection sensor:
- Alerting, like sensing a door/window using a reed switch or PIR
- In combination with another sensor for environmental metrics as a temper detector. Imagine you have a grey box measuring eg. temperature and humidity and you want to know if someone opens it up, rips it from its mounting, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand, one question: If I want to monitor some remote site with alarm detection and device is waking up periodically (in addition to GPIO alarm trigger) i need to keep it up at least for 70s in order to be able to see what battery I have left there, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to wait for the device metrics to be sent (which include the battery voltage) it would be, but not anymore. I added the battery voltage to the state broadcast.
The state broadcast was broken anyway. Instead of the state it reported hasDetectionEvent(), so it always reported "Friendlyname status: 0".
Now you can set it to 24h or 1 week and get "Friendlyname status: high, 56%"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So essentially we can set min_wake_secs to 5s, state_broadcast_secs to 24h and minimum_broadcast_secs to 10min and we get a nice alarm sensor.
The potentially possible 0.5uA are crazy low. Even if it would be 2uA, a tiny 100mA battery would last 5.7 years, if only monitoring.
The Nordic datasheet clearly states it uses 0.4uA when off and additional 100nA sensing one pin. So 0.5uA in total. What spoils the party is potentially the LDO in front of the nRF52 and other components.
The RAK 'Nordic nRF52840 BLE Core Module', seemingly on a baseboard, was measured by Haruki with 2uA in shutdown.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, thanks for explanation! I would suggest renaming "state_broadcast_secs" to "state_broadcast_interval". Same with minimum broadcast :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, thanks for explanation! I would suggest renaming "state_broadcast_secs" to "state_broadcast_interval". Same with minimum broadcast :)
I just renamed:
state_broadcast_secs -> state_broadcast_interval
minimum_broadcast_secs -> message_rate_limit
This all is now much more readable. I will PR to change the descriptions of the Apps and the Website too.
minimum_broadcast_secs was plain misleading or even wrong btw., because it also rate limited the detection messages.
src/platform/nrf52/main-nrf52.cpp
Outdated
| #endif | ||
|
|
||
| #ifndef DMESHTASTIC_EXCLUDE_DETECTIONSENSOR | ||
| // enforce the rules of minimum_broadcast_secs of the detectionSensorModule. simply by delaying deep sleep |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not use detection module - but I think at this exact point LoRa radio and other subsystems are already down. Does minimum broadcast secs parameter makes sense in such device condition or should it be enforced higher in doDeepSleep() before other subsystems are shut down?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are down - but what when we wake up 3 seconds later by GPIO and don't know the time on the nRF52?
Getting this whole thing working, especially with an nRF52 which has disabled RTC in shutdown, measuring the sleeptime of the ESP32, making, both, the beloved shutdown state of the nRF52 and low power mode possible made my head twist for a couple of days. Since today everything should work smoothly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I get it - I understood this as minimum wakeup time but this is different setting. Overall this is a good idea and work :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's all a bit confusing. Even the word 'minimum' itself - it should be throttling.
|
After second thought - maybe it's better way to not use softdevice functions at all (given SD is active only in certain scenarios) and just use raw registers. As SoftDevice has impact on RAM (and probably power usage) my initial comment about enabling softdevice early on boot is not valid. |
…ese wakeups caused by other modules
|
During development i learned that direct access to |
|
I know the ULP some bit. about 4 years ago i wrote a program in this limited assembly language to monitor a pin attached to a simple 433mhz on/off receiver. |
Good to know - I'll research that, thanks. I will check whether is is generic NRF52 issue or this firmware issue. Maybe in the end it will be still a good idea to enable SD at boot and just keep it there all the time. I'm having similar concerns with implementing PowerHAL layer where depending on usage sometimes softdevice is on and sometimes off. In my case accessing triggering |
I think i read in Nordics papers or their forum, that sd_power_*() functions are the only safe way to access these registers when SD is in operation. |
|
I have the perfect solution for the register. Macros: usage: Looks a bit bloated at first, but is still efficient. Unfortunately the registered are called GPREGRET and GPREGRET2 (as they added GPREGRET2 later), btw. it is available on most nRF5x, only the nRF51-Series seem to lack it. So if we want to use both registers in the future this distinction is necessary. |
|
I want to test the code thoroughly in the next days in conjunction with additional sensors attached. |
I had a little chat with ChatGPT about the registers and softdevice. Verdicts:
I remember that when i started to rewrite all the accesses to |
|
Yeah, looks good - you can also save flash size by making it a function to be called instead of preprocessor pasting it each time. Also I suppose we will be forced to keep SD enabled at boot because filesystem driver is buggy: While async wait is checking for sd being enabled - flash erase operation is not. I just guess no one just ever tested meshtastic NRF52 without bluetooth compiled in or fully disabled.... I will be enabling SD at boot anyway in my PR - so maybe we can just simplify all RF52 codebase and use sd_* functions and don't care about wrappers. What do you think? |
state_broadcast_secs -> state_broadcast_interval minimum_broadcast_secs -> message_rate_limit updated some comments, cleanup
|
@rbomze I did a research about soft device - unfortunately this is hard-baked in Bluetooth library and enabling it externally causes conflicts. So we need to use your idea about safe functions - maybe it's better to use dedicated method |
Calling Here's some macro even in case there is no called by We won't use GPREGRET2 anyway so soon. |
|
The only suspicion I have is that calling sd_power* when SD is not enabled may actually crash CPU sometimes without returning an error. This is what happens when you run initBrownout() on boot a d before bluetooth starts :( |
|
|
Yeah, sadly Adafruit lib does not try to check if SD is already enabled. Nordic claims that using NVIC_* methods is unsafe if SD is enabled because on soft reboot some registers and memory parts are left initialized and enabling SD again on boot may fail / crash device. Which may explain some bug reports in this repo. |
AdafruitBluefruit does this: |
Hello again! This pull request replaces PR #8766. Presented by @Columbo818 and myself, it enables nRF52- and ESP32-based nodes to run the DetectionSensor module in low or even shutdown power modes.
The code takes effect when the following conditions are met:
Update - The following variables were renamed in this PR due to their misleading names:
Its behavior is configurable via the Minimum Sleep Time, the State Broadcast Interval and
Minimum BroadcastMessage Rate Limit [or similar in the future].Minimum sleep time(min_wake_secs) determines how long the device stays awake after a detection (and also after cold boot).Message Rate Limit(message_rate_limit) determines the minimal time between reporting detection events.State Broadcast Interval(state_broadcast_interval), determines the interval between wake-ups, if desired.The nRF52 knows two low power states. A low power mode (down to 14uA) and a shutdown (0.5uA), while still sensing a pin for a desired state (LOW/HIGH) which leads to a bootup.
If a State Broadcast Interval is set it the device enters a low power loop polling the pin. With unset interval it first enters a low power delay to comply with the Rate Limit and later goes into shutdown offering a power consumption lower than the self-discharge any battery.
This is necessary as in shutdown there is no RTC and thus it is impossible to keep track of time to compare with a timestamp of the last message send (for Rate Limit).
ESP32 based devices enter a
deepSleep(..)while the (RTC-)GPIO is monitored via EXT0.*Only ESP32 with EXT0 like ESP32, ESPS32S2/3 are supported. ESP32C3/6 lack this feature and thus are not supported. They fall back to normal operation, if power saving and detection sensor are enabled. Except DIY devices there are no commercially available devices without EXT0. Using EXT1 would interfere with the User Button and it would be impossible to choose a desired wake up level (LOW/HIGH), as EXT1 applies to all specified PIN concurrently, including the User Button, which has a default pull-up/-down.
These power consumption measurements were done with a
Fluke 77IVdirectly attached to the battery, with internal pull-ups enabled:Heltec T114 V2 (nRF52):
(More precise measurements are not possible with my hardware)
Heltec WiFi LoRa 32 V2 (ESP32):
Haruki’s Meshtastic Experiments confirm the high power consumption of the
Heltec V2with a measured value of 2.68mA.Additional measurements of the ESP32 devices by the community are welcome.
In a nutshell: this PR makes it possible to run a detection sensor node at a remote location for months or even years on a small battery.
There is one thing that should be mentioned in the documentation and applies to all telemetry, metrics or sensing modules, which do allow low power mode. When activated concurrently and using power saving, race conditions with doSleep(..) occur. This code is designed to work quite well with other modules active, as a GPIO event will always be detected during sleep, but the parameters should be chosen the following:
🤝 Attestations
[✅] I have tested that my proposed changes behave as described.
[✅] I have tested that my proposed changes do not cause any obvious regressions on the following devices:
[✅] Heltec WiFi LoRa 32 (V2)
[✅] Heltec T114