From e890e7a80acf01a4cb9bede36a86ed8f86518c9c Mon Sep 17 00:00:00 2001 From: geeksville Date: Sat, 1 Feb 2020 05:30:08 -0800 Subject: [PATCH] deep sleep now powers down GPS and lora radio --- main/configuration.h | 9 +-- main/main.ino | 129 +++++++++++++------------------------------ 2 files changed, 42 insertions(+), 96 deletions(-) diff --git a/main/configuration.h b/main/configuration.h index a596bce..4aee938 100644 --- a/main/configuration.h +++ b/main/configuration.h @@ -56,8 +56,8 @@ void ttn_register(void (*callback)(uint8_t message)); #define DEBUG_PORT Serial // Serial debug port #define SERIAL_BAUD 115200 // Serial debug baud rate -#define SLEEP_BETWEEN_MESSAGES 0 // Do sleep between messages -#define SEND_INTERVAL 60000 // Sleep for these many millis +#define SLEEP_BETWEEN_MESSAGES true // Do sleep between messages +#define SEND_INTERVAL (5 * 60 * 1000) // Sleep for these many millis #define MESSAGE_TO_SLEEP_DELAY 5000 // Time after message before going to sleep #define LOGO_DELAY 5000 // Time to show logo on first boot #define LORAWAN_PORT 10 // Port the messages will be sent to @@ -67,10 +67,7 @@ void ttn_register(void (*callback)(uint8_t message)); #define REQUIRE_RADIO true // If true, we will fail to start if the radio is not found // If not defined, we will wait for lock forever -// #define GPS_WAIT_FOR_LOCK 5000 // Wait 5s after every boot for GPS lock - -// If defined, we will enter deep sleep after sending our packet. We will sleep until this interval expires or the user presses the button -// #define DEEPSLEEP_INTERVAL (60 * 60 * 1000ULL) // sleep after we've received one message from the server (or we ran out of time), sleep for this many msecs +#define GPS_WAIT_FOR_LOCK (30 * 1000) // Wait 30s after every boot for GPS lock (may need longer than 5s because we turned the gps off during deep sleep) // ----------------------------------------------------------------------------- // DEBUG diff --git a/main/main.ino b/main/main.ino index 6ed1511..d9b6dd4 100644 --- a/main/main.ino +++ b/main/main.ino @@ -90,6 +90,40 @@ bool trySend() { } } + +void doDeepSleep(uint64_t msecToWake) +{ + Serial.printf("Entering deep sleep for %llu seconds\n", msecToWake / 1000); + + // not using wifi yet, but once we are this is needed to shutoff the radio hw + // esp_wifi_stop(); + + screen_off(); // datasheet says this will draw only 10ua + LMIC_shutdown(); // cleanly shutdown the radio + + if(axp192_found) { + // turn on after initial testing with real hardware + axp.setPowerOutPut(AXP192_LDO2, AXP202_OFF); // LORA radio + axp.setPowerOutPut(AXP192_LDO3, AXP202_OFF); // GPS main power + } + + // FIXME - use an external 10k pulldown so we can leave the RTC peripherals powered off + // until then we need the following lines + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); + + // Only GPIOs which are have RTC functionality can be used in this bit map: 0,2,4,12-15,25-27,32-39. + uint64_t gpioMask = (1ULL << BUTTON_PIN); + + // FIXME change polarity so we can wake on ANY_HIGH instead - that would allow us to use all three buttons (instead of just the first) + gpio_pullup_en((gpio_num_t) BUTTON_PIN); + + esp_sleep_enable_ext1_wakeup(gpioMask, ESP_EXT1_WAKEUP_ALL_LOW); + + esp_sleep_enable_timer_wakeup(msecToWake * 1000ULL); // call expects usecs + esp_deep_sleep_start(); // TBD mA sleep current (battery) +} + + void sleep() { #if SLEEP_BETWEEN_MESSAGES @@ -110,7 +144,7 @@ void sleep() { // We sleep for the interval between messages minus the current millis // this way we distribute the messages evenly every SEND_INTERVAL millis uint32_t sleep_for = (millis() < SEND_INTERVAL) ? SEND_INTERVAL - millis() : SEND_INTERVAL; - sleep_millis(sleep_for); + doDeepSleep(sleep_for); #endif } @@ -330,81 +364,11 @@ void setup() { } } -#ifdef DEEPSLEEP_INTERVAL +void loop() { + gps_loop(); + ttn_loop(); + screen_loop(); -void doDeepSleep() -{ - uint64_t msecToWake = DEEPSLEEP_INTERVAL; - Serial.printf("Entering deep sleep %llu\n", msecToWake); - - // not using wifi yet, but once we are this is needed to shutoff the radio hw - // esp_wifi_stop(); - - screen_off(); // datasheet says this will draw only 10ua - LMIC_shutdown(); // cleanly shutdown the radio - - if(axp192_found) { - // turn on after initial testing with real hardware - // axp.setPowerOutPut(AXP192_LDO2, AXP202_OFF); // LORA radio - // axp.setPowerOutPut(AXP192_LDO3, AXP202_OFF); // GPS main power - } - - // FIXME - use an external 10k pulldown so we can leave the RTC peripherals powered off - // until then we need the following lines - esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); - - // Only GPIOs which are have RTC functionality can be used in this bit map: 0,2,4,12-15,25-27,32-39. - uint64_t gpioMask = (1ULL << BUTTON_PIN); - - // FIXME change polarity so we can wake on ANY_HIGH instead - that would allow us to use all three buttons (instead of just the first) - gpio_pullup_en((gpio_num_t) BUTTON_PIN); - - esp_sleep_enable_ext1_wakeup(gpioMask, ESP_EXT1_WAKEUP_ALL_LOW); - - esp_sleep_enable_timer_wakeup(msecToWake * 1000ULL); // call expects usecs - esp_deep_sleep_start(); // TBD mA sleep current (battery) -} - - -/// send ONE packet (or timeout waiting for GPS/LORA) and then enter deep sleep. If screen is on let the user have a few seconds to -/// see the results -void deepSleepLoop() { - // Send every SEND_INTERVAL millis - static uint32_t last = 0, timeToSleep = 0; - static bool first = true; - - uint32_t now = millis(); - - if(packetSent) { // we've sent at least one packet to the server - timeToSleep = ssd1306_found ? now + 5000 : now; // If the display is on allow the user a few seconds to see it, otherwise go to sleep ASAP - } - - if(timeToSleep && now >= timeToSleep) // if a sleep was queued, possibly do it - doDeepSleep(); - - if (0 == last || now - last > SEND_INTERVAL) { - if (trySend()) { - last = millis(); - first = false; - Serial.println("TRANSMITTED"); - } else { - if (first) { - screen_print("Waiting GPS lock\n"); - first = false; - } -#ifdef GPS_WAIT_FOR_LOCK - if (millis() > GPS_WAIT_FOR_LOCK) { // we never found a GPS lock, just go back to sleep - doDeepSleep(); - } -#endif - } - } -} - -#else - -/// loop endlessly, sending a packet every SEND_INTERVAL -void nonDeepSleepLoop() { if(packetSent) { packetSent = false; sleep(); @@ -431,18 +395,3 @@ void nonDeepSleepLoop() { } } } - -#endif - - -void loop() { - gps_loop(); - ttn_loop(); - screen_loop(); - -#ifdef DEEPSLEEP_INTERVAL - deepSleepLoop(); -#else - nonDeepSleepLoop(); -#endif -}