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

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

Перевод: Максим Кузьмин (Cubewriter) Контакты:</br>* Skype: cubewriter</br>* E-mail: cubewriter@gmail.com</br>* Максим Кузьмин на freelance.ru
Проверка/Оформление/Редактирование: Мякишев Е.А.


Pixel Art Mini Meow Animated.gif Черновик


Режим глубокого сна: пробуждение с помощью нескольких 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)


Pixel Art Mini Meow Animated.gif Важное примечание: На момент написания этого руководства в документации о режиме глубокого сна была опечатка. Там указана функция 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»
  • Переведите это число в шестнадцатеричный формат. Это можно сделать при помощи этого конвертера(или воспользуйтесь любым ПО, которое может конвертировать числа из одной системы счисления в другую):
Esp32 deepsleep ext1 1.PNG.png
  • Скопируйте шестнадцатеричный результат в переменную «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 deepsleep ext1 monitor 1.PNG.png

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

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

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

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

Схема

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


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

Esp32 deepsleep ext1 exp 1.PNG.png

Код

  1 /*
  2 Режим глубокого сна и внешнее пробуждение
  3 =====================================
  4 Этот скетч-пример демонстрирует, как выводить ESP32
  5 из режима глубокого сна при помощи внешнего триггера,
  6 а также, как сохранять данные в RTC-память,
  7 чтобы потом использовать их между загрузками.
  8 
  9 Этот код распространяется по лицензии всеобщего достояния.
 10 =====================================
 11 
 12 ПРИМЕЧАНИЕ
 13 ======
 14 В качестве инициатора внешнего пробуждения
 15 могут использоваться только контакты типа RTC_GPIO.
 16 Вот они: 0, 2, 4, 12-15, 25-27, 32-39.
 17 
 18 Автор:
 19 Пранав Черукупалли <cherukupallip@gmail.com>
 20 */
 21 
 22 #define BUTTON_PIN_BITMASK 0x8004 // битовая маска 
 23                                   // для контактов GPIO2 и GPIO15
 24 
 25 RTC_DATA_ATTR int bootCount = 0;
 26 
 27 /*
 28 Это функция для печати в мониторе порта причины пробуждения ESP32
 29 */
 30 void print_wakeup_reason(){
 31   esp_sleep_wakeup_cause_t wakeup_reason;
 32 
 33   wakeup_reason = esp_sleep_get_wakeup_cause();
 34 
 35   switch(wakeup_reason)
 36   {
 37     case 1  : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
 38                          //  "Пробуждение от внешнего сигнала при помощи RTC_IO"
 39     case 2  : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
 40                          //  "Пробуждение от внешнего сигнала при помощи RTC_CNTL"
 41     case 3  : Serial.println("Wakeup caused by timer"); break;
 42                          //  "Пробуждение по таймеру"
 43     case 4  : Serial.println("Wakeup caused by touchpad"); break;
 44                          //  "Пробуждение от сенсорных контактов"
 45     case 5  : Serial.println("Wakeup caused by ULP program"); break;
 46                          //  "Пробуждение от ULP-программы"
 47     default : Serial.println("Wakeup was not caused by deep sleep"); break;
 48                          //  "Пробуждение не связано с режимом глубокого сна"
 49   }
 50 }
 51 
 52 /*
 53 Это функция для печати в мониторе порта номера GPIO-контакта,
 54 ставшего триггером вывода ESP32 из режима сна.  
 55 */
 56 void print_GPIO_wake_up(){
 57   int GPIO_reason = esp_sleep_get_ext1_wakeup_status();
 58   Serial.print("GPIO that triggered the wake up: GPIO ");
 59            //  "GPIO-контакт, ставший триггером пробуждения: GPIO"
 60   Serial.println((log(GPIO_reason))/log(2), 0);
 61 }
 62   
 63 void setup(){
 64   Serial.begin(115200);
 65   delay(1000); // даем время на установку последовательного соединения 
 66 
 67   // увеличиваем значение в счетчике загрузок 
 68   // и печатаем это значение с каждой загрузкой ESP32:
 69   ++bootCount;
 70   Serial.println("Boot number: " + String(bootCount));
 71              //  "Номер загрузки: "
 72 
 73   // печатаем причину пробуждения ESP32:
 74   print_wakeup_reason();
 75 
 76   // печатаем GPIO-контакт, ставший триггером пробуждения:
 77   print_GPIO_wake_up();
 78 
 79   /*
 80   Во-первых, задаем инициатора пробуждения – внешний триггер.
 81   Внешний триггер может быть двух типов: ext0 и ext1.
 82 
 83   Пробуждение типа ext0 использует один контакт RTC_GPIO,
 84   поэтому ему нужна включенная RTC-периферия.
 85   Пробуждение типа ext1 использует RTC-контроллер,
 86   поэтому ему включенная периферия не нужна.
 87 
 88   Кроме того, чтобы RTC-периферия оставалась включенной,
 89   понадобится использовать встроенные подтягивающие
 90   и стягивающие резисторы.
 91   */
 92 
 93   // если вы используете метод ext1, вам понадобится вот эта строчка: 
 94   esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);
 95 
 96   // переходим в режим сна:
 97   Serial.println("Going to sleep now");
 98              //  "Переходим в режим сна"
 99   delay(1000);
100   esp_deep_sleep_start();
101   Serial.println("This will never be printed");
102              //  "Это сообщение никогда не будет напечатано"
103 }
104 
105 void loop(){
106   // до этого фрагмента скетч никогда не доберется
107 }

См.также

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