mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-29 10:17:30 +02:00
esp_modem: Added modem_console commands for deep-sleep and modem PSM.
This commit is contained in:
@ -163,4 +163,10 @@ menu "Example Configuration"
|
|||||||
Buffer size of UART RX buffer.
|
Buffer size of UART RX buffer.
|
||||||
endmenu
|
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
|
endmenu
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
#include "esp_console.h"
|
#include "esp_console.h"
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
|
#include "esp_sleep.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
#include "cxx_include/esp_modem_dte.hpp"
|
#include "cxx_include/esp_modem_dte.hpp"
|
||||||
#include "esp_modem_config.h"
|
#include "esp_modem_config.h"
|
||||||
#include "cxx_include/esp_modem_api.hpp"
|
#include "cxx_include/esp_modem_api.hpp"
|
||||||
@ -41,7 +43,7 @@
|
|||||||
return 0; \
|
return 0; \
|
||||||
} else { \
|
} else { \
|
||||||
ESP_LOGE(TAG, "Failed with %s", err == command_result::TIMEOUT ? "TIMEOUT":"ERROR"); \
|
ESP_LOGE(TAG, "Failed with %s", err == command_result::TIMEOUT ? "TIMEOUT":"ERROR"); \
|
||||||
return 1; \
|
return 1; \
|
||||||
} } while (0)
|
} } while (0)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,6 +51,9 @@
|
|||||||
*/
|
*/
|
||||||
#define DEFAULT_APN "my_apn"
|
#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_http(void);
|
||||||
extern "C" void modem_console_register_ping(void);
|
extern "C" void modem_console_register_ping(void);
|
||||||
|
|
||||||
@ -59,8 +64,37 @@ using namespace esp_modem;
|
|||||||
static SignalGroup exit_signal;
|
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)
|
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(nvs_flash_init());
|
||||||
ESP_ERROR_CHECK(esp_netif_init());
|
ESP_ERROR_CHECK(esp_netif_init());
|
||||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||||
@ -115,7 +149,7 @@ extern "C" void app_main(void)
|
|||||||
while (1) {
|
while (1) {
|
||||||
exit_signal.clear(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
|
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...");
|
ESP_LOGI(TAG, "Waiting for USB device connection...");
|
||||||
auto dte = create_usb_dte(&dte_config);
|
auto dte = create_usb_dte(&dte_config);
|
||||||
dte->set_error_cb([&](terminal_error err) {
|
dte->set_error_cb([&](terminal_error err) {
|
||||||
@ -129,10 +163,10 @@ extern "C" void app_main(void)
|
|||||||
#else
|
#else
|
||||||
#error Invalid serial connection to modem.
|
#error Invalid serial connection to modem.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert(dce != nullptr);
|
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)) {
|
if (command_result::OK != dce->set_flow_control(2, 2)) {
|
||||||
ESP_LOGE(TAG, "Failed to set the set_flow_control mode");
|
ESP_LOGE(TAG, "Failed to set the set_flow_control mode");
|
||||||
return;
|
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_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));
|
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_http();
|
||||||
modem_console_register_ping();
|
modem_console_register_ping();
|
||||||
const struct SetModeArgs {
|
const struct SetModeArgs {
|
||||||
@ -160,7 +214,10 @@ extern "C" void app_main(void)
|
|||||||
} else if (mode == "PPP") {
|
} else if (mode == "PPP") {
|
||||||
dev_mode = esp_modem::modem_mode::DATA_MODE;
|
dev_mode = esp_modem::modem_mode::DATA_MODE;
|
||||||
} else if (mode == "CMUX") {
|
} 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;
|
dev_mode = esp_modem::modem_mode::CMUX_MODE;
|
||||||
|
mode_rtc = dev_mode;
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "Unsupported mode: %s", mode.c_str());
|
ESP_LOGE(TAG, "Unsupported mode: %s", mode.c_str());
|
||||||
return 1;
|
return 1;
|
||||||
@ -170,6 +227,8 @@ extern "C" void app_main(void)
|
|||||||
ESP_LOGE(TAG, "Failed to set the desired mode");
|
ESP_LOGE(TAG, "Failed to set the desired mode");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
mode_rtc = dev_mode;
|
||||||
|
|
||||||
ESP_LOGI(TAG, "OK");
|
ESP_LOGI(TAG, "OK");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -277,6 +336,7 @@ extern "C" void app_main(void)
|
|||||||
if (c->get_count_of(&SetApn::apn)) {
|
if (c->get_count_of(&SetApn::apn)) {
|
||||||
auto apn = c->get_string_of(&SetApn::apn);
|
auto apn = c->get_string_of(&SetApn::apn);
|
||||||
ESP_LOGI(TAG, "Setting the APN=%s...", apn.c_str());
|
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));
|
auto new_pdp = std::unique_ptr<PdpContext>(new PdpContext(apn));
|
||||||
dce->get_module()->configure_pdp_context(std::move(new_pdp));
|
dce->get_module()->configure_pdp_context(std::move(new_pdp));
|
||||||
ESP_LOGI(TAG, "OK");
|
ESP_LOGI(TAG, "OK");
|
||||||
@ -289,6 +349,83 @@ extern "C" void app_main(void)
|
|||||||
exit_signal.set(1);
|
exit_signal.set(1);
|
||||||
return 0;
|
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
|
// start console REPL
|
||||||
ESP_ERROR_CHECK(esp_console_start_repl(s_repl));
|
ESP_ERROR_CHECK(esp_console_start_repl(s_repl));
|
||||||
// wait for exit
|
// wait for exit
|
||||||
@ -296,7 +433,7 @@ extern "C" void app_main(void)
|
|||||||
s_repl->del(s_repl);
|
s_repl->del(s_repl);
|
||||||
ESP_LOGI(TAG, "Exiting...%d", esp_get_free_heap_size());
|
ESP_LOGI(TAG, "Exiting...%d", esp_get_free_heap_size());
|
||||||
#if defined(CONFIG_EXAMPLE_SERIAL_CONFIG_USB)
|
#if defined(CONFIG_EXAMPLE_SERIAL_CONFIG_USB)
|
||||||
// USB example runs in a loop to demonstrate hot-plugging and sudden disconnection features.
|
// USB example runs in a loop to demonstrate hot-plugging and sudden disconnection features.
|
||||||
} // while (1)
|
} // while (1)
|
||||||
#endif
|
#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_SUPPORT=y
|
||||||
|
# CONFIG_LWIP_PPP_ENABLE_IPV6 is not set
|
||||||
CONFIG_LWIP_PPP_PAP_SUPPORT=y
|
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