forked from espressif/esp-protocols
Merge pull request #155 from espressif-abhikroy/esp_modem/power_saving_mode_commands
esp_modem: Added modem_console commands for deep-sleep and modem PSM. (IDFGH-8468)
This commit is contained in:
@ -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
|
||||
|
@ -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<<GPIO_OUTPUT_PWRKEY)
|
||||
|
||||
extern "C" void modem_console_register_http(void);
|
||||
extern "C" void modem_console_register_ping(void);
|
||||
|
||||
@ -59,8 +64,37 @@ using namespace esp_modem;
|
||||
static SignalGroup exit_signal;
|
||||
|
||||
|
||||
void config_gpio(void)
|
||||
{
|
||||
gpio_config_t io_conf = {}; //zero-initialize the config structure.
|
||||
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE; //disable interrupt
|
||||
io_conf.mode = GPIO_MODE_OUTPUT; //set as output mode
|
||||
io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; //bit mask of the pins that you want to set,e.g.GPIO18/19
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; //disable pull-down mode
|
||||
io_conf.pull_up_en = GPIO_PULLUP_DISABLE; //disable pull-up mode
|
||||
|
||||
gpio_config(&io_conf); //configure GPIO with the given settings
|
||||
}
|
||||
|
||||
void wakeup_modem(void)
|
||||
{
|
||||
/* Power on the modem */
|
||||
ESP_LOGI(TAG, "Power on the modem");
|
||||
gpio_set_level(GPIO_OUTPUT_PWRKEY, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
gpio_set_level(GPIO_OUTPUT_PWRKEY, 0);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
}
|
||||
|
||||
extern "C" void app_main(void)
|
||||
{
|
||||
static RTC_RODATA_ATTR char apn_rtc[20] = DEFAULT_APN;
|
||||
static RTC_DATA_ATTR modem_mode mode_rtc = esp_modem::modem_mode::COMMAND_MODE;
|
||||
|
||||
config_gpio();
|
||||
|
||||
ESP_ERROR_CHECK(nvs_flash_init());
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
@ -115,7 +149,7 @@ extern "C" void app_main(void)
|
||||
while (1) {
|
||||
exit_signal.clear(1);
|
||||
struct esp_modem_usb_term_config usb_config = ESP_MODEM_DEFAULT_USB_CONFIG(0x2C7C, 0x0296, 2); // VID, PID and interface num of BG96 modem
|
||||
const esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_USB_CONFIG(usb_config);
|
||||
const esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_USB_CONFIG(usb_config);
|
||||
ESP_LOGI(TAG, "Waiting for USB device connection...");
|
||||
auto dte = create_usb_dte(&dte_config);
|
||||
dte->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<PdpContext>(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<PdpContext>(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, "<tout>", "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, "<Requested_Periodic-TAU>", "T3412 Timer in 8-bit format"),
|
||||
active_time(STR0, nullptr, nullptr, "<Requested_Active-Time>", "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
|
||||
}
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user