Хочешь создать умный дом, но не знаешь как? Присмотрись к Node-REDCutehamster.gif! Так же не забывай поддержать наш справочникCutehamster.gif.

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

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

Перевод: Максим Кузьмин (Cubewriter)
Перевел 3377 статей для сайта.

Контакты:

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


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. }

См.также

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