diff --git a/examples/shutdown/CMakeLists.txt b/examples/deep_sleep/CMakeLists.txt similarity index 79% rename from examples/shutdown/CMakeLists.txt rename to examples/deep_sleep/CMakeLists.txt index 4e4be0a..7c07596 100644 --- a/examples/shutdown/CMakeLists.txt +++ b/examples/deep_sleep/CMakeLists.txt @@ -5,4 +5,6 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake) # e.g. list(APPEND EXTRA_COMPONENT_DIRS "/Users/me/Documents/ttn-esp32") list(APPEND EXTRA_COMPONENT_DIRS "../..") -project(shutdown) +#add_definitions(-DLMIC_ENABLE_event_logging=1) + +project(deep_sleep) diff --git a/examples/shutdown/main/CMakeLists.txt b/examples/deep_sleep/main/CMakeLists.txt similarity index 100% rename from examples/shutdown/main/CMakeLists.txt rename to examples/deep_sleep/main/CMakeLists.txt diff --git a/examples/shutdown/main/main.cpp b/examples/deep_sleep/main/main.cpp similarity index 61% rename from examples/shutdown/main/main.cpp rename to examples/deep_sleep/main/main.cpp index 69a93b5..09a6e0f 100644 --- a/examples/shutdown/main/main.cpp +++ b/examples/deep_sleep/main/main.cpp @@ -1,23 +1,23 @@ /******************************************************************************* - * + * * ttn-esp32 - The Things Network device library for ESP-IDF / SX127x - * - * Copyright (c) 2018 Manuel Bleichenbacher - * + * + * Copyright (c) 2021 Manuel Bleichenbacher + * * Licensed under MIT License * https://opensource.org/licenses/MIT * - * Sample program showing how to send and receive messages. + * Sample program sending messages and going to deep sleep in-between. *******************************************************************************/ -#include "freertos/FreeRTOS.h" -#include "esp_event.h" #include "driver/gpio.h" +#include "esp_event.h" +#include "esp_sleep.h" +#include "freertos/FreeRTOS.h" #include "nvs_flash.h" #include "TheThingsNetwork.h" - // NOTE: // The LoRaWAN frequency and the radio chip must be configured by running 'idf.py menuconfig'. // Go to Components / The Things Network, select the appropriate values and save. @@ -32,71 +32,24 @@ const char *devEui = "????????????????"; // AppKey const char *appKey = "????????????????????????????????"; - // Pins and other resources -#define TTN_SPI_HOST HSPI_HOST -#define TTN_SPI_DMA_CHAN 1 -#define TTN_PIN_SPI_SCLK 5 -#define TTN_PIN_SPI_MOSI 27 -#define TTN_PIN_SPI_MISO 19 -#define TTN_PIN_NSS 18 -#define TTN_PIN_RXTX TTN_NOT_CONNECTED -#define TTN_PIN_RST 14 -#define TTN_PIN_DIO0 26 -#define TTN_PIN_DIO1 35 +#define TTN_SPI_HOST HSPI_HOST +#define TTN_SPI_DMA_CHAN 1 +#define TTN_PIN_SPI_SCLK 5 +#define TTN_PIN_SPI_MOSI 27 +#define TTN_PIN_SPI_MISO 19 +#define TTN_PIN_NSS 18 +#define TTN_PIN_RXTX TTN_NOT_CONNECTED +#define TTN_PIN_RST 14 +#define TTN_PIN_DIO0 26 +#define TTN_PIN_DIO1 35 static TheThingsNetwork ttn; -const unsigned TX_INTERVAL = 30; +const unsigned TX_INTERVAL = 60; static uint8_t msgData[] = "Hello, world"; -bool join() -{ - printf("Joining...\n"); - if (ttn.join()) - { - printf("Joined.\n"); - return true; - } - else - { - printf("Join failed. Goodbye\n"); - return false; - } -} - - -void sendMessages(void* pvParameter) -{ - while (1) { - - // Send 2 messages - for (int i = 0; i < 2; i++) - { - printf("Sending message...\n"); - TTNResponseCode res = ttn.transmitMessage(msgData, sizeof(msgData) - 1); - printf(res == kTTNSuccessfulTransmission ? "Message sent.\n" : "Transmission failed.\n"); - - vTaskDelay(TX_INTERVAL * pdMS_TO_TICKS(1000)); - } - - // shutdown - ttn.shutdown(); - - // go to sleep - printf("Sleeping for 30s...\n"); - vTaskDelay(pdMS_TO_TICKS(30000)); - - // startup - ttn.startup(); - - // join again - if (!join()) - return; - } -} - -void messageReceived(const uint8_t* message, size_t length, ttn_port_t port) +void messageReceived(const uint8_t *message, size_t length, ttn_port_t port) { printf("Message of %d bytes received on port %d:", length, port); for (int i = 0; i < length; i++) @@ -110,7 +63,7 @@ extern "C" void app_main(void) // Initialize the GPIO ISR handler service err = gpio_install_isr_service(ESP_INTR_FLAG_IRAM); ESP_ERROR_CHECK(err); - + // Initialize the NVS (non-volatile storage) for saving and restoring the keys err = nvs_flash_init(); ESP_ERROR_CHECK(err); @@ -132,10 +85,42 @@ extern "C" void app_main(void) // The below line can be commented after the first run as the data is saved in NVS ttn.provision(devEui, appEui, appKey); + // Register callback for received messages ttn.onMessage(messageReceived); - if (join()) + // ttn.setAdrEnabled(false); + // ttn.setDataRate(kTTNDataRate_US915_SF7); + // ttn.setMaxTxPower(14); + + if (ttn.resumeAfterDeepSleep()) { - xTaskCreate(sendMessages, "send_messages", 1024 * 4, (void* )0, 3, nullptr); + printf("Resumed from deep sleep.\n"); } + else + { + printf("Joining...\n"); + if (ttn.join()) + { + printf("Joined.\n"); + } + else + { + printf("Join failed. Goodbye\n"); + return; + } + } + + printf("Sending message...\n"); + TTNResponseCode res = ttn.transmitMessage(msgData, sizeof(msgData) - 1); + printf(res == kTTNSuccessfulTransmission ? "Message sent.\n" : "Transmission failed.\n"); + + // Wait until TTN communication is idle and save state + ttn.waitForIdle(); + ttn.prepareForDeepSleep(); + + // Schedule wake up + esp_sleep_enable_timer_wakeup(TX_INTERVAL * 1000000LL); + + printf("Going to deep sleep...\n"); + esp_deep_sleep_start(); } diff --git a/examples/deep_sleep_in_c/main/main.c b/examples/deep_sleep_in_c/main/main.c index 43e9949..0c1e80f 100644 --- a/examples/deep_sleep_in_c/main/main.c +++ b/examples/deep_sleep_in_c/main/main.c @@ -49,6 +49,14 @@ const char *appKey = "????????????????????????????????"; static uint8_t msgData[] = "Hello, world"; +void messageReceived(const uint8_t* message, size_t length, ttn_port_t port) +{ + printf("Message of %d bytes received on port %d:", length, port); + for (int i = 0; i < length; i++) + printf(" %02x", message[i]); + printf("\n"); +} + void app_main(void) { esp_err_t err; @@ -80,6 +88,9 @@ void app_main(void) // The below line can be commented after the first run as the data is saved in NVS ttn_provision(devEui, appEui, appKey); + // Register callback for received messages + ttn_on_message(messageReceived); + // ttn_set_adr_enabled(false); // ttn_set_data_rate(TTN_DR_US915_SF7); // ttn_set_max_tx_pow(14); diff --git a/src/hal/hal_esp32.c b/src/hal/hal_esp32.c index 7972ea1..bc4d362 100755 --- a/src/hal/hal_esp32.c +++ b/src/hal/hal_esp32.c @@ -391,7 +391,12 @@ TickType_t hal_esp32_get_timer_duration(void) return 1; // busy, not waiting if (alarm_time != 0) - return pdMS_TO_TICKS((alarm_time - get_current_time() + 999) / 1000); + { + TickType_t dur = pdMS_TO_TICKS((alarm_time - get_current_time() + 999) / 1000); + if (dur > pdMS_TO_TICKS(30000)) + dur = pdMS_TO_TICKS(200); + return dur; + } return 0; // waiting indefinitely diff --git a/src/ttn.c b/src/ttn.c index d6a7e4d..bf1790e 100644 --- a/src/ttn.c +++ b/src/ttn.c @@ -337,6 +337,7 @@ bool ttn_is_provisioned(void) void ttn_prepare_for_deep_sleep(void) { ttn_rtc_save(); + stop(); } @@ -357,8 +358,8 @@ TickType_t ttn_busy_duration(void) if (duration != 0) return duration; // busy or timer scheduled - if (current_rx_tx_window != TTN_WINDOW_IDLE) - return pdMS_TO_TICKS(100); // within TX/RX window + if ((LMIC.opmode & (OP_JOINING | OP_TXDATA | OP_POLL | OP_TXRXPEND)) != 0) + return pdMS_TO_TICKS(100); // pending action return 0; // idle }