Программирование ARM ESP32: режимы пониженного энергопотребления Sat, July 13 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

ESP32: режимы пониженного энергопотребления Печать
Добавил(а) microsin   

ESP32 может находиться в двух режимах пониженного энергопотребления: Light-sleep и Deep-sleep.

Light-sleep. В этом режиме сна цифровые периферийные устройства, большая часть RAM и CPU, не получают тактирование, и их напряжение питания снижено. При выходе из Light-sleep блоки периферийных устройств, RAM и CPU возобновляют свою работу в том состоянии, в каком они находились в момент входа Light-sleep (никакие данные не теряются).

Deep-sleep. В этом режиме выключено почти все: CPU, большая часть RAM и все цифровые периферийные устройства, которые тактируются от APB_CLK. Только некоторые части чипа остаются под питанием:

Контроллер RTC [2]
Периферийные устройства RTC
Сопроцессор ULP [3]
Быстрая память RTC (RTC fast memory)
Медленная память RTC (RTC slow memory)

Существует несколько источников пробуждения (wakeup) для выходя из режимов Deep-sleep и Light-sleep. Эти источники также можно комбинировать, чтобы чип просыпался, когда поступил сигнал пробуждения от любого источника. Источники пробуждения можно разрешить вызовом API-функций esp_sleep_enable_X_wakeup, и запретить esp_sleep_disable_wakeup_source. В следующей секции более подробно описываются эти API-вызовы. Источники пробуждения могут быть сконфигурированы в любой момент перед входом в режим Light-sleep или Deep-sleep.

Дополнительно приложение может принудительно активировать определенные режимы выключения для периферийных устройств RTC и областей памяти RTC, используя esp_sleep_pd_config API.

После того, как источники пробуждения сконфигурированы, приложение может войти в sleep mode, используя API-функцию esp_light_sleep_start или esp_deep_sleep_start. В этот момент аппаратура будет сконфигурирована в соответствии с запрошенными источниками пробуждения, и контроллер RTC будет делать либо power down, либо power off для ядер CPU и цифровых периферийных устройств.

Если соединения Wi-Fi должны сохраняться, разрешите режим Wi-Fi Modem-sleep и функцию automatic Light-sleep (см. API-функции управления энергопотреблением [4]). Это позволит системе автоматически выйти из сна, когда сконфигурирован драйвер Wi-Fi, поддерживая тем самым соединение с точкой доступа.

[Wi-Fi/Bluetooth и режимы сна]

В режимах сна Deep-sleep и Light-sleep беспроводные устройства выключены (power down). Перед входом в режим Deep-sleep или Light-sleep, приложение должно запретить Wi-Fi и Bluetooth, используя для этого соответствующие вызовы API-функций (т. е. esp_bluedroid_disable, esp_bt_controller_disable, esp_wifi_stop). Соединения Wi-Fi и Bluetooth не будут поддерживаться в режимах Deep-sleep или Light-sleep, даже если эти функции не были вызваны.

[Источники пробуждения]

Timer. Контроллер RTC содержит встроенный таймер, который может использоваться для пробуждения чипа после предварительно определенного интервала времени. Время указывается с точностью до микросекунды, однако реальная разрешающая способность указания времени зависит от выбранного источника тактирования для RTC SLOW_CLK.

Более подробно про опции тактирования RTC см. ESP32 Technical Reference Manual -> ULP Coprocessor [PDF]. Также см. [3].

Периферийные устройства RTC или блоки памяти RTC не нужно включать во время сна и этого режима выхода из сна.

Для разрешения пробуждения с помощью таймера может использоваться функция esp_sleep_enable_timer_wakeup.

Touchpad. Модуль RTC IO содержит логику для срабатывания пробуждения, когда происходит касание к сенсору тачпада. Чтобы произошло пробуждение от прерывания сенсора тачпада, необходимо сконфигурировать прерывание тачпада перед входом в режим Deep-sleep или Light-sleep.

