mirror of
https://github.com/meshtastic/firmware.git
synced 2025-04-25 09:42:35 +00:00
light sleep seems to work well
This commit is contained in:
parent
beccc34ef1
commit
7a745c9e65
8
TODO.md
8
TODO.md
@ -2,6 +2,13 @@
|
|||||||
|
|
||||||
Items to complete before the first alpha release.
|
Items to complete before the first alpha release.
|
||||||
|
|
||||||
|
* document rules for sleep wrt lora/bluetooth/screen/gps. also: if I have text messages (only) for the phone, then give a few seconds in the hopes BLE can get it across before we have to go back to sleep.
|
||||||
|
* if the phone doesn't read fromradio mailbox within X seconds, assume the phone is gone and we can stop queing location msgs
|
||||||
|
for it (because it will redownload the nodedb when it comes back)
|
||||||
|
* don't enter light sleep while the screen is on
|
||||||
|
* any time we wake from light sleep, briefly blink the led
|
||||||
|
|
||||||
|
* turn light sleep on agressively (while lora is on but BLE off)
|
||||||
* retest BLE software update for both board types
|
* retest BLE software update for both board types
|
||||||
* default to enter deep sleep if no LORA received for two hours (indicates user has probably left the meshS)
|
* default to enter deep sleep if no LORA received for two hours (indicates user has probably left the meshS)
|
||||||
* article writeup for hackaday?
|
* article writeup for hackaday?
|
||||||
@ -99,6 +106,7 @@ other node. This would nicely allow distant nodes to propogate their position t
|
|||||||
* essentially everything in this variant becomes broadcasts of "request db updates for >time X - for _all_ or for a particular nodenum" and nodes sending (either due to request or because they changed state) "here's a set of db updates". Every node is constantly trying to
|
* essentially everything in this variant becomes broadcasts of "request db updates for >time X - for _all_ or for a particular nodenum" and nodes sending (either due to request or because they changed state) "here's a set of db updates". Every node is constantly trying to
|
||||||
build the most recent version of reality, and if some nodes are too far, then nodes closer in will eventually forward their changes to the distributed db.
|
build the most recent version of reality, and if some nodes are too far, then nodes closer in will eventually forward their changes to the distributed db.
|
||||||
* construct non ambigious rules for who broadcasts to request db updates. ideally the algorithm should nicely realize node X can see most other nodes, so they should just listen to all those nodes and minimize the # of broadcasts. the distributed picture of nodes rssi could be useful here?
|
* construct non ambigious rules for who broadcasts to request db updates. ideally the algorithm should nicely realize node X can see most other nodes, so they should just listen to all those nodes and minimize the # of broadcasts. the distributed picture of nodes rssi could be useful here?
|
||||||
|
* possibly view the BLE protocol to the radio the same way - just a process of reconverging the node/msgdb database.
|
||||||
|
|
||||||
# Pre-beta priority
|
# Pre-beta priority
|
||||||
|
|
||||||
|
87
src/main.ino
87
src/main.ino
@ -66,10 +66,26 @@ esp_sleep_source_t wakeCause; // the reason we booted this time
|
|||||||
* We leave CPU at full speed during init, but once loop is called switch to low speed (for a 50% power savings)
|
* We leave CPU at full speed during init, but once loop is called switch to low speed (for a 50% power savings)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void setCPUFast(bool on) {
|
void setCPUFast(bool on)
|
||||||
|
{
|
||||||
setCpuFrequencyMhz(on ? 240 : 80);
|
setCpuFrequencyMhz(on ? 240 : 80);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setLed(bool ledOn) {
|
||||||
|
#ifdef LED_PIN
|
||||||
|
// toggle the led so we can get some rough sense of how often loop is pausing
|
||||||
|
digitalWrite(LED_PIN, ledOn);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef T_BEAM_V10
|
||||||
|
if (axp192_found)
|
||||||
|
{
|
||||||
|
// blink the axp led
|
||||||
|
axp.setChgLEDMode(ledOn ? AXP20X_LED_LOW_LEVEL : AXP20X_LED_OFF);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void doDeepSleep(uint64_t msecToWake)
|
void doDeepSleep(uint64_t msecToWake)
|
||||||
{
|
{
|
||||||
DEBUG_MSG("Entering deep sleep for %llu seconds\n", msecToWake / 1000);
|
DEBUG_MSG("Entering deep sleep for %llu seconds\n", msecToWake / 1000);
|
||||||
@ -94,15 +110,11 @@ void doDeepSleep(uint64_t msecToWake)
|
|||||||
digitalWrite(VEXT_ENABLE, 1); // turn off the display power
|
digitalWrite(VEXT_ENABLE, 1); // turn off the display power
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LED_PIN
|
setLed(false);
|
||||||
digitalWrite(LED_PIN, 0); // turn off the led
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef T_BEAM_V10
|
#ifdef T_BEAM_V10
|
||||||
if (axp192_found)
|
if (axp192_found)
|
||||||
{
|
{
|
||||||
axp.setChgLEDMode(AXP20X_LED_OFF); // turn off the AXP LED
|
|
||||||
|
|
||||||
// No need to turn this off if the power draw in sleep mode really is just 0.2uA and turning it off would
|
// No need to turn this off if the power draw in sleep mode really is just 0.2uA and turning it off would
|
||||||
// leave floating input for the IRQ line
|
// leave floating input for the IRQ line
|
||||||
|
|
||||||
@ -143,8 +155,7 @@ void doDeepSleep(uint64_t msecToWake)
|
|||||||
// FIXME, disable internal rtc pullups/pulldowns on the non isolated pins. for inputs that we aren't using
|
// FIXME, disable internal rtc pullups/pulldowns on the non isolated pins. for inputs that we aren't using
|
||||||
// to detect wake and in normal operation the external part drives them hard.
|
// to detect wake and in normal operation the external part drives them hard.
|
||||||
|
|
||||||
// FIXME - use an external 10k pulldown so we can leave the RTC peripherals powered off
|
// We want RTC peripherals to stay on
|
||||||
// until then we need the following lines
|
|
||||||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
||||||
|
|
||||||
#ifdef BUTTON_PIN
|
#ifdef BUTTON_PIN
|
||||||
@ -162,6 +173,41 @@ void doDeepSleep(uint64_t msecToWake)
|
|||||||
esp_deep_sleep_start(); // TBD mA sleep current (battery)
|
esp_deep_sleep_start(); // TBD mA sleep current (battery)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "esp_bt_main.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enter light sleep (preserves ram but stops everything about CPU).
|
||||||
|
*
|
||||||
|
* Returns (after restoring hw state) when the user presses a button or we get a LoRa interrupt
|
||||||
|
*/
|
||||||
|
void doLightSleep(uint32_t sleepMsec = 20 * 1000) // FIXME, use a more reasonable default
|
||||||
|
{
|
||||||
|
DEBUG_MSG("Enter light sleep\n");
|
||||||
|
uint64_t sleepUsec = sleepMsec * 1000LL;
|
||||||
|
|
||||||
|
setLed(false); // Never leave led on while in light sleep
|
||||||
|
|
||||||
|
// ESP docs say we must disable bluetooth and wifi before light sleep
|
||||||
|
if (esp_bluedroid_disable() != ESP_OK)
|
||||||
|
DEBUG_MSG("error disabling bluedroid\n");
|
||||||
|
if (esp_bt_controller_disable() != ESP_OK)
|
||||||
|
DEBUG_MSG("error disabling bt controller\n");
|
||||||
|
|
||||||
|
// We want RTC peripherals to stay on
|
||||||
|
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
|
||||||
|
|
||||||
|
gpio_wakeup_enable((gpio_num_t)BUTTON_PIN, GPIO_INTR_LOW_LEVEL); // when user presses, this button goes low
|
||||||
|
gpio_wakeup_enable((gpio_num_t)DIO0_GPIO, GPIO_INTR_HIGH_LEVEL); // RF95 interrupt, active high
|
||||||
|
esp_sleep_enable_gpio_wakeup();
|
||||||
|
esp_sleep_enable_timer_wakeup(sleepUsec);
|
||||||
|
esp_light_sleep_start();
|
||||||
|
DEBUG_MSG("Exit light sleep\n");
|
||||||
|
|
||||||
|
if (esp_bt_controller_enable(ESP_BT_MODE_BTDM) != ESP_OK)
|
||||||
|
DEBUG_MSG("error reenabling bt controller\n");
|
||||||
|
if (esp_bluedroid_enable() != ESP_OK)
|
||||||
|
DEBUG_MSG("error reenabling bluedroid\n");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enable modem sleep mode as needed and available. Should lower our CPU current draw to an average of about 20mA.
|
* enable modem sleep mode as needed and available. Should lower our CPU current draw to an average of about 20mA.
|
||||||
@ -426,6 +472,8 @@ void setup()
|
|||||||
|
|
||||||
// enableModemSleep();
|
// enableModemSleep();
|
||||||
setCPUFast(false);
|
setCPUFast(false);
|
||||||
|
|
||||||
|
// doLightSleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ledBlinker()
|
uint32_t ledBlinker()
|
||||||
@ -433,18 +481,8 @@ uint32_t ledBlinker()
|
|||||||
static bool ledOn;
|
static bool ledOn;
|
||||||
ledOn ^= 1;
|
ledOn ^= 1;
|
||||||
|
|
||||||
#ifdef LED_PIN
|
setLed(ledOn);
|
||||||
// toggle the led so we can get some rough sense of how often loop is pausing
|
|
||||||
digitalWrite(LED_PIN, ledOn);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef T_BEAM_V10
|
|
||||||
if (axp192_found)
|
|
||||||
{
|
|
||||||
// blink the axp led
|
|
||||||
axp.setChgLEDMode(ledOn ? AXP20X_LED_LOW_LEVEL : AXP20X_LED_OFF);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// have a very sparse duty cycle of LED being on, unless charging, then blink 0.5Hz square wave rate to indicate that
|
// have a very sparse duty cycle of LED being on, unless charging, then blink 0.5Hz square wave rate to indicate that
|
||||||
return isCharging ? 1000 : (ledOn ? 2 : 1000);
|
return isCharging ? 1000 : (ledOn ? 2 : 1000);
|
||||||
@ -508,6 +546,8 @@ void loop()
|
|||||||
if (!wasPressed)
|
if (!wasPressed)
|
||||||
{ // just started a new press
|
{ // just started a new press
|
||||||
DEBUG_MSG("pressing\n");
|
DEBUG_MSG("pressing\n");
|
||||||
|
|
||||||
|
//doLightSleep();
|
||||||
// esp_pm_dump_locks(stdout); // FIXME, do this someplace better
|
// esp_pm_dump_locks(stdout); // FIXME, do this someplace better
|
||||||
wasPressed = true;
|
wasPressed = true;
|
||||||
|
|
||||||
@ -553,5 +593,14 @@ void loop()
|
|||||||
|
|
||||||
// FIXME - until button press handling is done by interrupt (see polling above) we can't sleep very long at all or buttons feel slow
|
// FIXME - until button press handling is done by interrupt (see polling above) we can't sleep very long at all or buttons feel slow
|
||||||
msecstosleep = 10;
|
msecstosleep = 10;
|
||||||
|
|
||||||
|
bool bluetoothOn = false; // FIXME, leave bluetooth on per our power management policy (see doc)
|
||||||
|
|
||||||
|
// while we have bluetooth on, we can't do light sleep, but once off stay in light_sleep all the time
|
||||||
|
// we will wake from light sleep on button press or interrupt from the RF95 radio
|
||||||
|
if (!bluetoothOn && !is_screen_on())
|
||||||
|
doLightSleep(60 * 1000); // FIXME, wake up to briefly flash led, then go back to sleep (without repowering bluetooth)
|
||||||
|
else {
|
||||||
delay(msecstosleep);
|
delay(msecstosleep);
|
||||||
}
|
}
|
||||||
|
}
|
@ -51,6 +51,8 @@ OLEDDisplayUi ui(&dispdev);
|
|||||||
// A text message frame + debug frame + all the node infos
|
// A text message frame + debug frame + all the node infos
|
||||||
FrameCallback nonBootFrames[MAX_NUM_NODES + NUM_EXTRA_FRAMES];
|
FrameCallback nonBootFrames[MAX_NUM_NODES + NUM_EXTRA_FRAMES];
|
||||||
|
|
||||||
|
bool is_screen_on() { return screenOn; }
|
||||||
|
|
||||||
void msOverlay(OLEDDisplay *display, OLEDDisplayUiState *state)
|
void msOverlay(OLEDDisplay *display, OLEDDisplayUiState *state)
|
||||||
{
|
{
|
||||||
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||||
|
@ -12,3 +12,5 @@ void screen_start_bluetooth(uint32_t pin);
|
|||||||
|
|
||||||
// restore our regular frame list
|
// restore our regular frame list
|
||||||
void screen_set_frames();
|
void screen_set_frames();
|
||||||
|
|
||||||
|
bool is_screen_on();
|
||||||
|
Loading…
Reference in New Issue
Block a user