ESP32:Примеры/Режим глубокого сна: пробуждение с помощью нескольких GPIO-контактов

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Режим глубокого сна: пробуждение с помощью нескольких GPIO-контактов

В этом примере мы разберем проект, где ESP32 можно будет разбудить с помощью разных кнопок, а код будет определять, с помощью какой кнопки было инициировано пробуждение. В данном случае контактами для пробуждения будут служить GPIO2 и GPIO15.

Справочная информация

Внешнее пробуждение типа «ext0»

Во-первых, ESP32 можно разбудить при помощи одного контакта RTC_GPIO. Чтобы использовать этот метод пробуждения, в коде нужно воспользоваться следующей функцией:

esp_sleep_enable_ext0_wakeup(GPIO_NUM_X, level)

Первый параметр в этой функции – это «GPIO_NUM_X», то есть контакт, которым мы хотим воспользоваться (здесь «X» – это GPIO-номер этого контакта).

Второй параметр – это значение, которое станет триггером для пробуждения («0» или «1»).

Примечание

Для этого типа пробуждения необходимо использовать только контакты RTC_GPIO.

Внешнее пробуждение типа «ext1»

Во-вторых, ESP32 можно пробудить при помощи нескольких контактов RTC_GPIO. В этом случае предусмотрены две возможности:

  • Пробуждение, если какой-либо из заданных контактов получил значение «HIGH»
  • Пробуждение, если все заданные контакты получили значение «LOW»

Этот тип пробуждения выполняется с помощью RTC-контроллера. Следовательно, RTC-периферию и RTC-память при использовании этого режима можно отключить.

Чтобы воспользоваться этим типом пробуждения, в коде нужно вписать следующую функцию:

esp_sleep_enable_ext1_wakeup(bitmask, mode)
Внимание!

На момент написания этого руководства в документации о режиме глубокого сна была опечатка. Там указана функция esp_deep_sleep_enable_ext1_wakeup(), но в действительности работает та, что указана выше – esp_sleep_enable_ext1_wakeup()

В этой функции два параметра:

  • «bitmask», т.е. битовая маска для номеров GPIO-контактов, являющихся инициаторами пробуждения
  • «mode», т.е. тип ext1-пробуждения ESP32:
    • «ESP_EXT1_WAKEUP_ALL_LOW» – пробуждение, если у всех контактов «LOW»
    • «ESP_EXT1_WAKEUP_ANY_HIGH» – пробуждение, если у любого контакта «HIGH»
Примечание

Для этого типа пробуждения необходимо использовать только контакты RTC_GPIO.

Общий принцип создания битовой маски для GPIO-контактов

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

  1. Возведите «2» в степень, соответствующую номеру контакта. Сохраните результат в десятичном формате;
  2. Перейдите сюда и переведите это десятичное число в шестнадцатеричный формат(или воспользуйтесь любым ПО, которое может конвертировать числа из одной системы счисления в другую);
  3. Вставьте результат в переменную «BUTTON_PIN_BITMASK»;

Битовая маска для одного GPIO-контакта

Сначала давайте разберем, как сделать битовую маску для одного контакта. Допустим в скетче кнопка подключена к контакту GPIO33. Чтобы сделать маску для этого контакта, проделайте следующее:

  • Возведите «2» в степень «33» (2^33). У вас должно получиться «8589934592»
  • Переведите это число в шестнадцатеричный формат. Это можно сделать при помощи этого конвертера(или воспользуйтесь любым ПО, которое может конвертировать числа из одной системы счисления в другую):
  • Скопируйте шестнадцатеричный результат в переменную «BUTTON_PIN_BITMASK». У вас должно получиться вот так:
#define BUTTON_PIN_BITMASK 0x200000000 // это 2 в 33 степени
                                       // в шестнадцатеричном 
                                       // выражении

Битовая маска для нескольких GPIO-контактов

Если вы хотите использовать в качестве инициаторов пробуждения контакты GPIO2 и GPIO15, вам нужно сделать следующее:

  1. Возведите «2» в степень «2» (2^2), затем «2» в степень «15» (2^15), а потом сложите два этих значения друг с другом. У вас должно получиться «32772»
  2. Переведите это число в шестнадцатеричный формат. У вас должно получиться «8004»
  3. Вставьте результат в переменную «BUTTON_PIN_BITMASK», чтобы получилось так:
#define BUTTON_PIN_BITMASK 0x8004

Определение GPIO-контакта, используемого для пробуждения

Если вы используете несколько контактов для пробуждения ESP32, то в коде также нужен фрагмент для определения того, какой именно контакт вызвал пробуждение. Для этого используется следующая функция:

esp_sleep_get_ext1_wakeup_status();

Эта функция возвращает число, которое получится если возвести «2» в степень, равную номеру GPIO-контакта (2^GPIO), вызвавшего пробуждение. Следовательно, чтобы рассчитать номер контакта, ставшего причиной пробуждения, нужно проделать следующие расчеты:

