diff --git a/components/esp_modem/examples/modem_console/main/Kconfig.projbuild b/components/esp_modem/examples/modem_console/main/Kconfig.projbuild index 70ad5996b..482d466d2 100644 --- a/components/esp_modem/examples/modem_console/main/Kconfig.projbuild +++ b/components/esp_modem/examples/modem_console/main/Kconfig.projbuild @@ -163,4 +163,10 @@ menu "Example Configuration" Buffer size of UART RX buffer. endmenu + config EXAMPLE_MODEM_PWRKEY_PIN + int "PWRKEY Pin Number" + default 18 + range 0 31 + help + Pin number connected to modem's power key pin. endmenu diff --git a/components/esp_modem/examples/modem_console/main/modem_console_main.cpp b/components/esp_modem/examples/modem_console/main/modem_console_main.cpp index 3c375d65f..9ace57c1e 100644 --- a/components/esp_modem/examples/modem_console/main/modem_console_main.cpp +++ b/components/esp_modem/examples/modem_console/main/modem_console_main.cpp @@ -15,6 +15,8 @@ #include "esp_console.h" #include "esp_event.h" #include "nvs_flash.h" +#include "esp_sleep.h" +#include "driver/gpio.h" #include "cxx_include/esp_modem_dte.hpp" #include "esp_modem_config.h" #include "cxx_include/esp_modem_api.hpp" @@ -41,7 +43,7 @@ return 0; \ } else { \ ESP_LOGE(TAG, "Failed with %s", err == command_result::TIMEOUT ? "TIMEOUT":"ERROR"); \ - return 1; \ + return 1; \ } } while (0) /** @@ -49,6 +51,9 @@ */ #define DEFAULT_APN "my_apn" +#define GPIO_OUTPUT_PWRKEY (gpio_num_t)CONFIG_EXAMPLE_MODEM_PWRKEY_PIN +#define GPIO_OUTPUT_PIN_SEL (1ULL<set_error_cb([&](terminal_error err) { @@ -129,10 +163,10 @@ extern "C" void app_main(void) #else #error Invalid serial connection to modem. #endif - + assert(dce != nullptr); - if(dte_config.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) { + if (dte_config.uart_config.flow_control == ESP_MODEM_FLOW_CONTROL_HW) { if (command_result::OK != dce->set_flow_control(2, 2)) { ESP_LOGE(TAG, "Failed to set the set_flow_control mode"); return; @@ -145,6 +179,26 @@ extern "C" void app_main(void) esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &s_repl)); + switch (esp_sleep_get_wakeup_cause()) { + case ESP_SLEEP_WAKEUP_TIMER: + if (esp_modem::modem_mode::CMUX_MODE == mode_rtc) { + ESP_LOGI(TAG, "Deep sleep reset\n"); + + /* Set APN */ + auto new_pdp = std::unique_ptr(new PdpContext(apn_rtc)); + dce->get_module()->configure_pdp_context(std::move(new_pdp)); + + /* Set CMUX mode */ + if (!dce->set_mode(mode_rtc)) { + ESP_LOGE(TAG, "Failed to set the desired mode"); + } + } + break; + case ESP_SLEEP_WAKEUP_UNDEFINED: + default: + ESP_LOGD(TAG, "Not a deep sleep reset\n"); + } + modem_console_register_http(); modem_console_register_ping(); const struct SetModeArgs { @@ -160,7 +214,10 @@ extern "C" void app_main(void) } else if (mode == "PPP") { dev_mode = esp_modem::modem_mode::DATA_MODE; } else if (mode == "CMUX") { + /* Even if switching to CMUX fails, we make the DTE multiplex terminal. + (This is potentially a bug and might be fixed eventually) */ dev_mode = esp_modem::modem_mode::CMUX_MODE; + mode_rtc = dev_mode; } else { ESP_LOGE(TAG, "Unsupported mode: %s", mode.c_str()); return 1; @@ -170,6 +227,8 @@ extern "C" void app_main(void) ESP_LOGE(TAG, "Failed to set the desired mode"); return 1; } + mode_rtc = dev_mode; + ESP_LOGI(TAG, "OK"); } return 0; @@ -277,6 +336,7 @@ extern "C" void app_main(void) if (c->get_count_of(&SetApn::apn)) { auto apn = c->get_string_of(&SetApn::apn); ESP_LOGI(TAG, "Setting the APN=%s...", apn.c_str()); + strcpy(apn_rtc, apn.c_str()); auto new_pdp = std::unique_ptr(new PdpContext(apn)); dce->get_module()->configure_pdp_context(std::move(new_pdp)); ESP_LOGI(TAG, "OK"); @@ -289,6 +349,83 @@ extern "C" void app_main(void) exit_signal.set(1); return 0; }); + + /* Put the esp32 into deep sleep */ + const struct DeepSleepArgs { + DeepSleepArgs(): timeout(INT1, nullptr, nullptr, "", "TIMEOUT") {} + CommandArgs timeout; + } deep_sleep_args; + const ConsoleCommand SetDeepSleep("set_deep_sleep", "Put esp32 to deep sleep", &deep_sleep_args, sizeof(deep_sleep_args), [&](ConsoleCommand * c) { + int tout = c->get_int_of(&DeepSleepArgs::timeout); + ESP_LOGI(TAG, "Entering deep sleep for %d sec", tout); + ESP_LOGI(TAG, "Wakeup Cause: %d ", esp_sleep_get_wakeup_cause()); + esp_deep_sleep(tout * 1000000); + return 0; + }); + + /* Wake up modem */ + const ConsoleCommand WakeupModem("wakeup_modem", "Wakes up the modem from PSM", no_args, [&](ConsoleCommand * c) { + wakeup_modem(); + ESP_LOGI(TAG, "OK"); + return 0; + }); + + /* Enable PSM modem */ + const ConsoleCommand EnablePSM("enable_psm", "Enables PSM on the modem", no_args, [&](ConsoleCommand * c) { + std::string out; + CHECK_ERR(dce->at("AT+CPSMS=1", out, 500), ESP_LOGI(TAG, "OK. %s", out.c_str())); + return 0; + }); + + /* Disable PSM modem */ + const ConsoleCommand DisablePSM("disable_psm", "Disables PSM on the modem", no_args, [&](ConsoleCommand * c) { + std::string out; + CHECK_ERR(dce->at("AT+CPSMS=0", out, 500), ESP_LOGI(TAG, "OK. %s", out.c_str())); + return 0; + }); + + /* Get modem PSM cfg */ + const ConsoleCommand GetModemCfg("get_psm_cfg", "Get PSM config", no_args, [&](ConsoleCommand * c) { + std::string out; + CHECK_ERR(dce->at("AT+CPSMS?", out, 500), ESP_LOGI(TAG, "OK. %s", out.c_str())); + return 0; + }); + + /* Set modem PSM config */ + const struct SetPsmCfgArgs { + SetPsmCfgArgs(): + periodic_tau(STR1, nullptr, nullptr, "", "T3412 Timer in 8-bit format"), + active_time(STR0, nullptr, nullptr, "", "T3324 Timer in 8-bit format") {} + CommandArgs periodic_tau; + CommandArgs active_time; + } set_psm_cfg_args; + const ConsoleCommand SetPsmCfg("set_psm_cfg", "Set PSM config", &set_psm_cfg_args, sizeof(set_psm_cfg_args), [&](ConsoleCommand * c) { + std::string out; + auto periodic_tau = c->get_string_of(&SetPsmCfgArgs::periodic_tau); + auto active_time = c->get_string_of(&SetPsmCfgArgs::active_time); + + /* Validate input */ + if ((strlen(periodic_tau.c_str()) != strlen("00000000")) || + (strlen(active_time.c_str()) != strlen("00000000"))) { + ESP_LOGE(TAG, "Failed with ERROR: Invalid argument length"); + return 1; + } + + /* Get PSM config */ + dce->at("AT+CPSMS?", out, 500); + + /* Update PSM config */ + if (out.size() > 8) { + std::string set_cmd = "AT+CPSMS=" + std::to_string(out.c_str()[8] - '0') + ",,,\"" + periodic_tau.c_str() + "\",\"" + active_time.c_str() + "\""; + CHECK_ERR(dce->at(set_cmd, out, 500), ESP_LOGI(TAG, "OK. %s", out.c_str())); + } else { + ESP_LOGE(TAG, "Failed with ERROR: Invalid AT+CPSMS? return length"); + } + + return 0; + }); + + // start console REPL ESP_ERROR_CHECK(esp_console_start_repl(s_repl)); // wait for exit @@ -296,7 +433,7 @@ extern "C" void app_main(void) s_repl->del(s_repl); ESP_LOGI(TAG, "Exiting...%d", esp_get_free_heap_size()); #if defined(CONFIG_EXAMPLE_SERIAL_CONFIG_USB) - // USB example runs in a loop to demonstrate hot-plugging and sudden disconnection features. - } // while (1) + // USB example runs in a loop to demonstrate hot-plugging and sudden disconnection features. +} // while (1) #endif } diff --git a/components/esp_modem/examples/modem_console/sdkconfig.defaults b/components/esp_modem/examples/modem_console/sdkconfig.defaults index 893755f68..e90110de9 100644 --- a/components/esp_modem/examples/modem_console/sdkconfig.defaults +++ b/components/esp_modem/examples/modem_console/sdkconfig.defaults @@ -1,8 +1,12 @@ -# Override some defaults to enable PPP +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration +# +CONFIG_IDF_TARGET="esp32c3" +CONFIG_EXAMPLE_MODEM_DEVICE_SIM7600=y +CONFIG_EXAMPLE_MODEM_UART_TX_PIN=4 +CONFIG_EXAMPLE_MODEM_UART_RX_PIN=5 +CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE=4096 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=7168 CONFIG_LWIP_PPP_SUPPORT=y +# CONFIG_LWIP_PPP_ENABLE_IPV6 is not set CONFIG_LWIP_PPP_PAP_SUPPORT=y -CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096 -# Do not enable IPV6 in dte<->dce link local -CONFIG_LWIP_PPP_ENABLE_IPV6=n -# Disable legacy API -CONFIG_MODEM_LEGACY_API=n