deep sleep (experimental)

This commit is contained in:
Verkehrsrot 2019-10-16 21:14:34 +02:00
parent 0bc368c228
commit f75cdd4f5c
16 changed files with 238 additions and 98 deletions

View File

@ -7,7 +7,8 @@
extern uint8_t DisplayIsOn; extern uint8_t DisplayIsOn;
void refreshTheDisplay(bool nextPage = false); 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 draw_page(time_t t, uint8_t page);
void dp_printf(uint16_t x, uint16_t y, uint8_t font, uint8_t inv, void dp_printf(uint16_t x, uint16_t y, uint8_t font, uint8_t inv,
const char *format, ...); const char *format, ...);

View File

@ -51,6 +51,11 @@
enum sendprio_t { prio_low, prio_normal, prio_high }; enum sendprio_t { prio_low, prio_normal, prio_high };
enum timesource_t { _gps, _rtc, _lora, _unsynced }; enum timesource_t { _gps, _rtc, _lora, _unsynced };
enum runmode_t {
RUNMODE_NORMAL,
RUNMODE_UPDATE,
RUNMODE_WAKEUP
};
// Struct holding devices's runtime configuration // Struct holding devices's runtime configuration
typedef struct { typedef struct {

View File

@ -1,5 +1,5 @@
#ifndef _I2CSCAN_H #ifndef _I2C_H
#define _I2CSCAN_H #define _I2C_H
#include <Arduino.h> #include <Arduino.h>
@ -11,6 +11,8 @@
#define MCP_24AA02E64_PRIMARY_ADDRESS (0x50) #define MCP_24AA02E64_PRIMARY_ADDRESS (0x50)
#define QUECTEL_GPS_PRIMARY_ADDRESS (0x10) #define QUECTEL_GPS_PRIMARY_ADDRESS (0x10)
void i2c_init(void);
void i2c_deinit(void);
int i2c_scan(void); int i2c_scan(void);
#endif #endif

View File

@ -21,6 +21,7 @@
#endif #endif
extern TaskHandle_t lmicTask, lorasendTask; extern TaskHandle_t lmicTask, lorasendTask;
extern RTC_DATA_ATTR int RTCseqnoUp, RTCseqnoDn;
// table of LORAWAN MAC commands // table of LORAWAN MAC commands
typedef struct { typedef struct {
@ -29,7 +30,7 @@ typedef struct {
const uint8_t params; const uint8_t params;
} mac_t; } mac_t;
esp_err_t lora_stack_init(); esp_err_t lora_stack_init(bool joined = false);
void lora_setupForNetwork(bool preJoin); void lora_setupForNetwork(bool preJoin);
void lmictask(void *pvParameters); void lmictask(void *pvParameters);
void gen_lora_deveui(uint8_t *pdeveui); void gen_lora_deveui(uint8_t *pdeveui);

View File

@ -8,7 +8,7 @@
#include "globals.h" #include "globals.h"
#include "power.h" #include "power.h"
#include "i2cscan.h" #include "i2c.h"
#include "blescan.h" #include "blescan.h"
#include "wifiscan.h" #include "wifiscan.h"
#include "configmanager.h" #include "configmanager.h"
@ -18,6 +18,7 @@
#include "irqhandler.h" #include "irqhandler.h"
#include "led.h" #include "led.h"
#include "spislave.h" #include "spislave.h"
#if (HAS_LORA) #if (HAS_LORA)
#include "lorawan.h" #include "lorawan.h"
#endif #endif

View File

@ -3,19 +3,24 @@
#include <Arduino.h> #include <Arduino.h>
#include <driver/adc.h> #include <driver/adc.h>
#include <driver/rtc_io.h>
#include <esp_adc_cal.h> #include <esp_adc_cal.h>
#include "i2cscan.h" #include "i2c.h"
#define DEFAULT_VREF 1100 // tbd: use adc2_vref_to_gpio() for better estimate #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 #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); uint16_t read_voltage(void);
void calibrate_voltage(void); void calibrate_voltage(void);
bool batt_sufficient(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 #ifdef HAS_PMU
#include <axp20x.h> #include <axp20x.h>
void power_event_IRQ(void); void AXP192_powerevent_IRQ(void);
void AXP192_power(bool on); void AXP192_power(bool on);
void AXP192_init(void); void AXP192_init(void);
void AXP192_showstatus(void); void AXP192_showstatus(void);

View File

@ -7,7 +7,7 @@
; ---> SELECT THE TARGET PLATFORM HERE! <--- ; ---> SELECT THE TARGET PLATFORM HERE! <---
[board] [board]
halfile = generic.h ;halfile = generic.h
;halfile = ebox.h ;halfile = ebox.h
;halfile = eboxtube.h ;halfile = eboxtube.h
;halfile = ecopower.h ;halfile = ecopower.h
@ -19,7 +19,7 @@ halfile = generic.h
;halfile = ttgov21new.h ;halfile = ttgov21new.h
;halfile = ttgofox.h ;halfile = ttgofox.h
;halfile = ttgobeam.h ;halfile = ttgobeam.h
;halfile = ttgobeam10.h halfile = ttgobeam10.h
;halfile = fipy.h ;halfile = fipy.h
;halfile = lopy.h ;halfile = lopy.h
;halfile = lopy4.h ;halfile = lopy4.h
@ -43,10 +43,10 @@ description = Paxcounter is a device for metering passenger flows in realtime. I
[common] [common]
; for release_version use max. 10 chars total, use any decimal format like "a.b.c" ; 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! ; 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 ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
debug_level = 3 debug_level = 4
extra_scripts = pre:build.py extra_scripts = pre:build.py
otakeyfile = ota.conf otakeyfile = ota.conf
lorakeyfile = loraconf.h lorakeyfile = loraconf.h

View File

@ -33,7 +33,6 @@ void defaultConfig() {
cfg.vendorfilter = VENDORFILTER; // 0=disabled, 1=enabled cfg.vendorfilter = VENDORFILTER; // 0=disabled, 1=enabled
cfg.rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) cfg.rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%)
cfg.monitormode = 0; // 0=disabled, 1=enabled cfg.monitormode = 0; // 0=disabled, 1=enabled
cfg.runmode = 0; // 0=normal, 1=update
cfg.payloadmask = PAYLOADMASK; // all payload switched on cfg.payloadmask = PAYLOADMASK; // all payload switched on
cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = { cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = {
0}; // init BSEC state for BME680 sensor 0}; // init BSEC state for BME680 sensor
@ -157,10 +156,6 @@ void saveConfig() {
flash8 != cfg.monitormode) flash8 != cfg.monitormode)
nvs_set_i8(my_handle, "monitormode", 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 || if (nvs_get_i16(my_handle, "rssilimit", &flash16) != ESP_OK ||
flash16 != cfg.rssilimit) flash16 != cfg.rssilimit)
nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit); nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit);
@ -350,14 +345,6 @@ void loadConfig() {
saveConfig(); 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); nvs_close(my_handle);
ESP_LOGI(TAG, "Done"); ESP_LOGI(TAG, "Done");
} }