Ревизии 0 и 1 кристалла ESP32 поддерживают только этот режим пробуждения, когда периферийные устройства RTC не были включены принудительно (т. е. ESP_PD_DOMAIN_RTC_PERIPH должно быть установлено в ESP_PD_OPTION_AUTO).

Для разрешения этого источника пробуждения может использоваться функция esp_sleep_enable_touchpad_wakeup.

External Wakeup (ext0). Модуль RTC IO содержит логику для активации пробуждения от одной из ножек RTC GPIO, когда она установится в предварительно определенный логический уровень. RTC IO является частью домена питания периферийных устройств RTC, так что для периферийных устройств RTC будет сохраняться питание в режиме Deep-sleep, если был запрошен этот источник пробуждения.

В этом режиме модуль The RTC IO разрешен, так что также можно использовать внутренние резисторы подтяжки pullup или pulldown. Они должны быть сконфигурированы приложением с помощью функций rtc_gpio_pullup_en и rtc_gpio_pulldown_en перед вызовом esp_deep_sleep_start.

В ревизиях кристалла 0 и 1 ESP32 этот источник пробуждения несовместим с ULP и источниками пробуждения касания (touch wakeup sources).

Для разрешения пробуждения от ext0 может использоваться функция esp_sleep_enable_ext0_wakeup.

Предупреждение: после выхода из сна ножка IO, которая используется для пробуждения, будет сконфигурирована как RTC IO. Таким образом, перед использованием этой ножки как digital GPIO необходимо переконфигурировать её вызовом функции rtc_gpio_deinit.

External Wakeup (ext1). Контроллер RTC содержит логику для активации пробуждения с помощью нескольких ножек RTC GPIO. Для срабатывания пробуждения может использоваться одна из двух логических функций:

• Пробуждение, если любая из выбранных ножек находится в лог. 1 (ESP_EXT1_WAKEUP_ANY_HIGH).
• Пробуждение, если любая из выбранных ножек находится в лог. 0 (ESP_EXT1_WAKEUP_ALL_LOW).

Этот источник пробуждения реализован контроллером RTC. Таким образом, для этого режима пробуждения периферийные устройства RTC и блоки памяти RTC могут быть выключены. Однако, если периферийные устройства RTC выключены, то будут запрещены внутренние резисторы подтяжки pullup и pulldown. Для использования внутренних резисторов подтяжки запросите сохранение питания для домена периферийных устройств RTC во время сна, и перед входом в режим сна сконфигурируйте резисторы pullup/pulldown с помощью функций rtc_gpio_:

esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
gpio_pullup_dis(gpio_num);
gpio_pulldown_en(gpio_num);

Предупреждение: после выхода из сна ножка (ножки) IO, которая используется для пробуждения, будет сконфигурирована как RTC IO. Перед использованием этой ножки в качестве digital GPIO переконфигурируйте её с помощью функции rtc_gpio_deinit.

Для разрешения этого источника пробуждения может использоваться функция esp_sleep_enable_ext1_wakeup.

ULP Coprocessor Wakeup. Сопроцессор ULP может работать, когда чип находится в режиме сна, и поэтому может использоваться для опроса сенсоров, мониторинга значений ADC или сенсора касания, и выводить чип из сна, когда было определено определенное событие. Сопроцессор ULP является частью домена питания периферийных устройств RTC, и он запускает программу, сохраненную в медленной памяти RTC (RTC slow memory). Медленная память RTC будет получать питание во время сна, если запрошен этот режим пробуждения. Периферийные устройства RTC автоматически получат питание, перед тем, как сопроцессор ULP запустит эту программу; после прекращения работы этой программы периферийные устройства RTC снова автоматически выключатся.

Ревизии кристалла 0 и 1 of ESP32 будут поддерживать этот режим пробуждения только когда периферийные устройства RTC не были принудительно включены (т. е. ESP_PD_DOMAIN_RTC_PERIPH должно быть установлено в ESP_PD_OPTION_AUTO).

