From 04ba564c93dd7ac55f3d5f44666e2b5ced8ac6c4 Mon Sep 17 00:00:00 2001 From: Glenn Moloney Date: Tue, 27 Jun 2023 17:07:32 +1000 Subject: [PATCH] ports/esp32: Set ESPNow power management with ESPNow.config(pm=). Control the ESPNOW power management parameters with the new "pm" option to ESPNow.config(). Usage: e.config(pm=(75, 200)) sets the wake_window to 75ms and the wake_interval to 200ms, ie: turn on the radio for 7ms every 200ms. Signed-off-by: Glenn Moloney --- docs/library/espnow.rst | 20 ++++++++++++++++++++ ports/esp32/modespnow.c | 14 +++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/docs/library/espnow.rst b/docs/library/espnow.rst index f344983700..469488157f 100644 --- a/docs/library/espnow.rst +++ b/docs/library/espnow.rst @@ -170,6 +170,26 @@ Configuration `_. + *pm*: (ESP32 only) Set the ESPNOW wireless power saving parameters. + Usage: ``e.config(pm=(window, interval))``: every ``interval`` + milliseconds the radio will be turned on for ``window`` milliseconds to + listen for incoming messages (``interval`` should be a multiple of + 100ms). Incoming messages will be lost while the radio is off. Messages + may be sent at any time. By default, ESPNOW power saving is disabled and + the radio is turned on continuously. Examples:: + + e.config(pm=(75, 200)) # equivalent to WLAN.config(pm=WLAN.PM_PERFORMANCE) + e.config(pm=(75, 300)) # equivalent to WLAN.config(pm=WLAN.PM_POWERSAVE) + + If the device is also connected to a wifi Access Point, the wifi power + saving mode will be used instead + (see `WLAN.config(pm=XX)`). + + See `Config ESP-NOW Power-saving Parameter + `_. + .. data:: Returns: ``None`` or the value of the parameter being queried. diff --git a/ports/esp32/modespnow.c b/ports/esp32/modespnow.c index 08836c0ad7..179313b6ad 100644 --- a/ports/esp32/modespnow.c +++ b/ports/esp32/modespnow.c @@ -236,12 +236,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(espnow_active_obj, 1, 2, espnow_activ // timeout: Default read timeout (default=300,000 milliseconds) STATIC mp_obj_t espnow_config(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { esp_espnow_obj_t *self = _get_singleton(); - enum { ARG_get, ARG_rxbuf, ARG_timeout_ms, ARG_rate }; + enum { ARG_get, ARG_rxbuf, ARG_timeout_ms, ARG_rate, ARG_pm }; static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_timeout_ms, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MIN} }, { MP_QSTR_rate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + { MP_QSTR_pm, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, @@ -258,6 +259,17 @@ STATIC mp_obj_t espnow_config(size_t n_args, const mp_obj_t *pos_args, mp_map_t check_esp_err(esp_wifi_config_espnow_rate(ESP_IF_WIFI_STA, args[ARG_rate].u_int)); check_esp_err(esp_wifi_config_espnow_rate(ESP_IF_WIFI_AP, args[ARG_rate].u_int)); } + if (args[ARG_pm].u_obj != MP_OBJ_NULL) { + mp_obj_tuple_t *t = (mp_obj_tuple_t *)MP_OBJ_TO_PTR(args[ARG_pm].u_obj); + if (!mp_obj_is_type(t, &mp_type_tuple) || t->len < 1 || t->len > 2) { + mp_raise_TypeError(MP_ERROR_TEXT("pm should be set to tuple of length 2")); + } + check_esp_err(esp_now_set_wake_window(mp_obj_get_int(t->items[0]))); + if (t->len == 2) { + check_esp_err(esp_wifi_connectionless_module_set_wake_interval(mp_obj_get_int(t->items[1]))); + } + } + if (args[ARG_get].u_obj == MP_OBJ_NULL) { return mp_const_none; }