View File

@ -20,7 +20,7 @@ void doHousekeeping() {
uptime(); uptime();
// check if update mode trigger switch was set // check if update mode trigger switch was set
if (cfg.runmode == 1) if (RTC_runmode == RUNMODE_UPDATE)
do_reset(); do_reset();
// task storage debugging // // task storage debugging //

View File

@ -60,7 +60,7 @@ uint8_t displaybuf[DISPLAY_WIDTH * DISPLAY_HEIGHT / 8] = {0};
QRCode qrcode; QRCode qrcode;
void init_display(uint8_t verbose) { void init_display(bool verbose) {
// block i2c bus access // block i2c bus access
if (!I2C_MUTEX_LOCK()) 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 // is we have display RST line we toggle it to re-initialize display
#ifdef MY_OLED_RST #ifdef MY_OLED_RST
pinMode(MY_OLED_RST, OUTPUT); 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 delay(1); // keep RES low for at least 3us according to SSD1306 datasheet
digitalWrite(MY_OLED_RST, 1); // normal operation digitalWrite(MY_OLED_RST, 1); // normal operation
#endif #endif
@ -182,6 +182,18 @@ void refreshTheDisplay(bool nextPage) {
} // mutex } // mutex
} // refreshDisplay() } // 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) { void draw_page(time_t t, uint8_t page) {
char timeState; char timeState;

View File

@ -1,10 +1,30 @@
// Basic config // Basic config
#include "globals.h" #include "globals.h"
#include "i2cscan.h" #include "i2c.h"
// Local logging tag // Local logging tag
static const char TAG[] = __FILE__; 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_scan(void) {
int i2c_ret, addr; int i2c_ret, addr;

View File

@ -66,7 +66,7 @@ void irqHandler(void *pvParameters) {
// do we have a power event? // do we have a power event?
#if (HAS_PMU) #if (HAS_PMU)
if (InterruptStatus & PMU_IRQ) if (InterruptStatus & PMU_IRQ)
power_event_IRQ(); AXP192_powerevent_IRQ();
#endif #endif
// is time to send the payload? // is time to send the payload?

View File

@ -73,6 +73,10 @@ static const lmic_pinmap myPinmap = {
.spi_freq = 8000000, // 8MHz .spi_freq = 8000000, // 8MHz
.pConfig = &myHalConfig}; .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) { void lora_setupForNetwork(bool preJoin) {
if (preJoin) { if (preJoin) {
@ -86,9 +90,9 @@ void lora_setupForNetwork(bool preJoin) {
#elif CFG_LMIC_EU_like #elif CFG_LMIC_EU_like
// setting for TheThingsNetwork // setting for TheThingsNetwork
// TTN uses SF9, not SF12, for RX2 window // TTN uses SF9, not SF12, for RX2 window
LMIC.dn2Dr = EU868_DR_SF9; // LMIC.dn2Dr = EU868_DR_SF9;
// Disable link check validation // Enable link check validation
LMIC_setLinkCheckMode(0); LMIC_setLinkCheckMode(true);
#endif #endif
} else { } else {
@ -103,6 +107,10 @@ void lora_setupForNetwork(bool preJoin) {
getSfName(updr2rps(LMIC.datarate)), getSfName(updr2rps(LMIC.datarate)),
getBwName(updr2rps(LMIC.datarate)), getBwName(updr2rps(LMIC.datarate)),
getCrName(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) { while (1) {
// postpone until we are joined if we are not // postpone until we are joined if we are not
// while (!LMIC.devaddr) { while (!LMIC.devaddr) {
// vTaskDelay(pdMS_TO_TICKS(500)); vTaskDelay(pdMS_TO_TICKS(500));
//} }
// fetch next or wait for payload to send from queue // fetch next or wait for payload to send from queue
if (xQueueReceive(LoraSendQueue, &SendBuffer, portMAX_DELAY) != pdTRUE) { 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); assert(SEND_QUEUE_SIZE);
LoraSendQueue = xQueueCreate(SEND_QUEUE_SIZE, sizeof(MessageBuffer_t)); LoraSendQueue = xQueueCreate(SEND_QUEUE_SIZE, sizeof(MessageBuffer_t));
if (LoraSendQueue == 0) { if (LoraSendQueue == 0) {
@ -307,9 +315,17 @@ esp_err_t lora_stack_init() {
&lmicTask, // task handle &lmicTask, // task handle
1); // CPU core 1); // CPU core
// start join // start join if we did not wakeup from sleep, else continue session
if (!LMIC_startJoining()) if (!joined) {
ESP_LOGI(TAG, "Already 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 // start lmic send task
xTaskCreatePinnedToCore(lora_send, // task function xTaskCreatePinnedToCore(lora_send, // task function

View File

@ -131,51 +131,54 @@ void setup() {
ESP_LOGI(TAG, "Starting Software v%s", PROGVERSION); 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) #if (VERBOSE)
esp_chip_info_t chip_info; esp_chip_info_t chip_info;
esp_chip_info(&chip_info); esp_chip_info(&chip_info);
ESP_LOGI(TAG, ESP_LOGI(TAG,
"This is ESP32 chip with %d CPU cores, WiFi%s%s, silicon revision " "This is ESP32 chip with %d CPU cores, WiFi%s%s, silicon revision "
"%d, %dMB %s Flash", "%d, %dMB %s Flash",
chip_info.cores, (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", chip_info.cores,
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "", (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
chip_info.revision, spi_flash_get_chip_size() / (1024 * 1024), (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "",
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" chip_info.revision, spi_flash_get_chip_size() / (1024 * 1024),
: "external"); (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded"
ESP_LOGI(TAG, "Internal Total heap %d, internal Free Heap %d", : "external");
ESP.getHeapSize(), ESP.getFreeHeap()); ESP_LOGI(TAG, "Internal Total heap %d, internal Free Heap %d",
ESP.getHeapSize(), ESP.getFreeHeap());
#ifdef BOARD_HAS_PSRAM #ifdef BOARD_HAS_PSRAM
ESP_LOGI(TAG, "SPIRam Total heap %d, SPIRam Free Heap %d", ESP.getPsramSize(), ESP_LOGI(TAG, "SPIRam Total heap %d, SPIRam Free Heap %d",
ESP.getFreePsram()); ESP.getPsramSize(), ESP.getFreePsram());
#endif #endif
ESP_LOGI(TAG, "ChipRevision %d, Cpu Freq %d, SDK Version %s", ESP_LOGI(TAG, "ChipRevision %d, Cpu Freq %d, SDK Version %s",
ESP.getChipRevision(), ESP.getCpuFreqMHz(), ESP.getSdkVersion()); ESP.getChipRevision(), ESP.getCpuFreqMHz(), ESP.getSdkVersion());
ESP_LOGI(TAG, "Flash Size %d, Flash Speed %d", ESP.getFlashChipSize(), ESP_LOGI(TAG, "Flash Size %d, Flash Speed %d", ESP.getFlashChipSize(),
ESP.getFlashChipSpeed()); ESP.getFlashChipSpeed());
ESP_LOGI(TAG, "Wifi/BT software coexist version %s", esp_coex_version_get()); ESP_LOGI(TAG, "Wifi/BT software coexist version %s",
esp_coex_version_get());
#if (HAS_LORA) #if (HAS_LORA)
ESP_LOGI(TAG, "IBM LMIC version %d.%d.%d", LMIC_VERSION_MAJOR, ESP_LOGI(TAG, "IBM LMIC version %d.%d.%d", LMIC_VERSION_MAJOR,
LMIC_VERSION_MINOR, LMIC_VERSION_BUILD); LMIC_VERSION_MINOR, LMIC_VERSION_BUILD);
ESP_LOGI(TAG, "Arduino LMIC version %d.%d.%d.%d", ESP_LOGI(TAG, "Arduino LMIC version %d.%d.%d.%d",
ARDUINO_LMIC_VERSION_GET_MAJOR(ARDUINO_LMIC_VERSION), ARDUINO_LMIC_VERSION_GET_MAJOR(ARDUINO_LMIC_VERSION),
ARDUINO_LMIC_VERSION_GET_MINOR(ARDUINO_LMIC_VERSION), ARDUINO_LMIC_VERSION_GET_MINOR(ARDUINO_LMIC_VERSION),
ARDUINO_LMIC_VERSION_GET_PATCH(ARDUINO_LMIC_VERSION), ARDUINO_LMIC_VERSION_GET_PATCH(ARDUINO_LMIC_VERSION),
ARDUINO_LMIC_VERSION_GET_LOCAL(ARDUINO_LMIC_VERSION)); ARDUINO_LMIC_VERSION_GET_LOCAL(ARDUINO_LMIC_VERSION));
showLoraKeys(); showLoraKeys();
#endif // HAS_LORA #endif // HAS_LORA
#if (HAS_GPS) #if (HAS_GPS)
ESP_LOGI(TAG, "TinyGPS+ version %s", TinyGPSPlus::libraryVersion()); ESP_LOGI(TAG, "TinyGPS+ version %s", TinyGPSPlus::libraryVersion());
#endif #endif
}
// open i2c bus // open i2c bus
#ifdef HAS_DISPLAY i2c_init();
Wire.begin(MY_OLED_SDA, MY_OLED_SCL, 400000);
#else
Wire.begin(SDA, SCL, 400000);
#endif
// setup power on boards with power management logic // setup power on boards with power management logic
#ifdef EXT_POWER_SW #ifdef EXT_POWER_SW
@ -197,7 +200,7 @@ void setup() {
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
strcat_P(features, " OLED"); strcat_P(features, " OLED");
DisplayIsOn = cfg.screenon; DisplayIsOn = cfg.screenon;
init_display(!cfg.runmode); // note: blocking call init_display(RTC_runmode == RUNMODE_NORMAL); // note: blocking call
#endif #endif
// scan i2c bus for devices // scan i2c bus for devices
@ -266,9 +269,8 @@ void setup() {
#if (USE_OTA) #if (USE_OTA)
strcat_P(features, " OTA"); strcat_P(features, " OTA");
// reboot to firmware update mode if ota trigger switch is set // reboot to firmware update mode if ota trigger switch is set
if (cfg.runmode == 1) { if (RTC_runmode == RUNMODE_UPDATE) {
cfg.runmode = 0; RTC_runmode = RUNMODE_NORMAL;
saveConfig();
start_ota_update(); start_ota_update();
} }
#endif #endif
@ -283,11 +285,11 @@ void setup() {
} else } else
btStop(); btStop();
#else #else
// remove bluetooth stack to gain more free memory // remove bluetooth stack to gain more free memory
btStop(); btStop();
ESP_ERROR_CHECK(esp_bt_mem_release(ESP_BT_MODE_BTDM)); ESP_ERROR_CHECK(esp_bt_mem_release(ESP_BT_MODE_BTDM));
ESP_ERROR_CHECK(esp_coex_preference_set( ESP_ERROR_CHECK(esp_coex_preference_set(
ESP_COEX_PREFER_WIFI)); // configure Wifi/BT coexist lib ESP_COEX_PREFER_WIFI)); // configure Wifi/BT coexist lib
#endif #endif
// initialize gps // initialize gps
@ -314,7 +316,7 @@ void setup() {
// initialize LoRa // initialize LoRa
#if (HAS_LORA) #if (HAS_LORA)
strcat_P(features, " LORA"); strcat_P(features, " LORA");
assert(lora_stack_init() == ESP_OK); assert(lora_stack_init(RTC_runmode == RUNMODE_WAKEUP) == ESP_OK);
#endif #endif
// initialize SPI // initialize SPI
@ -338,11 +340,11 @@ void setup() {
#if PAYLOAD_ENCODER == 1 #if PAYLOAD_ENCODER == 1
strcat_P(features, " PLAIN"); strcat_P(features, " PLAIN");
#elif PAYLOAD_ENCODER == 2 #elif PAYLOAD_ENCODER == 2
strcat_P(features, " PACKED"); strcat_P(features, " PACKED");
#elif PAYLOAD_ENCODER == 3 #elif PAYLOAD_ENCODER == 3
strcat_P(features, " LPPDYN"); strcat_P(features, " LPPDYN");
#elif PAYLOAD_ENCODER == 4 #elif PAYLOAD_ENCODER == 4
strcat_P(features, " LPPPKD"); strcat_P(features, " LPPPKD");
#endif #endif
// initialize RTC // initialize RTC
@ -369,10 +371,10 @@ void setup() {
// function gets it's seed from RF noise // function gets it's seed from RF noise
get_salt(); // get new 16bit for salting hashes get_salt(); // get new 16bit for salting hashes
#else #else
// switch off wifi // switch off wifi
WiFi.mode(WIFI_OFF); WiFi.mode(WIFI_OFF);
esp_wifi_stop(); esp_wifi_stop();
esp_wifi_deinit(); esp_wifi_deinit();
#endif #endif
// start state machine // start state machine
@ -465,6 +467,9 @@ void setup() {
// show compiled features // show compiled features
ESP_LOGI(TAG, "Features:%s", features); ESP_LOGI(TAG, "Features:%s", features);
// set runmode to normal
RTC_runmode = RUNMODE_NORMAL;
vTaskDelete(NULL); vTaskDelete(NULL);
} // setup() } // setup()

View File

@ -5,11 +5,14 @@
// Local logging tag // Local logging tag
static const char TAG[] = __FILE__; 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 #ifdef HAS_PMU
AXP20X_Class pmu; AXP20X_Class pmu;
void power_event_IRQ(void) { void AXP192_powerevent_IRQ(void) {
pmu.readIRQ(); pmu.readIRQ();
@ -34,10 +37,12 @@ void power_event_IRQ(void) {
if (pmu.isBattTempHighIRQ()) if (pmu.isBattTempHighIRQ())
ESP_LOGI(TAG, "Battery low temperature."); ESP_LOGI(TAG, "Battery low temperature.");
// display on/off // esp32 sleep mode, can be exited by pressing user button
// if (pmu.isPEKShortPressIRQ()) { #ifdef HAS_BUTTON
// cfg.screenon = !cfg.screenon; if (pmu.isPEKShortPressIRQ() && (RTC_runmode == RUNMODE_NORMAL)) {
//} enter_deepsleep(0, HAS_BUTTON);
}
#endif
// shutdown power // shutdown power
if (pmu.isPEKLongtPressIRQ()) { if (pmu.isPEKLongtPressIRQ()) {
@ -60,7 +65,8 @@ void AXP192_power(bool on) {
pmu.setChgLEDMode(AXP20X_LED_BLINK_1HZ); pmu.setChgLEDMode(AXP20X_LED_BLINK_1HZ);
} else { } else {
pmu.setChgLEDMode(AXP20X_LED_OFF); 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_LDO3, AXP202_OFF);
pmu.setPowerOutPut(AXP192_LDO2, 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 #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) { void calibrate_voltage(void) {
#ifdef BAT_MEASURE_ADC #ifdef BAT_MEASURE_ADC
// configure ADC // configure ADC

View File

@ -37,7 +37,7 @@ void set_reset(uint8_t val[]) {
case 9: // reset and ask for software update via Wifi OTA case 9: // reset and ask for software update via Wifi OTA
ESP_LOGI(TAG, "Remote command: software update via Wifi"); ESP_LOGI(TAG, "Remote command: software update via Wifi");
#if (USE_OTA) #if (USE_OTA)
cfg.runmode = 1; RTC_runmode = RUNMODE_UPDATE;
#endif // USE_OTA #endif // USE_OTA
break; break;