mirror of
https://github.com/espressif/esp-protocols.git
synced 2025-07-29 18:27:31 +02:00
esp_modem/examples: Add an example to synchronise PSM sleep in Sim70XX modem and esp32.
This example enables Power saving mode in Sim70XX modem and tries to synchronise the sleep cycle of the modem with esp32. When the modem wakes up from PSM sleep it wakes up the esp32. While the modem is awake esp32 is set to light sleep. Closes: https://github.com/espressif/esp-protocols/issues/54
This commit is contained in:
@ -0,0 +1,3 @@
|
||||
|
||||
idf_component_register(SRCS "modem_psm.c"
|
||||
INCLUDE_DIRS ".")
|
109
components/esp_modem/examples/modem_psm/main/Kconfig.projbuild
Normal file
109
components/esp_modem/examples/modem_psm/main/Kconfig.projbuild
Normal file
@ -0,0 +1,109 @@
|
||||
|
||||
menu "Example Configuration"
|
||||
|
||||
choice EXAMPLE_MODEM_DEVICE
|
||||
prompt "Choose supported modem device (DCE)"
|
||||
default EXAMPLE_MODEM_DEVICE_SIM7080
|
||||
help
|
||||
Select modem device connected to the ESP DTE.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM7070
|
||||
bool "SIM7070"
|
||||
help
|
||||
SIM7070 is Multi-Band CAT M and NB IoT module.
|
||||
config EXAMPLE_MODEM_DEVICE_SIM7080
|
||||
bool "SIM7080"
|
||||
help
|
||||
SIM7080 is Multi-Band CAT M and NB IoT module.
|
||||
endchoice
|
||||
|
||||
menu "UART Configuration"
|
||||
config EXAMPLE_MODEM_UART_TX_PIN
|
||||
int "TXD Pin Number"
|
||||
default 4
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART TX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RX_PIN
|
||||
int "RXD Pin Number"
|
||||
default 5
|
||||
range 0 31
|
||||
help
|
||||
Pin number of UART RX.
|
||||
|
||||
config EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE
|
||||
int "UART Event Task Stack Size"
|
||||
range 2000 6000
|
||||
default 4096
|
||||
help
|
||||
Stack size of UART event task.
|
||||
|
||||
config EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY
|
||||
int "UART Event Task Priority"
|
||||
range 3 22
|
||||
default 5
|
||||
help
|
||||
Priority of UART event task.
|
||||
|
||||
config EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE
|
||||
int "UART Event Queue Size"
|
||||
range 10 40
|
||||
default 30
|
||||
help
|
||||
Length of UART event queue.
|
||||
|
||||
config EXAMPLE_MODEM_UART_TX_BUFFER_SIZE
|
||||
int "UART TX Buffer Size"
|
||||
range 256 2048
|
||||
default 512
|
||||
help
|
||||
Buffer size of UART TX buffer.
|
||||
|
||||
config EXAMPLE_MODEM_UART_RX_BUFFER_SIZE
|
||||
int "UART RX Buffer Size"
|
||||
range 256 2048
|
||||
default 1024
|
||||
help
|
||||
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.
|
||||
|
||||
config EXAMPLE_MODEM_STATUS_PIN
|
||||
int "STATUS Pin Number"
|
||||
default 19
|
||||
range 0 31
|
||||
help
|
||||
Pin number connected to modem's status pin.
|
||||
|
||||
config EXAMPLE_MODEM_LIGHT_SLEEP_DURATION
|
||||
int "Light Sleep Duration"
|
||||
default 10
|
||||
range 0 15000
|
||||
help
|
||||
Duration in seconds, of which the esp32 goes into light sleep while the modem is awake.
|
||||
|
||||
config EXAMPLE_MODEM_PPP_APN
|
||||
string "Set MODEM APN"
|
||||
default "internet"
|
||||
help
|
||||
Set APN (Access Point Name), a logical name to choose data network
|
||||
|
||||
config EXAMPLE_MODEM_T3412_PERIODIC_TAU
|
||||
string "T3412 Requester Periodic TAU"
|
||||
default "00000100"
|
||||
help
|
||||
T3412 timer, i.e the duration of one awake and sleep cycle of the modem in PSM.
|
||||
|
||||
config EXAMPLE_MODEM_T3324_ACTIVE_TIME
|
||||
string "T3324 Requester Active Time"
|
||||
default "00000001"
|
||||
help
|
||||
T3324 timer, i.e the duration for which the modem stays PSM.
|
||||
|
||||
endmenu
|
202
components/esp_modem/examples/modem_psm/main/modem_psm.c
Normal file
202
components/esp_modem/examples/modem_psm/main/modem_psm.c
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Power Saving Mode(PSM) in Sim70XX modems along with
|
||||
* Deep sleep and Light Sleep modes in esp32.
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "driver/uart.h"
|
||||
#include "string.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "esp_modem_api.h"
|
||||
#include "esp_event.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
|
||||
#define BUF_SIZE 1024
|
||||
|
||||
#define TXD_PIN ((gpio_num_t)CONFIG_EXAMPLE_MODEM_UART_TX_PIN)
|
||||
#define RXD_PIN ((gpio_num_t)CONFIG_EXAMPLE_MODEM_UART_RX_PIN)
|
||||
#define GPIO_INPUT_STATUS ((gpio_num_t)CONFIG_EXAMPLE_MODEM_STATUS_PIN)
|
||||
#define GPIO_OUTPUT_PWRKEY ((gpio_num_t)CONFIG_EXAMPLE_MODEM_PWRKEY_PIN)
|
||||
#define GPIO_OUTPUT_PIN_SEL (1ULL<<GPIO_OUTPUT_PWRKEY)
|
||||
|
||||
#define CHECK_ERR(cmd, success_action) do { \
|
||||
esp_err_t ret = cmd; \
|
||||
if (ret == ESP_OK) { \
|
||||
success_action; \
|
||||
} else { \
|
||||
ESP_LOGE(TAG, "Failed with %s", ret == ESP_ERR_TIMEOUT ? "TIMEOUT":"ERROR"); \
|
||||
} } while (0)
|
||||
|
||||
|
||||
const char *TAG = "modem_psm";
|
||||
RTC_DATA_ATTR static int boot_count = 0;
|
||||
|
||||
|
||||
void dce_init(esp_modem_dce_t **dce, esp_netif_t **esp_netif)
|
||||
{
|
||||
esp_modem_dce_config_t dce_config = ESP_MODEM_DCE_DEFAULT_CONFIG(CONFIG_EXAMPLE_MODEM_PPP_APN);
|
||||
esp_modem_dte_config_t dte_config = ESP_MODEM_DTE_DEFAULT_CONFIG();
|
||||
esp_netif_config_t netif_ppp_config = ESP_NETIF_DEFAULT_PPP();
|
||||
*esp_netif = esp_netif_new(&netif_ppp_config);
|
||||
assert(*esp_netif);
|
||||
|
||||
/* setup UART specific configuration based on kconfig options */
|
||||
dte_config.uart_config.tx_io_num = CONFIG_EXAMPLE_MODEM_UART_TX_PIN;
|
||||
dte_config.uart_config.rx_io_num = CONFIG_EXAMPLE_MODEM_UART_RX_PIN;
|
||||
dte_config.uart_config.rx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE;
|
||||
dte_config.uart_config.tx_buffer_size = CONFIG_EXAMPLE_MODEM_UART_TX_BUFFER_SIZE;
|
||||
dte_config.uart_config.event_queue_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_QUEUE_SIZE;
|
||||
dte_config.task_stack_size = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_STACK_SIZE;
|
||||
dte_config.task_priority = CONFIG_EXAMPLE_MODEM_UART_EVENT_TASK_PRIORITY;
|
||||
dte_config.dte_buffer_size = CONFIG_EXAMPLE_MODEM_UART_RX_BUFFER_SIZE / 2;
|
||||
|
||||
ESP_LOGI(TAG, "Initializing esp_modem for a generic module...");
|
||||
*dce = esp_modem_new(&dte_config, &dce_config, *esp_netif);
|
||||
assert(*dce);
|
||||
}
|
||||
|
||||
void config_pwrkey_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 power_on_modem(esp_modem_dce_t *dce)
|
||||
{
|
||||
rtc_gpio_hold_dis(GPIO_OUTPUT_PWRKEY);
|
||||
|
||||
/* Power on the modem */
|
||||
ESP_LOGI(TAG, "Power on the modem");
|
||||
gpio_set_level(GPIO_OUTPUT_PWRKEY, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
gpio_set_level(GPIO_OUTPUT_PWRKEY, 0);
|
||||
|
||||
rtc_gpio_hold_en(GPIO_OUTPUT_PWRKEY);
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
|
||||
CHECK_ERR(esp_modem_sync(dce), ESP_LOGI(TAG, "OK"));
|
||||
}
|
||||
|
||||
void power_down_modem(esp_modem_dce_t *dce)
|
||||
{
|
||||
char data[BUF_SIZE];
|
||||
|
||||
ESP_LOGI(TAG, "Power down the modem");
|
||||
|
||||
/* Power down the modem by AT command */
|
||||
CHECK_ERR(esp_modem_at(dce, "AT+CPOWD=1", data, 500), ESP_LOGI(TAG, "OK. %s", data));
|
||||
}
|
||||
|
||||
void run_at(esp_modem_dce_t *dce, uint8_t count)
|
||||
{
|
||||
for (int i = 0; i < count; i++) {
|
||||
CHECK_ERR(esp_modem_sync(dce), ESP_LOGI(TAG, "OK"));
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
}
|
||||
|
||||
void run_at_ping(esp_modem_dce_t *dce)
|
||||
{
|
||||
char data[BUF_SIZE];
|
||||
int rssi, ber;
|
||||
CHECK_ERR(esp_modem_get_signal_quality(dce, &rssi, &ber), ESP_LOGI(TAG, "OK. rssi=%d, ber=%d", rssi, ber));
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
|
||||
CHECK_ERR(esp_modem_at(dce, "AT+CPSMS?", data, 500), ESP_LOGI(TAG, "OK. %s", data));
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
|
||||
CHECK_ERR(esp_modem_at(dce, "AT+CPSI?", data, 500), ESP_LOGI(TAG, "OK. %s", data)); // Inquiring UE system information
|
||||
CHECK_ERR(esp_modem_at(dce, "AT+CNACT=0,1", data, 500), ESP_LOGI(TAG, "OK. %s", data)); // Activate the APP network
|
||||
CHECK_ERR(esp_modem_at(dce, "AT+SNPDPID=0", data, 500), ESP_LOGI(TAG, "OK. %s", data)); // Select PDP index for PING
|
||||
CHECK_ERR(esp_modem_at(dce, "AT+SNPING4=\"8.8.8.8\",3,16,1000", data, 500), ESP_LOGI(TAG, "OK. %s", data)); // Send IPv4 PING
|
||||
CHECK_ERR(esp_modem_at(dce, "AT+CNACT=0,0", data, 500), ESP_LOGI(TAG, "OK. %s", data)); // Deactivate the APP network
|
||||
}
|
||||
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
char *cmd;
|
||||
char data[BUF_SIZE];
|
||||
esp_modem_dce_t *dce = NULL;
|
||||
esp_netif_t *esp_netif = NULL;
|
||||
esp_sleep_wakeup_cause_t wakeup_cause = esp_sleep_get_wakeup_cause();
|
||||
ESP_LOGI(TAG, "Deep sleep Wake Up Cause: %d\n", wakeup_cause);
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
dce_init(&dce, &esp_netif);
|
||||
|
||||
switch (wakeup_cause) {
|
||||
case ESP_SLEEP_WAKEUP_UNDEFINED:
|
||||
/* Power on the modem */
|
||||
config_pwrkey_gpio();
|
||||
power_on_modem(dce);
|
||||
|
||||
run_at(dce, 3);
|
||||
|
||||
/* Configure Power Saving Mode in the modem */
|
||||
asprintf(&cmd, "AT+CPSMS=1,,,\"%s\",\"%s\"\r\n", CONFIG_EXAMPLE_MODEM_T3412_PERIODIC_TAU,
|
||||
CONFIG_EXAMPLE_MODEM_T3324_ACTIVE_TIME);
|
||||
CHECK_ERR(esp_modem_at(dce, cmd, data, 500), ESP_LOGI(TAG, "OK. %s", data));
|
||||
free(cmd);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
|
||||
/* Perform Communication tasks */
|
||||
run_at_ping(dce);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
break;
|
||||
|
||||
case ESP_SLEEP_WAKEUP_EXT0:
|
||||
run_at(dce, 3);
|
||||
|
||||
/* Perform Communication tasks */
|
||||
run_at_ping(dce);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
break;
|
||||
|
||||
default:
|
||||
ESP_LOGI(TAG, "Not a deep sleep reset: %d\n", wakeup_cause);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Light sleep before going to Deep sleep\n\n");
|
||||
|
||||
/* Enter light sleep mode as long as the modem is awake */
|
||||
esp_sleep_enable_timer_wakeup(CONFIG_EXAMPLE_MODEM_LIGHT_SLEEP_DURATION * 1000000);
|
||||
esp_light_sleep_start();
|
||||
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_TIMER); // Disabling timer before going to deep sleep.
|
||||
wakeup_cause = esp_sleep_get_wakeup_cause();
|
||||
ESP_LOGI(TAG, "Light sleep wakeup cause: %d\n", wakeup_cause);
|
||||
|
||||
/* DCE and netif clean-up */
|
||||
/* In Deep-sleep mode, the CPUs, most of the RAM, and all digital peripherals are powered off.
|
||||
* So dce and netif would be lost anyway if they are not explicitly destroyed.
|
||||
* But since dce is also linked with UART communication with the modem it's better to exit gracefully before going to deep sleep.
|
||||
*/
|
||||
esp_modem_destroy(dce);
|
||||
esp_netif_destroy(esp_netif);
|
||||
|
||||
/* Enable wakeup if status pin is high */
|
||||
esp_sleep_enable_ext0_wakeup(GPIO_INPUT_STATUS, 1);
|
||||
|
||||
ESP_LOGI(TAG, "Entering deep sleep: %d\n", boot_count++);
|
||||
esp_deep_sleep_start();
|
||||
}
|
Reference in New Issue
Block a user