GPIO = log(GPIO_reason)/log(2);

Проверка скетча

Подключив кнопки к контактам GPIO2 и GPIO15, а также убедившись, что в IDE Arduino выбраны правильные плата и COM-порт, загрузите на ESP32 код выше.

Итак, ESP32 уже должна быть в режиме глубокого сна. Вы можете разбудить ее, нажав на одну из двух подключенных к ней кнопок.

Откройте монитор порта на скорости 115200 бод. Понажимайте на кнопки, чтобы разбудить ESP32.

В мониторе порта должно появиться примерно следующее:

Итак, в этом примере мы научились выводить ESP32 из режима глубокого сна при помощи внешнего пробуждения. Это значит, что вы теперь знаете, как будить ESP32 с помощью изменения состояния на каком-либо GPIO-контакте.

Если вкратце, мы научились следующему:

  • Для внешнего пробуждения можно использовать только контакты типа RTC_GPIO;
  • Внешнее пробуждение бывает двух типов: ext0 и ext1;
  • Метод ext0 позволяет будить ESP32 с помощью одного GPIO-контакта;
  • Метод ext1 позволяет будить ESP32 с помощью нескольких GPIO-контактов;

Необходимое оборудование

Схема

Примечание

На данной схеме используется плата ESP32S-HiLetgo, если вы используете другую, сверьтесь с вашей распиновкой.

Кнопки подключены к GPIO2 и GPIO15.

Код

/*
Режим глубокого сна и внешнее пробуждение
=====================================
Этот скетч-пример демонстрирует, как выводить ESP32
из режима глубокого сна при помощи внешнего триггера,
а также, как сохранять данные в RTC-память,
чтобы потом использовать их между загрузками.

Этот код распространяется по лицензии всеобщего достояния.
=====================================

ПРИМЕЧАНИЕ
======
В качестве инициатора внешнего пробуждения
могут использоваться только контакты типа RTC_GPIO.
Вот они: 0, 2, 4, 12-15, 25-27, 32-39.

Автор:
Пранав Черукупалли <cherukupallip@gmail.com>
*/

#define BUTTON_PIN_BITMASK 0x8004 // битовая маска 
                                  // для контактов GPIO2 и GPIO15

RTC_DATA_ATTR int bootCount = 0;

/*
Это функция для печати в мониторе порта причины пробуждения ESP32
*/
void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch(wakeup_reason)
  {
    case 1  : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
                         //  "Пробуждение от внешнего сигнала при помощи RTC_IO"
    case 2  : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
                         //  "Пробуждение от внешнего сигнала при помощи RTC_CNTL"
    case 3  : Serial.println("Wakeup caused by timer"); break;
                         //  "Пробуждение по таймеру"
    case 4  : Serial.println("Wakeup caused by touchpad"); break;
                         //  "Пробуждение от сенсорных контактов"
    case 5  : Serial.println("Wakeup caused by ULP program"); break;
                         //  "Пробуждение от ULP-программы"
    default : Serial.println("Wakeup was not caused by deep sleep"); break;
                         //  "Пробуждение не связано с режимом глубокого сна"
  }
}

/*
Это функция для печати в мониторе порта номера GPIO-контакта,
ставшего триггером вывода ESP32 из режима сна.  
*/
void print_GPIO_wake_up(){
  int GPIO_reason = esp_sleep_get_ext1_wakeup_status();
  Serial.print("GPIO that triggered the wake up: GPIO ");
           //  "GPIO-контакт, ставший триггером пробуждения: GPIO"
  Serial.println((log(GPIO_reason))/log(2), 0);
}
  
void setup(){
  Serial.begin(115200);
  delay(1000); // даем время на установку последовательного соединения 

  // увеличиваем значение в счетчике загрузок 
  // и печатаем это значение с каждой загрузкой ESP32:
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));
             //  "Номер загрузки: "

  // печатаем причину пробуждения ESP32:
  print_wakeup_reason();

  // печатаем GPIO-контакт, ставший триггером пробуждения:
  print_GPIO_wake_up();

  /*
  Во-первых, задаем инициатора пробуждения – внешний триггер.
  Внешний триггер может быть двух типов: ext0 и ext1.

  Пробуждение типа ext0 использует один контакт RTC_GPIO,
  поэтому ему нужна включенная RTC-периферия.
  Пробуждение типа ext1 использует RTC-контроллер,
  поэтому ему включенная периферия не нужна.

  Кроме того, чтобы RTC-периферия оставалась включенной,
  понадобится использовать встроенные подтягивающие
  и стягивающие резисторы.
  */

  // если вы используете метод ext1, вам понадобится вот эта строчка: 
  esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);

  // переходим в режим сна:
  Serial.println("Going to sleep now");
             //  "Переходим в режим сна"
  delay(1000);
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
             //  "Это сообщение никогда не будет напечатано"
}

void loop(){
  // до этого фрагмента скетч никогда не доберется
}

См.также

Внешние ссылки