Для разрешения этого источника пробуждения может использоваться функция esp_sleep_enable_ulp_wakeup.

GPIO Wakeup (только для Light-sleep). В дополнение к вышеописанным источникам пробуждения EXT0 и EXT1 есть еще один метод пробуждения от внешних входов, доступный в режиме Light-sleep. С этим источником пробуждения каждая ножка может быть индивидуально сконфигурирована (с помощью функции gpio_wakeup_enable) для вывода чипа из сна по высокому или низкому уровню. В отличие от источников пробуждения EXT0 и EXT1, которые могут использовать ножки RTC IO, этот источник может использоваться на любой ножке IO (RTC или digital).

Для разрешения этого источника пробуждения может использоваться функция esp_sleep_enable_gpio_wakeup.

Предупреждение: перед входом в режим Light-sleep проверьте, принадлежит ли домену питания VDD_SDIO любая ножка GPIO, используемая для пробуждения. Если это так, то этот домен питания должен быть сконфигурирован так, чтобы он оставался включенным во время сна. Например, на плате ESP32-WROOM-32 ножки GPIO16 и GPIO17 связаны с доменом питания VDD_SDIO. Если они сконфигурированы так, чтобы оставаться в лог. 1, когда активен режим Light-sleep, то домен питания должен быть сконфигурирован оставаться включенным. Это можно сделать вызовом esp_sleep_pd_config:

esp_sleep_pd_config(ESP_PD_DOMAIN_VDDSDIO, ESP_PD_OPTION_ON);

UART Wakeup (только для Light-sleep). Когда ESP32 получает данные на входе UART от внешних устройств, часто необходимо разбудить чип, чтобы он мог обработать доступные данные. Периферийное устройство UART содержит функцию, которая позволяет вывести чип из режима Light-sleep, когда на ножке RX появилось определенное количество положительных перепадов. Это количество перепадов может быть установлено функцией uart_set_wakeup_threshold. Обратите внимание, что символ, который активирует пробуждение (и любые символы до него) не будут приняты UART после пробуждения (т. е. будут потеряны). Это значит, что внешнему устройству перед отправкой полезных данных обычно требуется отправить в ESP32 дополнительный символ, чтобы активировалось пробуждение.

Для разрешения этого источника пробуждения может использоваться функция esp_sleep_enable_uart_wakeup.

[Выключение периферийных устройств и блоков памяти RTC]

По умолчанию все функции esp_deep_sleep_start и esp_light_sleep_start выключат все домены питания RTC, которые не требуются для разрешенных источников пробуждения. Для переназначения этого поведения предоставлена функция esp_sleep_pd_config.

Примечание: в ревизии 0 кристалла ESP32, быстрая память RTC в режиме Deep-sleep будет всегда удерживаться разрешенной, чтобы после сброса могла работать заглушка Deep-sleep. Это может быть переопределено, если приложению не требуется чистый сброс после Deep-sleep.

Если некоторые переменные в программе помещены в медленную память RTC (например, с помощью атрибута RTC_DATA_ATTR), то по умолчанию на медленной памяти RTC будет сохранено питание. Это при необходимости может быть переопределено с помощью функции esp_sleep_pd_config.

Вход в Light-sleep. После того, как источники пробуждения были сконфигурированы, для входа в режим Light-sleep может использоваться функция esp_light_sleep_start. Также есть возможность входа в Light-sleep, когда не было сконфигурировано ни одного источника пробуждения. В этом случае чип будет бесконечно находиться в режиме Light-sleep, пока не придет сигнал внешнего сброса.

Вход в Deep-sleep. После того, как источники пробуждения были сконфигурированы, для входа в режим Deep-sleep может использоваться функция esp_deep_sleep_start. Также есть возможность в входа Deep-sleep, когда не было сконфигурировано ни одного источника пробуждения. В этом случае чип будет бесконечно находиться в режиме Deep-sleep, пока не придет сигнал внешнего сброса.

