From f75cdd4f5ccc322235d3ce9a4e9142e3a954f56d Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Wed, 16 Oct 2019 21:14:34 +0200 Subject: [PATCH] deep sleep (experimental) --- include/display.h | 3 +- include/globals.h | 5 ++ include/{i2cscan.h => i2c.h} | 6 +- include/lorawan.h | 3 +- include/main.h | 3 +- include/power.h | 9 ++- platformio.ini | 8 +-- src/configmanager.cpp | 13 ----- src/cyclic.cpp | 2 +- src/display.cpp | 16 ++++- src/{i2cscan.cpp => i2c.cpp} | 22 ++++++- src/irqhandler.cpp | 2 +- src/lorawan.cpp | 36 ++++++++---- src/main.cpp | 109 ++++++++++++++++++----------------- src/power.cpp | 97 +++++++++++++++++++++++++++++-- src/rcommand.cpp | 2 +- 16 files changed, 238 insertions(+), 98 deletions(-) rename include/{i2cscan.h => i2c.h} (80%) rename src/{i2cscan.cpp => i2c.cpp} (78%) diff --git a/include/display.h b/include/display.h index 0e94b806..8e503ce5 100644 --- a/include/display.h +++ b/include/display.h @@ -7,7 +7,8 @@ extern uint8_t DisplayIsOn; void refreshTheDisplay(bool nextPage = false); -void init_display(uint8_t verbose = 0); +void init_display(bool verbose = false); +void shutdown_display(void); void draw_page(time_t t, uint8_t page); void dp_printf(uint16_t x, uint16_t y, uint8_t font, uint8_t inv, const char *format, ...); diff --git a/include/globals.h b/include/globals.h index 76b733d4..9e41d441 100644 --- a/include/globals.h +++ b/include/globals.h @@ -51,6 +51,11 @@ enum sendprio_t { prio_low, prio_normal, prio_high }; enum timesource_t { _gps, _rtc, _lora, _unsynced }; +enum runmode_t { + RUNMODE_NORMAL, + RUNMODE_UPDATE, + RUNMODE_WAKEUP +}; // Struct holding devices's runtime configuration typedef struct { diff --git a/include/i2cscan.h b/include/i2c.h similarity index 80% rename from include/i2cscan.h rename to include/i2c.h index 38487e76..ed042b31 100644 --- a/include/i2cscan.h +++ b/include/i2c.h @@ -1,5 +1,5 @@ -#ifndef _I2CSCAN_H -#define _I2CSCAN_H +#ifndef _I2C_H +#define _I2C_H #include @@ -11,6 +11,8 @@ #define MCP_24AA02E64_PRIMARY_ADDRESS (0x50) #define QUECTEL_GPS_PRIMARY_ADDRESS (0x10) +void i2c_init(void); +void i2c_deinit(void); int i2c_scan(void); #endif \ No newline at end of file diff --git a/include/lorawan.h b/include/lorawan.h index 4341b397..ead91d5c 100644 --- a/include/lorawan.h +++ b/include/lorawan.h @@ -21,6 +21,7 @@ #endif extern TaskHandle_t lmicTask, lorasendTask; +extern RTC_DATA_ATTR int RTCseqnoUp, RTCseqnoDn; // table of LORAWAN MAC commands typedef struct { @@ -29,7 +30,7 @@ typedef struct { const uint8_t params; } mac_t; -esp_err_t lora_stack_init(); +esp_err_t lora_stack_init(bool joined = false); void lora_setupForNetwork(bool preJoin); void lmictask(void *pvParameters); void gen_lora_deveui(uint8_t *pdeveui); diff --git a/include/main.h b/include/main.h index 4b5617cb..f57ce3f9 100644 --- a/include/main.h +++ b/include/main.h @@ -8,7 +8,7 @@ #include "globals.h" #include "power.h" -#include "i2cscan.h" +#include "i2c.h" #include "blescan.h" #include "wifiscan.h" #include "configmanager.h" @@ -18,6 +18,7 @@ #include "irqhandler.h" #include "led.h" #include "spislave.h" + #if (HAS_LORA) #include "lorawan.h" #endif diff --git a/include/power.h b/include/power.h index 1af87f09..8737e963 100644 --- a/include/power.h +++ b/include/power.h @@ -3,19 +3,24 @@ #include #include +#include #include -#include "i2cscan.h" +#include "i2c.h" #define DEFAULT_VREF 1100 // tbd: use adc2_vref_to_gpio() for better estimate #define NO_OF_SAMPLES 64 // we do some multisampling to get better values +extern RTC_DATA_ATTR runmode_t RTC_runmode; + uint16_t read_voltage(void); void calibrate_voltage(void); bool batt_sufficient(void); +void enter_deepsleep(const int wakeup_sec, const gpio_num_t wakeup_gpio); +int exit_deepsleep(void); #ifdef HAS_PMU #include -void power_event_IRQ(void); +void AXP192_powerevent_IRQ(void); void AXP192_power(bool on); void AXP192_init(void); void AXP192_showstatus(void); diff --git a/platformio.ini b/platformio.ini index 1975fe69..80148ece 100644 --- a/platformio.ini +++ b/platformio.ini @@ -7,7 +7,7 @@ ; ---> SELECT THE TARGET PLATFORM HERE! <--- [board] -halfile = generic.h +;halfile = generic.h ;halfile = ebox.h ;halfile = eboxtube.h ;halfile = ecopower.h @@ -19,7 +19,7 @@ halfile = generic.h ;halfile = ttgov21new.h ;halfile = ttgofox.h ;halfile = ttgobeam.h -;halfile = ttgobeam10.h +halfile = ttgobeam10.h ;halfile = fipy.h ;halfile = lopy.h ;halfile = lopy4.h @@ -43,10 +43,10 @@ description = Paxcounter is a device for metering passenger flows in realtime. I [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.9.6 +release_version = 1.9.63 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose -debug_level = 3 +debug_level = 4 extra_scripts = pre:build.py otakeyfile = ota.conf lorakeyfile = loraconf.h diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 0fce294f..0fd6ca39 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -33,7 +33,6 @@ void defaultConfig() { cfg.vendorfilter = VENDORFILTER; // 0=disabled, 1=enabled cfg.rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) cfg.monitormode = 0; // 0=disabled, 1=enabled - cfg.runmode = 0; // 0=normal, 1=update cfg.payloadmask = PAYLOADMASK; // all payload switched on cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = { 0}; // init BSEC state for BME680 sensor @@ -157,10 +156,6 @@ void saveConfig() { flash8 != cfg.monitormode) nvs_set_i8(my_handle, "monitormode", cfg.monitormode); - if (nvs_get_i8(my_handle, "runmode", &flash8) != ESP_OK || - flash8 != cfg.runmode) - nvs_set_i8(my_handle, "runmode", cfg.runmode); - if (nvs_get_i16(my_handle, "rssilimit", &flash16) != ESP_OK || flash16 != cfg.rssilimit) nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit); @@ -350,14 +345,6 @@ void loadConfig() { saveConfig(); } - if (nvs_get_i8(my_handle, "runmode", &flash8) == ESP_OK) { - cfg.runmode = flash8; - ESP_LOGI(TAG, "Run mode = %d", flash8); - } else { - ESP_LOGI(TAG, "Run mode set to default %d", cfg.runmode); - saveConfig(); - } - nvs_close(my_handle); ESP_LOGI(TAG, "Done"); } diff --git a/src/cyclic.cpp b/src/cyclic.cpp index 9b75ecef..86eae864 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -20,7 +20,7 @@ void doHousekeeping() { uptime(); // check if update mode trigger switch was set - if (cfg.runmode == 1) + if (RTC_runmode == RUNMODE_UPDATE) do_reset(); // task storage debugging // diff --git a/src/display.cpp b/src/display.cpp index 1e888f21..7f4da8f5 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -60,7 +60,7 @@ uint8_t displaybuf[DISPLAY_WIDTH * DISPLAY_HEIGHT / 8] = {0}; QRCode qrcode; -void init_display(uint8_t verbose) { +void init_display(bool verbose) { // block i2c bus access if (!I2C_MUTEX_LOCK()) @@ -70,7 +70,7 @@ void init_display(uint8_t verbose) { // is we have display RST line we toggle it to re-initialize display #ifdef MY_OLED_RST pinMode(MY_OLED_RST, OUTPUT); - digitalWrite(MY_OLED_RST, 0); // iniialization of SSD1306 chip is executed + digitalWrite(MY_OLED_RST, 0); // initialization of SSD1306 chip is executed delay(1); // keep RES low for at least 3us according to SSD1306 datasheet digitalWrite(MY_OLED_RST, 1); // normal operation #endif @@ -182,6 +182,18 @@ void refreshTheDisplay(bool nextPage) { } // mutex } // refreshDisplay() +void shutdown_display(void) { + // block i2c bus access + if (!I2C_MUTEX_LOCK()) + ESP_LOGV(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0); + else { + cfg.screenon = 0; + oledShutdown(); + delay(DISPLAYREFRESH_MS / 1000 * 1.1); + I2C_MUTEX_UNLOCK(); // release i2c bus access + } +} + void draw_page(time_t t, uint8_t page) { char timeState; diff --git a/src/i2cscan.cpp b/src/i2c.cpp similarity index 78% rename from src/i2cscan.cpp rename to src/i2c.cpp index d6e7ff64..4fe58adc 100644 --- a/src/i2cscan.cpp +++ b/src/i2c.cpp @@ -1,10 +1,30 @@ // Basic config #include "globals.h" -#include "i2cscan.h" +#include "i2c.h" // Local logging tag static const char TAG[] = __FILE__; +void i2c_init(void) { +#ifdef HAS_DISPLAY + Wire.begin(MY_OLED_SDA, MY_OLED_SCL, 400000); +#else + Wire.begin(SDA, SCL, 400000); +#endif +} + +void i2c_deinit(void) { + Wire.~TwoWire(); // shutdown/power off I2C hardware +#ifdef HAS_DISPLAY + // to save power, because Wire.end() enables pullups + pinMode(MY_OLED_SDA, INPUT); + pinMode(MY_OLED_SCL, INPUT); +#else + pinMode(SDA, INPUT); + pinMode(SCL, INPUT); +#endif +} + int i2c_scan(void) { int i2c_ret, addr; diff --git a/src/irqhandler.cpp b/src/irqhandler.cpp index 8d1be880..63b85821 100644 --- a/src/irqhandler.cpp +++ b/src/irqhandler.cpp @@ -66,7 +66,7 @@ void irqHandler(void *pvParameters) { // do we have a power event? #if (HAS_PMU) if (InterruptStatus & PMU_IRQ) - power_event_IRQ(); + AXP192_powerevent_IRQ(); #endif // is time to send the payload? diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 398e86f4..7e47ab0e 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -73,6 +73,10 @@ static const lmic_pinmap myPinmap = { .spi_freq = 8000000, // 8MHz .pConfig = &myHalConfig}; +RTC_DATA_ATTR u4_t RTCnetid, RTCdevaddr; +RTC_DATA_ATTR u1_t RTCnwkKey[16], RTCartKey[16]; +RTC_DATA_ATTR int RTCseqnoUp, RTCseqnoDn; + void lora_setupForNetwork(bool preJoin) { if (preJoin) { @@ -86,9 +90,9 @@ void lora_setupForNetwork(bool preJoin) { #elif CFG_LMIC_EU_like // setting for TheThingsNetwork // TTN uses SF9, not SF12, for RX2 window - LMIC.dn2Dr = EU868_DR_SF9; - // Disable link check validation - LMIC_setLinkCheckMode(0); + // LMIC.dn2Dr = EU868_DR_SF9; + // Enable link check validation + LMIC_setLinkCheckMode(true); #endif } else { @@ -103,6 +107,10 @@ void lora_setupForNetwork(bool preJoin) { getSfName(updr2rps(LMIC.datarate)), getBwName(updr2rps(LMIC.datarate)), getCrName(updr2rps(LMIC.datarate))); + // store keys and counters in RTC memory + LMIC_getSessionKeys(&RTCnetid, &RTCdevaddr, RTCnwkKey, RTCartKey); + RTCseqnoUp = LMIC.seqnoUp; + RTCseqnoDn = LMIC.seqnoDn; } } @@ -244,9 +252,9 @@ void lora_send(void *pvParameters) { while (1) { // postpone until we are joined if we are not - // while (!LMIC.devaddr) { - // vTaskDelay(pdMS_TO_TICKS(500)); - //} + while (!LMIC.devaddr) { + vTaskDelay(pdMS_TO_TICKS(500)); + } // fetch next or wait for payload to send from queue if (xQueueReceive(LoraSendQueue, &SendBuffer, portMAX_DELAY) != pdTRUE) { @@ -287,7 +295,7 @@ void lora_send(void *pvParameters) { } } -esp_err_t lora_stack_init() { +esp_err_t lora_stack_init(bool joined) { assert(SEND_QUEUE_SIZE); LoraSendQueue = xQueueCreate(SEND_QUEUE_SIZE, sizeof(MessageBuffer_t)); if (LoraSendQueue == 0) { @@ -307,9 +315,17 @@ esp_err_t lora_stack_init() { &lmicTask, // task handle 1); // CPU core - // start join - if (!LMIC_startJoining()) - ESP_LOGI(TAG, "Already joined"); + // start join if we did not wakeup from sleep, else continue session + if (!joined) { + if (!LMIC_startJoining()) + ESP_LOGI(TAG, "Already joined"); + } else { + LMIC_reset(); + LMIC_setSession(RTCnetid, RTCdevaddr, RTCnwkKey, RTCartKey); + LMIC.seqnoUp = RTCseqnoUp; + LMIC.seqnoDn = RTCseqnoDn; + lora_setupForNetwork(true); + } // start lmic send task xTaskCreatePinnedToCore(lora_send, // task function diff --git a/src/main.cpp b/src/main.cpp index f9bdce47..d366a762 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -131,51 +131,54 @@ void setup() { ESP_LOGI(TAG, "Starting Software v%s", PROGVERSION); - // print chip information on startup if in verbose mode + if (RTC_runmode == RUNMODE_WAKEUP) + exit_deepsleep(); + else { + + // print chip information on startup if in verbose mode #if (VERBOSE) - esp_chip_info_t chip_info; - esp_chip_info(&chip_info); - ESP_LOGI(TAG, - "This is ESP32 chip with %d CPU cores, WiFi%s%s, silicon revision " - "%d, %dMB %s Flash", - chip_info.cores, (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", - (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "", - chip_info.revision, spi_flash_get_chip_size() / (1024 * 1024), - (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" - : "external"); - ESP_LOGI(TAG, "Internal Total heap %d, internal Free Heap %d", - ESP.getHeapSize(), ESP.getFreeHeap()); + esp_chip_info_t chip_info; + esp_chip_info(&chip_info); + ESP_LOGI(TAG, + "This is ESP32 chip with %d CPU cores, WiFi%s%s, silicon revision " + "%d, %dMB %s Flash", + chip_info.cores, + (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", + (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "", + chip_info.revision, spi_flash_get_chip_size() / (1024 * 1024), + (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" + : "external"); + ESP_LOGI(TAG, "Internal Total heap %d, internal Free Heap %d", + ESP.getHeapSize(), ESP.getFreeHeap()); #ifdef BOARD_HAS_PSRAM - ESP_LOGI(TAG, "SPIRam Total heap %d, SPIRam Free Heap %d", ESP.getPsramSize(), - ESP.getFreePsram()); + ESP_LOGI(TAG, "SPIRam Total heap %d, SPIRam Free Heap %d", + ESP.getPsramSize(), ESP.getFreePsram()); #endif - ESP_LOGI(TAG, "ChipRevision %d, Cpu Freq %d, SDK Version %s", - ESP.getChipRevision(), ESP.getCpuFreqMHz(), ESP.getSdkVersion()); - ESP_LOGI(TAG, "Flash Size %d, Flash Speed %d", ESP.getFlashChipSize(), - ESP.getFlashChipSpeed()); - ESP_LOGI(TAG, "Wifi/BT software coexist version %s", esp_coex_version_get()); + ESP_LOGI(TAG, "ChipRevision %d, Cpu Freq %d, SDK Version %s", + ESP.getChipRevision(), ESP.getCpuFreqMHz(), ESP.getSdkVersion()); + ESP_LOGI(TAG, "Flash Size %d, Flash Speed %d", ESP.getFlashChipSize(), + ESP.getFlashChipSpeed()); + ESP_LOGI(TAG, "Wifi/BT software coexist version %s", + esp_coex_version_get()); #if (HAS_LORA) - ESP_LOGI(TAG, "IBM LMIC version %d.%d.%d", LMIC_VERSION_MAJOR, - LMIC_VERSION_MINOR, LMIC_VERSION_BUILD); - ESP_LOGI(TAG, "Arduino LMIC version %d.%d.%d.%d", - ARDUINO_LMIC_VERSION_GET_MAJOR(ARDUINO_LMIC_VERSION), - ARDUINO_LMIC_VERSION_GET_MINOR(ARDUINO_LMIC_VERSION), - ARDUINO_LMIC_VERSION_GET_PATCH(ARDUINO_LMIC_VERSION), - ARDUINO_LMIC_VERSION_GET_LOCAL(ARDUINO_LMIC_VERSION)); - showLoraKeys(); + ESP_LOGI(TAG, "IBM LMIC version %d.%d.%d", LMIC_VERSION_MAJOR, + LMIC_VERSION_MINOR, LMIC_VERSION_BUILD); + ESP_LOGI(TAG, "Arduino LMIC version %d.%d.%d.%d", + ARDUINO_LMIC_VERSION_GET_MAJOR(ARDUINO_LMIC_VERSION), + ARDUINO_LMIC_VERSION_GET_MINOR(ARDUINO_LMIC_VERSION), + ARDUINO_LMIC_VERSION_GET_PATCH(ARDUINO_LMIC_VERSION), + ARDUINO_LMIC_VERSION_GET_LOCAL(ARDUINO_LMIC_VERSION)); + showLoraKeys(); #endif // HAS_LORA #if (HAS_GPS) - ESP_LOGI(TAG, "TinyGPS+ version %s", TinyGPSPlus::libraryVersion()); + ESP_LOGI(TAG, "TinyGPS+ version %s", TinyGPSPlus::libraryVersion()); #endif + } -// open i2c bus -#ifdef HAS_DISPLAY - Wire.begin(MY_OLED_SDA, MY_OLED_SCL, 400000); -#else - Wire.begin(SDA, SCL, 400000); -#endif + // open i2c bus + i2c_init(); // setup power on boards with power management logic #ifdef EXT_POWER_SW @@ -197,7 +200,7 @@ void setup() { #ifdef HAS_DISPLAY strcat_P(features, " OLED"); DisplayIsOn = cfg.screenon; - init_display(!cfg.runmode); // note: blocking call + init_display(RTC_runmode == RUNMODE_NORMAL); // note: blocking call #endif // scan i2c bus for devices @@ -266,9 +269,8 @@ void setup() { #if (USE_OTA) strcat_P(features, " OTA"); // reboot to firmware update mode if ota trigger switch is set - if (cfg.runmode == 1) { - cfg.runmode = 0; - saveConfig(); + if (RTC_runmode == RUNMODE_UPDATE) { + RTC_runmode = RUNMODE_NORMAL; start_ota_update(); } #endif @@ -283,11 +285,11 @@ void setup() { } else btStop(); #else - // remove bluetooth stack to gain more free memory - btStop(); - ESP_ERROR_CHECK(esp_bt_mem_release(ESP_BT_MODE_BTDM)); - ESP_ERROR_CHECK(esp_coex_preference_set( - ESP_COEX_PREFER_WIFI)); // configure Wifi/BT coexist lib + // remove bluetooth stack to gain more free memory + btStop(); + ESP_ERROR_CHECK(esp_bt_mem_release(ESP_BT_MODE_BTDM)); + ESP_ERROR_CHECK(esp_coex_preference_set( + ESP_COEX_PREFER_WIFI)); // configure Wifi/BT coexist lib #endif // initialize gps @@ -314,7 +316,7 @@ void setup() { // initialize LoRa #if (HAS_LORA) strcat_P(features, " LORA"); - assert(lora_stack_init() == ESP_OK); + assert(lora_stack_init(RTC_runmode == RUNMODE_WAKEUP) == ESP_OK); #endif // initialize SPI @@ -338,11 +340,11 @@ void setup() { #if PAYLOAD_ENCODER == 1 strcat_P(features, " PLAIN"); #elif PAYLOAD_ENCODER == 2 - strcat_P(features, " PACKED"); + strcat_P(features, " PACKED"); #elif PAYLOAD_ENCODER == 3 - strcat_P(features, " LPPDYN"); + strcat_P(features, " LPPDYN"); #elif PAYLOAD_ENCODER == 4 - strcat_P(features, " LPPPKD"); + strcat_P(features, " LPPPKD"); #endif // initialize RTC @@ -369,10 +371,10 @@ void setup() { // function gets it's seed from RF noise get_salt(); // get new 16bit for salting hashes #else - // switch off wifi - WiFi.mode(WIFI_OFF); - esp_wifi_stop(); - esp_wifi_deinit(); + // switch off wifi + WiFi.mode(WIFI_OFF); + esp_wifi_stop(); + esp_wifi_deinit(); #endif // start state machine @@ -465,6 +467,9 @@ void setup() { // show compiled features ESP_LOGI(TAG, "Features:%s", features); + // set runmode to normal + RTC_runmode = RUNMODE_NORMAL; + vTaskDelete(NULL); } // setup() diff --git a/src/power.cpp b/src/power.cpp index 597f68e8..73b3991f 100644 --- a/src/power.cpp +++ b/src/power.cpp @@ -5,11 +5,14 @@ // Local logging tag static const char TAG[] = __FILE__; +RTC_DATA_ATTR struct timeval sleep_enter_time; +RTC_DATA_ATTR runmode_t RTC_runmode = RUNMODE_NORMAL; + #ifdef HAS_PMU AXP20X_Class pmu; -void power_event_IRQ(void) { +void AXP192_powerevent_IRQ(void) { pmu.readIRQ(); @@ -34,10 +37,12 @@ void power_event_IRQ(void) { if (pmu.isBattTempHighIRQ()) ESP_LOGI(TAG, "Battery low temperature."); - // display on/off - // if (pmu.isPEKShortPressIRQ()) { - // cfg.screenon = !cfg.screenon; - //} +// esp32 sleep mode, can be exited by pressing user button +#ifdef HAS_BUTTON + if (pmu.isPEKShortPressIRQ() && (RTC_runmode == RUNMODE_NORMAL)) { + enter_deepsleep(0, HAS_BUTTON); + } +#endif // shutdown power if (pmu.isPEKLongtPressIRQ()) { @@ -60,7 +65,8 @@ void AXP192_power(bool on) { pmu.setChgLEDMode(AXP20X_LED_BLINK_1HZ); } else { pmu.setChgLEDMode(AXP20X_LED_OFF); - pmu.setPowerOutPut(AXP192_DCDC1, AXP202_OFF); + // we don't cut off power of display, because then display blocks i2c bus + // pmu.setPowerOutPut(AXP192_DCDC1, AXP202_OFF); pmu.setPowerOutPut(AXP192_LDO3, AXP202_OFF); pmu.setPowerOutPut(AXP192_LDO2, AXP202_OFF); } @@ -185,6 +191,85 @@ static const adc_unit_t unit = ADC_UNIT_1; #endif // BAT_MEASURE_ADC +void enter_deepsleep(const int wakeup_sec, const gpio_num_t wakeup_gpio) { + + if ((!wakeup_sec) && (!wakeup_gpio) && (RTC_runmode == RUNMODE_NORMAL)) + return; + + // set wakeup timer + if (wakeup_sec) + esp_sleep_enable_timer_wakeup(wakeup_sec * 1000000); + + // set wakeup gpio + if (wakeup_gpio != NOT_A_PIN) { + rtc_gpio_isolate(wakeup_gpio); + esp_sleep_enable_ext1_wakeup(1ULL << wakeup_gpio, ESP_EXT1_WAKEUP_ALL_LOW); + } + + // store LMIC counters and time + RTCseqnoUp = LMIC.seqnoUp; + RTCseqnoDn = LMIC.seqnoDn; + + // store sleep enter time + gettimeofday(&sleep_enter_time, NULL); + + // halt interrupts accessing i2c bus + mask_user_IRQ(); + +// switch off display +#ifdef HAS_DISPLAY + shutdown_display(); +#endif + +// switch off wifi & ble +#if (BLECOUNTER) + stop_BLEscan(); +#endif + +// switch off power if has PMU +#ifdef HAS_PMU + AXP192_power(false); // switch off Lora, GPS, display +#endif + + // shutdown i2c bus + i2c_deinit(); + + // enter sleep mode + esp_deep_sleep_start(); +} + +int exit_deepsleep(void) { + + struct timeval now; + gettimeofday(&now, NULL); + int sleep_time_ms = (now.tv_sec - sleep_enter_time.tv_sec) * 1000 + + (now.tv_usec - sleep_enter_time.tv_usec) / 1000; + + // switch on power if has PMU +#ifdef HAS_PMU + AXP192_power(true); // power on Lora, GPS, display +#endif + + // re-init i2c bus + void i2c_init(); + + switch (esp_sleep_get_wakeup_cause()) { + case ESP_SLEEP_WAKEUP_EXT1: + case ESP_SLEEP_WAKEUP_TIMER: + RTC_runmode = RUNMODE_WAKEUP; + ESP_LOGI(TAG, "[%0.3f] wake up from deep sleep after %dms", sleep_time_ms); + break; + case ESP_SLEEP_WAKEUP_UNDEFINED: + default: + RTC_runmode = RUNMODE_NORMAL; + } + + if (RTC_runmode == RUNMODE_WAKEUP) + return sleep_time_ms; + else + return -1; +} + void calibrate_voltage(void) { #ifdef BAT_MEASURE_ADC // configure ADC diff --git a/src/rcommand.cpp b/src/rcommand.cpp index 4290555c..24972c73 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -37,7 +37,7 @@ void set_reset(uint8_t val[]) { case 9: // reset and ask for software update via Wifi OTA ESP_LOGI(TAG, "Remote command: software update via Wifi"); #if (USE_OTA) - cfg.runmode = 1; + RTC_runmode = RUNMODE_UPDATE; #endif // USE_OTA break;