light sleep seems to work well

1.2-legacy
geeksville 2020-02-21 04:57:08 -08:00
rodzic beccc34ef1
commit 7a745c9e65
4 zmienionych plików z 85 dodań i 24 usunięć

Wyświetl plik

@ -2,6 +2,13 @@
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
* default to enter deep sleep if no LORA received for two hours (indicates user has probably left the meshS)
* 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
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?
* possibly view the BLE protocol to the radio the same way - just a process of reconverging the node/msgdb database.
# Pre-beta priority

Wyświetl plik

@ -53,8 +53,8 @@ bool packetSent, packetQueued;
RTC_DATA_ATTR int bootCount = 0;
esp_sleep_source_t wakeCause; // the reason we booted this time
#define xstr(s) str(s)
#define str(s) #s
#define xstr(s) str(s)
#define str(s) #s
// -----------------------------------------------------------------------------
// Application
@ -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)
*
*/
void setCPUFast(bool on) {
void setCPUFast(bool on)
{
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)
{
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
#endif
#ifdef LED_PIN
digitalWrite(LED_PIN, 0); // turn off the led
#endif
setLed(false);
#ifdef T_BEAM_V10
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
// 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
// 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
// until then we need the following lines
// We want RTC peripherals to stay on
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
#ifdef BUTTON_PIN
@ -162,6 +173,41 @@ void doDeepSleep(uint64_t msecToWake)
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.
@ -426,6 +472,8 @@ void setup()
// enableModemSleep();
setCPUFast(false);
// doLightSleep();
}
uint32_t ledBlinker()
@ -433,18 +481,8 @@ uint32_t ledBlinker()
static bool ledOn;
ledOn ^= 1;
#ifdef LED_PIN
// toggle the led so we can get some rough sense of how often loop is pausing
digitalWrite(LED_PIN, ledOn);
#endif
setLed(ledOn);
#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
return isCharging ? 1000 : (ledOn ? 2 : 1000);
@ -467,7 +505,7 @@ uint32_t axpReads()
}
Periodic axpDebugOutput(axpReads);
#endif
#endif
void loop()
{
@ -508,6 +546,8 @@ void loop()
if (!wasPressed)
{ // just started a new press
DEBUG_MSG("pressing\n");
//doLightSleep();
// esp_pm_dump_locks(stdout); // FIXME, do this someplace better
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
msecstosleep = 10;
delay(msecstosleep);
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);
}
}

Wyświetl plik

@ -51,6 +51,8 @@ OLEDDisplayUi ui(&dispdev);
// A text message frame + debug frame + all the node infos
FrameCallback nonBootFrames[MAX_NUM_NODES + NUM_EXTRA_FRAMES];
bool is_screen_on() { return screenOn; }
void msOverlay(OLEDDisplay *display, OLEDDisplayUiState *state)
{
display->setTextAlignment(TEXT_ALIGN_RIGHT);

Wyświetl plik

@ -11,4 +11,6 @@ void screen_setup(), screen_on(), screen_off(), screen_press();
void screen_start_bluetooth(uint32_t pin);
// restore our regular frame list
void screen_set_frames();
void screen_set_frames();
bool is_screen_on();