[Конфигурирование IO]

Некоторые ножки ввода/вывода ESP32 (IO) снабжены внутренними резисторами подтяжки pullup или pulldown, которые по умолчанию разрешены. Если внешняя схема управляет такой ножкой в режиме Deep-sleep, то может увеличиться ток потребления, который будет протекать через эти резисторы.

Чтобы изолировать (переключить в третье состояние) ножку IO и тем самым исключить лишний ток потребления, вызовите функцию rtc_gpio_isolate.

Например, в модуле ESP32-WROVER ножка GPIO12 подтягивается к верхнему уровню снаружи (pullup), и на ней присутствует внутренняя подтяжка к нижнему уровню (internal pulldown) чипа ESP32. Это значит, что в режиме Deep-sleep будет протекать некоторый лишний ток через внешний и внутренний резисторы, что увеличит ток потребления в режиме Deep-sleep, так что он будет больше минимально возможного.

Чтобы устранить этот дополнительный ток, добавьте следующий код перед esp_deep_sleep_start:

rtc_gpio_isolate(GPIO_NUM_12);

[Обработка вывода UART]

Перед входом в режим сна esp_deep_sleep_start сбросит (flush) содержимое всех стеков UART FIFO.

Когда происходит вход в Light-sleep с помощью esp_light_sleep_start, стеки UART FIFO не будут сбрасываться. Вместо этого вывод UART будет приостановлен, и оставшиеся в FIFO символы будут отправлены после выхода из режима Light-sleep.

[Проверка, от чего произошло пробуждение]

Чтобы проверить, какой из источников пробуждения вывел устройство из режима сна, может использоваться функция esp_sleep_get_wakeup_cause.

Для тачпада есть возможность идентифицировать, какая ножка касания (touch pin) привела к пробуждению, путем вызова функции esp_sleep_get_touchpad_wakeup_status.

Для источника пробуждения ext1 можно идентифицировать, какая ножка касания привела к пробуждению, с помощью функции esp_sleep_get_ext1_wakeup_status.

/**
 * @brief Возможные причины пробуждения
 */
typedef enum
{
   ESP_SLEEP_WAKEUP_UNDEFINED,    //!< В случае deep sleep сброс не был вызван выходом из deep sleep.
   ESP_SLEEP_WAKEUP_ALL,          //!< Не случай пробуждения, используется для запрета всех источников
                                  //   пробуждения вызовом функции esp_sleep_disable_wakeup_source.
   ESP_SLEEP_WAKEUP_EXT0,         //!< Пробуждение было вызвано внешним сигналом, используется RTC_IO.
   ESP_SLEEP_WAKEUP_EXT1,         //!< Пробуждение было вызвано внешним сигналом, используется RTC_CNTL.
   ESP_SLEEP_WAKEUP_TIMER,        //!< Пробуждение от таймера.
   ESP_SLEEP_WAKEUP_TOUCHPAD,     //!< Пробуждение от тачпада.
   ESP_SLEEP_WAKEUP_ULP,          //!< Пробуждение от программы ULP(*).
   ESP_SLEEP_WAKEUP_GPIO,         //!< Пробуждение от GPIO (работает только для light sleep).
   ESP_SLEEP_WAKEUP_UART,         //!< Пробуждение от UART (работает только для light sleep).
   ESP_SLEEP_WAKEUP_WIFI,         //!< Пробуждение от WIFI (работает только для light sleep).
   ESP_SLEEP_WAKEUP_COCPU,             //!< Пробуждение от прерывания COCPU.
   ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG,   //!< Пробуждение от COCPU crash.
   ESP_SLEEP_WAKEUP_BT,           //!< Пробуждение от BT (работает только для light sleep).
} esp_sleep_source_t;
 
