From a037351f217e234c6d3aea7a888f81538cb107c5 Mon Sep 17 00:00:00 2001 From: Jan Grewe <jan@faked.org> Date: Fri, 31 Jul 2020 01:52:28 +0200 Subject: [PATCH] first working version with deepsleep --- platformio.ini | 2 - src/config.h.sample | 13 +-- src/main.cpp | 236 ++++++++++++++++++++++++++++++-------------- 3 files changed, 164 insertions(+), 87 deletions(-) diff --git a/platformio.ini b/platformio.ini index 925298c..a75b147 100644 --- a/platformio.ini +++ b/platformio.ini @@ -25,6 +25,4 @@ lib_deps = AXP202X_Library@1.1.2 TinyGPSPlus@1.0.2 MCCI Arduino LoRaWAN Library@0.8.0 - OneButton@0.0.0-alpha+sha.eb583d713a CayenneLPP@1.1.0 - diff --git a/src/config.h.sample b/src/config.h.sample index a260387..a457d04 100644 --- a/src/config.h.sample +++ b/src/config.h.sample @@ -1,10 +1,5 @@ +#define TIME_TO_SLEEP 900 // 15 minutes -//char DevEUIString[] = "0102030405060708"; -//char AppEUIString[] = "70B3D50A0B0C0D0E"; -//char AppKeyString[] = "00112233445566778899AABBCCDDEEFF"; - -#define TTN_DEVEUI { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 }; // LSB / little-endian / "byte order reversed" -#define TTN_APPEUI { 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0xD5, 0xB3, 0x70 }; // LSB / little-endian / "byte order reversed" -#define TTN_APPKEY { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }; // MSB / big-endian / "byte order same as string" - -#define BUTTON_PIN 38 +#define TTN_DEVEUI { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 }; // LSB +#define TTN_APPEUI { 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0xD5, 0xB3, 0x70 }; // LSB +#define TTN_APPKEY { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF }; // MSB diff --git a/src/main.cpp b/src/main.cpp index e9ffc7d..b7e847c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -55,7 +55,7 @@ const cLoRaWAN::lmic_pinmap pinMap = { .nss = 18, .rxtx = cLoRaWAN::lmic_pinmap::LMIC_UNUSED_PIN, .rst = 23, - .dio = {26, 33, cLoRaWAN::lmic_pinmap::LMIC_UNUSED_PIN}, + .dio = {26, 33, 32}, }; AXP20X_Class axp; @@ -64,8 +64,11 @@ TinyGPSPlus gps; cLoRaWAN LoRaWAN{}; CayenneLPP lpp(55); DynamicJsonDocument jsonBuffer(1024); -OneButton btn = OneButton(BUTTON_PIN, true, true); -unsigned long statusTimer; +bool gpsFix = false; +bool statusSending = false; +bool statusSent = false; +unsigned long timerGpsFix; +RTC_DATA_ATTR int bootCount = 0; void onEvent(ev_t ev) { @@ -90,6 +93,7 @@ void onEvent(ev_t ev) break; case EV_JOINED: Serial.println(F("EV_JOINED")); + axp.setChgLEDMode(AXP20X_LED_LOW_LEVEL); break; case EV_RFU1: Serial.println(F("EV_RFU1")); @@ -111,6 +115,9 @@ void onEvent(ev_t ev) Serial.println(LMIC.dataLen); Serial.println(F(" bytes of payload")); } + // this allows going to deep sleep + statusSending = false; + statusSent = true; break; case EV_LOST_TSYNC: Serial.println(F("EV_LOST_TSYNC")); @@ -138,6 +145,9 @@ void onEvent(ev_t ev) break; case EV_JOIN_TXCOMPLETE: Serial.println(F("EV_JOIN_TXCOMPLETE: no JoinAccept")); + // this allows restarting + statusSending = false; + statusSent = false; break; default: Serial.println(F("Unknown event " + (unsigned)ev)); @@ -145,39 +155,8 @@ void onEvent(ev_t ev) } } -void setupPower() -{ - if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) - { - Serial.println("AXP192 Begin PASS"); - } - else - { - Serial.println("AXP192 Begin FAIL"); - } - axp.setPowerOutPut(AXP192_DCDC1, AXP202_OFF); // OLED : off - axp.setPowerOutPut(AXP192_DCDC2, AXP202_OFF); // N/C : off - axp.setPowerOutPut(AXP192_DCDC3, AXP202_ON); // ESP32 : on - axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); // LORA : on - axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); // GPS : on - axp.setDCDC3Voltage(3300); // ESP32 : 3.3V - axp.setLDO2Voltage(3300); // LORA : 3.3V - axp.setLDO3Voltage(3300); // GPS : 3.3V - axp.setChgLEDMode(AXP20X_LED_OFF); -} - -void setupGps() +void printPowerStatus() { - GPS.begin(9600, SERIAL_8N1, 34, 12); // IO34: RX, IO12: TX -} - -void printStatus() -{ - axp.setChgLEDMode(AXP20X_LED_LOW_LEVEL); - while (GPS.available()) - { - gps.encode(GPS.read()); - } Serial.println("##############################"); Serial.println("--- Power ---"); Serial.printf("DCDC1/OLED Status : %s\n", axp.isDCDC1Enable() ? "enabled" : "disabled"); @@ -204,79 +183,184 @@ void printStatus() } Serial.println("--- Chip ---"); Serial.printf("Chip Temp : %.1f C°\n", axp.getTemp() / 10); + Serial.println("##############################"); +} + +void printGpsStatus() +{ + while (GPS.available()) + { + gps.encode(GPS.read()); + } + Serial.println("##############################"); Serial.println("--- GPS ---"); - Serial.print("Latitude : "); - Serial.println(gps.location.lat(), 5); - Serial.print("Longitude : "); - Serial.println(gps.location.lng(), 4); - Serial.print("Satellites : "); - Serial.println(gps.satellites.value()); - Serial.print("Altitude : "); - Serial.print(gps.altitude.meters()); - Serial.println("M"); - Serial.print("Time : "); - Serial.print(gps.time.hour()); - Serial.print(":"); - Serial.print(gps.time.minute()); - Serial.print(":"); - Serial.println(gps.time.second()); - Serial.print("Speed : "); - Serial.println(gps.speed.kmph()); + Serial.printf("Has Fix : %s\n", gps.satellites.isValid() ? "true" : "false"); + Serial.printf("Latitude : %f\n", gps.location.lat()); + Serial.printf("Longitude : %f\n", gps.location.lng()); + Serial.printf("Satellites : %d\n", gps.satellites.value()); + Serial.printf("Altitude : %g m\n", gps.altitude.meters()); + Serial.printf("Time : %02d:%02d:%02d\n", gps.time.hour(), gps.time.minute(), gps.time.second()); + Serial.printf("Speed : %g\n", gps.speed.kmph()); Serial.println("##############################"); - axp.setChgLEDMode(AXP20X_LED_OFF); } -void do_send() +void setupPower() { - // Check if there is not a current TX/RX job running - if (LMIC.opmode & OP_TXRXPEND) + if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) { - Serial.println(F("OP_TXRXPEND, not sending")); + Serial.println("AXP192 Begin PASS"); } else { + Serial.println("AXP192 Begin FAIL"); + } + axp.setPowerOutPut(AXP192_DCDC1, AXP202_OFF); // OLED : off + axp.setPowerOutPut(AXP192_DCDC2, AXP202_OFF); // N/C : off + axp.setPowerOutPut(AXP192_DCDC3, AXP202_ON); // ESP32 : on + axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); // LORA : on + axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); // GPS : on + /* + axp.setDCDC3Voltage(3300); // ESP32 : 3.3V + axp.setLDO2Voltage(3300); // LORA : 3.3V + axp.setLDO3Voltage(3300); // GPS : 3.3V + */ + axp.setChgLEDMode(AXP20X_LED_OFF); + printPowerStatus(); +} + +void setupGps() +{ + GPS.begin(9600, SERIAL_8N1, 34, 12); // IO34: RX, IO12: TX +} + +bool checkGpsFix() +{ + if (millis() - timerGpsFix >= 1000 * 1) // 1 second + { + Serial.println("Waiting for GPS fix..."); while (GPS.available()) { gps.encode(GPS.read()); } - lpp.reset(); - lpp.addGPS(1, gps.location.lat(), gps.location.lng(), gps.altitude.meters()); - lpp.addAnalogInput(2, axp.getBattVoltage()/1000); + if (gps.satellites.value() >= 3 && + gps.satellites.isValid() && + gps.location.isValid()) + { + printGpsStatus(); + return true; + } + timerGpsFix = millis(); + } + return false; +} + +void createPayload() +{ + while (GPS.available()) + { + gps.encode(GPS.read()); + } + lpp.reset(); + lpp.addGPS(1, gps.location.lat(), gps.location.lng(), gps.altitude.meters()); + lpp.addAnalogInput(2, axp.getBattVoltage() / 1000); + // debug output + JsonObject json = jsonBuffer.to<JsonObject>(); + lpp.decodeTTN(lpp.getBuffer(), lpp.getSize(), json); + serializeJsonPretty(json, Serial); + Serial.println(); +} + +void sendPayload() +{ + if (LMIC.opmode & OP_TXRXPEND) + { + Serial.println(F("OP_TXRXPEND, not sending")); + } + else + { LMIC_setTxData2(1, lpp.getBuffer(), lpp.getSize(), 0); Serial.println(F("Packet queued")); Serial.println(); - JsonObject json = jsonBuffer.to<JsonObject>(); - lpp.decodeTTN(lpp.getBuffer(), lpp.getSize(), json); - serializeJsonPretty(json, Serial); - Serial.println(); } } -static void handleClick() +void sendStatus() { - printStatus(); - do_send(); + Serial.println("Sending status..."); + axp.setChgLEDMode(AXP20X_LED_BLINK_4HZ); + createPayload(); + sendPayload(); + statusSending = true; +} + +void doSleep() +{ + Serial.println("Going to sleep for " + String(TIME_SLEEP) + " seconds."); + axp.setPowerOutPut(AXP192_LDO2, AXP202_OFF); // LORA : off + axp.setPowerOutPut(AXP192_LDO3, AXP202_OFF); // GPS : off + axp.setChgLEDMode(AXP20X_LED_OFF); + esp_sleep_enable_ext0_wakeup(GPIO_NUM_38, LOW); // wake up with "user" button (middle) + esp_sleep_enable_timer_wakeup(1000000 * TIME_SLEEP); + esp_deep_sleep_start(); +} + +void print_wakeup_reason() +{ + esp_sleep_wakeup_cause_t wakeup_reason; + + wakeup_reason = esp_sleep_get_wakeup_cause(); + + switch (wakeup_reason) + { + case ESP_SLEEP_WAKEUP_EXT0: + Serial.println("Wakeup caused by external signal using RTC_IO"); + break; + case ESP_SLEEP_WAKEUP_EXT1: + Serial.println("Wakeup caused by external signal using RTC_CNTL"); + break; + case ESP_SLEEP_WAKEUP_TIMER: + Serial.println("Wakeup caused by timer"); + break; + case ESP_SLEEP_WAKEUP_TOUCHPAD: + Serial.println("Wakeup caused by touchpad"); + break; + case ESP_SLEEP_WAKEUP_ULP: + Serial.println("Wakeup caused by ULP program"); + break; + default: + Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason); + break; + } } void setup() { Serial.begin(115200); Wire.begin(21, 22); + ++bootCount; + Serial.println("Boot number: " + String(bootCount)); + print_wakeup_reason(); setupPower(); setupGps(); LoRaWAN.begin(pinMap); - btn.attachClick(handleClick); - printStatus(); - statusTimer = millis(); + timerGpsFix = millis(); + axp.setChgLEDMode(AXP20X_LED_BLINK_1HZ); } void loop() { LoRaWAN.loop(); - btn.tick(); - if (millis() - statusTimer >= 1000 * 30) { - printStatus(); - do_send(); - statusTimer = millis(); - } + + if (!gpsFix) + { + gpsFix = checkGpsFix(); + } + else if (gpsFix && !statusSending && !statusSent) + { + sendStatus(); + } + else if (statusSent) + { + doSleep(); + } } -- GitLab