/* Этот тип определен для сохранения совместимости */
typedef esp_sleep_source_t esp_sleep_wakeup_cause_t;

Примечание (*): блоком ULP оборудованы не все модели процессоров ESP32, подробнее см. [3].

[Запрет источника пробуждения]

Сконфигурированные ранее источники пробуждения могут быть запрещены позже с помощь API-функции esp_sleep_disable_wakeup_source. Эта функция деактивирует триггер пробуждения для указанного источника. Дополнительно можно запретить все триггеры, если передать в аргументе ESP_SLEEP_WAKEUP_ALL.

[Примеры приложений]

protocols/sntp: реализация базового функционала Deep-sleep, где модуль ESP периодически выводится из сна для получения времени с сервера NTP.

wifi/power_save: реализация примера засыпания модема.

system/deep_sleep: использование различных триггеров для пробуждения из Deep-sleep и программирование сопроцессора ULP.

[Справочник по API-функциям Sleep Modes]

Заголовочный файл: components/esp_hw_support/include/esp_sleep.h.

Функция Описание
esp_sleep_disable_wakeup_source Запрещает источник пробуждения. Эта функция используется для деактивации триггера пробуждения для источника, переданного в аргументе функции. Подробную информацию см. в docs/sleep-modes.rst.
esp_sleep_enable_ulp_wakeup Разрешает пробуждение от сопроцессора ULP.
esp_sleep_enable_timer_wakeup Разрешает пробуждение от таймера.
esp_sleep_enable_touchpad_wakeup Разрешает пробуждение от датчика касания (touch sensor).
esp_sleep_get_touchpad_wakeup_status Вернет ножку тачпада, которая вызвала пробуждение. Если пробуждение было вызвано другим источником, то эта функция вернет TOUCH_PAD_MAX.
esp_sleep_enable_ext0_wakeup Разрешит пробуждение от ножки RTC. Эта функция использует возможность пробуждения от внешнего сигнала периферийного устройства RTC_IO. Это будет работать только когда во время сна сохранено питание периферийного устройства RTC. Можно мониторить состояние любого вывода, который относится к RTC IO. Как только было обнаружен переход в состояние, указанное в аргументе функции, чип выйдет из режима сна.
esp_sleep_enable_ext1_wakeup Разрешает пробуждение от нескольких выводов. Эта функция использует возможность пробуждения от внешнего сигнала контроллера RTC. Она будет работать даже если периферийное устройство RTC выключено во время сна. Можно мониторить любое количество выводов, которые находятся в RTC IO. Как только любой из выбранных выводов перейдет в состояние, указанное в аргументе, чип выйдет из сна.
esp_sleep_enable_gpio_wakeup Разрешает пробуждение из Light-Sleep с помощью GPIO. Каждая ножка GPIO поддерживает активацию пробуждения, которое может срабатывать либо от низкого, либо от высокого уровня. В отличие от источников пробуждения EXT0 и EXT1, этот метод может использовать для всех типов ножек IO: RTC IO и digital IO. Пробуждение возможно только из Light-Sleep. Для разрешения пробуждения сначала вызывается gpio_wakeup_enable, где указывается номер ножки GPIO и уровень пробуждения для каждой ножки GPIO. Затем вызывается функция esp_sleep_enable_gpio_wakeup для разрешения работы пробуждения.
esp_sleep_enable_uart_wakeup Разрешает побуждение из Light-Sleep с помощью UART. Для конфигурирования порога пробуждения UART используется функция uart_set_wakeup_threshold. Выход из Light-Sleep требует некоторого времени, так что не каждый символ, отправленный в UART, может быть принят приложением.
esp_sleep_enable_wifi_wakeup Разрешает пробуждение от WiFi MAC.
esp_sleep_disable_wifi_wakeup Запрещает пробуждение от WiFi MAC.
esp_sleep_get_ext1_wakeup_status Получает битовую маску ножек GPIO, которые вызвали пробуждение (ext1). Если пробуждение произошло от другого источника, то эта функция вернет 0.
esp_sleep_pd_config Установит режим выключения (power down mode) для домена питания RTC в режиме сна. Если с помощью этого API-вызова ничего не было установлено, то по умолчанию у всех доменов питания режим ESP_PD_OPTION_AUTO.
esp_deep_sleep_start Вход в Deep-Sleep с опциями пробуждения, которые были предварительно сконфигурированы.
esp_light_sleep_start Вход в Light-Sleep с опциями пробуждения, которые были предварительно сконфигурированы.
esp_deep_sleep Вход в режим Deep-Sleep. Устройство автоматически выйдет из режима глубокого сна после истечения интервала времени, указанного в параметре. После пробуждения устройство вызовет заглушку глубокого сна (deep sleep wake stub), и затем перейдет к загрузке приложения. Вызов esp_deep_sleep эквивалентен вызову esp_deep_sleep_enable_timer_wakeup, за которым следует вызов esp_deep_sleep_start. Функция esp_deep_sleep не выключит корректно WiFi, BT и соединения высокоуровневого протокола. Убедитесь, что предварительно были вызваны соответствующие функции стека WiFi и BT, чтобы были закрыты любые соединения и отменена инициализация периферийных устройств (это включает esp_bluedroid_disable, esp_bt_controller_disable, esp_wifi_stop). Из функции esp_deep_sleep не будет выполнен возврат.
esp_sleep_get_wakeup_cause Выдаст информацию по источнику, от которого произошло пробуждение.
esp_wake_deep_sleep Заглушка по умолчанию для запуска при выходе из режима Deep-Sleep. Позволяет запустить некоторый код немедленно после выхода из сна, до момента запуска программного загрузчика (загрузчик второго уровня) или приложения ESP-IDF. Эта функция линкуется в режиме weak, т. е. она может быть переопределена разработчиком. Подробную информацию см. в docs/deep-sleep-stub.rst.
esp_set_deep_sleep_wake_stub Установит новую заглушку во время выполнения кода (runtime), чтобы она запустилась при выходе устройства из Deep-Sleep. Если разработчиком переопределена функция esp_wake_deep_sleep(), то не нужно вызывать функцию esp_set_deep_sleep_wake_stub. Однако все-таки её вызвать можно, чтобы установить другую заглушку. Любая функция, которая используется как заглушка выхода из глубокого сна (deep sleep stub), должна быть помечена атрибутом RTC_IRAM_ATTR, и должна соблюдать те же правила, что и esp_wake_deep_sleep().
esp_get_deep_sleep_wake_stub Получает текущее пробуждение от deep sleep stub.
esp_default_wake_deep_sleep Заглушка по умолчанию для esp_wake_deep_sleep(), предоставленная средой разработки ESP-IDF. Подробную информацию см. в docs/deep-sleep-stub.rst.
esp_deep_sleep_disable_rom_logging Запретит вывод в лог из кода ROM после Deep-Sleep, использует младший бит (LSB) из RTC_STORE4.
esp_sleep_config_gpio_isolate Конфигурирует третье состояние всех ножек GPIO для режима сна.
esp_sleep_enable_gpio_switch Разрешает или запрещает состояние переключения ножек GPIO между сном и пробуждением.

Примечание: полное описание макросов, типов данных, API-функций и их параметров см. в документации [1].

[Словарик]

BT BlueTooth.

RTC Real Time Clock, часы реального времени.

ULP Ultra Low Power, режим с очень низким потреблением энергии.

[Ссылки]

1. ESP32 Sleep Modes site:docs.espressif.com.
2. ESP32 System Time site:docs.espressif.com.
3. ESP32: программирование сопроцессора ULP.
4. ESP32: управление энергопотреблением.
5ESP32-C3: режимы пониженного энергопотребления.

 

Добавить комментарий


Защитный код
Обновить

Top of Page