ESP32 Derin Uyku Kullanımı ve Uyandırma Kaynakları

ESP32 derin uyku modu ile güç kısmında yüksek bir tasarruf sağlayabilir, projelerinizin çalışma ömrünü arttırabilirsiniz. Bu yazı, Arduino IDE ile ESP32 Derin Uyku modu için eksiksiz bir kılavuzdur. Size ESP32’yi nasıl derin uyku moduna geçireceğinizi göstereceğiz ve onu uyandırmak için farklı modlara göz atacağız: zamanlayıcıyla uyandırma, dokunarak uyandırma ve harici uyandırma. Bu kılavuz, kod, kod açıklaması ve şemalarla ilgili pratik örnekler sunar.

ESP32 Derin Uyku Kullanımı ve Uyandırma Kaynakları esp32 derin uyku,esp32 deep sleep

Bu yazı 4 farklı bölüme ayrılmıştır:

  • Derin Uyku Moduna Giriş
  • Zamanlayıcı ile Uyandırma
  • Uyandırmak için Dokunun
  • Harici Uyandırma

Derin Uyku Moduna Giriş

ESP32, farklı güç modları arasında geçiş yapabilir:

  • Aktif mod
  • Modem Uyku modu
  • Hafif(Light) Uyku modu
  • Derin(Deep) Uyku modu
  • Hazırda Bekletme(Hibernation) modu

Aşağıdaki tablodaki beş farklı modu ESP32 Espressif veri sayfasından karşılaştırabilirsiniz.

ESP32 Derin Uyku Kullanımı ve Uyandırma Kaynakları esp32 derin uyku,esp32 deep sleep

ESP32 Espressif veri sayfası, farklı güç modlarının güç tüketimini karşılaştıran bir tablo da sağlar.

ESP32 Derin Uyku Kullanımı ve Uyandırma Kaynakları esp32 derin uyku,esp32 deep sleep

Ayrıca aktif modda güç tüketimini karşılaştırmak için Tablo 10:

ESP32 Derin Uyku Kullanımı ve Uyandırma Kaynakları esp32 derin uyku,esp32 deep sleep

Neden Derin Uyku Modu?

ESP32’nizin pillerle aktif modda çalışması ideal değildir, çünkü pillerden gelen güç çok çabuk bitecektir.

ESP32’nizi derin uyku moduna alırsanız, güç tüketimini azaltacak ve pilleriniz daha uzun süre dayanacaktır.

ESP32’nizin derin uyku modunda olması, çalışırken daha fazla güç tüketen, ancak ilginç bir şey olduğunda işlemciyi uyandırmaya yetecek kadar etkinlik bırakan etkinliklerle kesintiye uğramak anlamına gelir.

Derin uyku modunda ne CPU ne de Wi-Fi etkinlikleri gerçekleşir, ancak Ultra Düşük Güç (ULP) yardımcı işlemcisi hala açık olabilir.

ESP32 derin uyku modundayken, RTC belleği de açık kalır, böylece ULP yardımcı işlemcisi için bir program yazabilir ve çevresel cihazlara, dahili zamanlayıcılara ve dahili sensörlere erişmek için bunu RTC belleğinde saklayabiliriz.

Bu çalışma modu, minimum güç tüketimini korurken harici bir olay, zamanlayıcı veya her ikisi ile ana CPU’yu uyandırmanız gerektiğinde kullanışlıdır.

RTC_GPIO Pinleri

Derin uyku sırasında, ESP32 pinlerinden bazıları ULP yardımcı işlemcisi tarafından, yani RTC_GPIO pinleri ve Touch Pinleri tarafından kullanılabilir. ESP32 veri sayfası, RTC_GPIO pinlerini tanımlayan bir tablo sağlar. Bu tabloyu burada, 7. sayfada bulabilirsiniz.

Bu tabloyu referans olarak kullanabilir veya farklı RTC_GPIO pinlerini bulmak için aşağıdaki pinout’a bakabilirsiniz. RTC_GPIO pinleri turuncu bir dikdörtgen kutu ile vurgulanmıştır.

ESP32 Derin Uyku Kullanımı ve Uyandırma Kaynakları esp32 derin uyku,esp32 deep sleep

Önerilen yazı: ESP32 Pin Referansları, Hangi Pini Kullanmalısınız?

Uyandırma Kaynakları

ESP32’yi derin uyku moduna geçirdikten sonra, onu uyandırmanın birkaç yolu vardır:

  • Zamanlayıcıyı kullanarak ESP32’nizi önceden tanımlanmış zaman dilimlerini kullanarak uyandırabilirsiniz;
  • Dokunmatik pinleri kullanabilirsiniz;
  • İki harici uyandırma olasılığını kullanabilirsiniz: bir harici uyandırma veya birkaç farklı harici uyandırma kullanabilirsiniz;
  • ULP yardımcı işlemcisini uyandırmak için kullanabilirsiniz – bu olay bu yazıda ele alınmayacaktır.

Derin Uyku Kodu Yazmak

ESP32’nizi derin uyku moduna geçirmek üzere bir kod yazmak ve ardından onu uyandırmak için şunları aklınızda bulundurmanız gerekir:

  • İlk olarak, uyandırma kaynaklarını yapılandırmanız gerekir. Bu, ESP32’yi neyin uyandıracağını yapılandırmak anlamına gelir. Bir uyandırma kaynağı kullanabilir veya birden fazla uyandırma kaynağını birleştirebilirsiniz.
  • Derin uyku sırasında hangi çevre birimlerinin kapatılacağına veya devam ettirileceğine karar verebilirsiniz. Ancak, varsayılan olarak ESP32, tanımladığınız uyandırma kaynağı ile ihtiyaç duyulmayan çevre birimlerini otomatik olarak kapatır.
  • Son olarak, ESP32’nizi derin uyku moduna geçirmek için esp_deep_sleep_start() işlevini kullanırsınız.

ESP32 RTC denetleyicisi, önceden tanımlanmış bir süre sonra ESP32’yi uyandırmak için kullanabileceğiniz yerleşik bir zamanlayıcıya sahiptir.

Zamanlayıcı ile Uyandırmak

ESP32’nin önceden tanımlanmış bir süre sonra uyanmasını sağlamak çok basittir. Arduino IDE’de, aşağıdaki fonksiyonda uyku süresini mikrosaniye cinsinden belirtmeniz yeterlidir:

esp_sleep_enable_timer_wakeup(time_in_us)

Arduino Kodu

Bu kütüphaneden bir örnek kullanarak nasıl çalıştığını görelim. Arduino IDE’nizi açın ve Dosya > Örnekler > ESP32 > Deep Sleep‘e gidin ve TimerWakeUp örneğini açın.

#define uS_TO_S_FACTOR 1000000  /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP  5        /* Time ESP32 will go to sleep (in seconds) */

RTC_DATA_ATTR int bootCount = 0;

/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch(wakeup_reason)
  {
    case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}

void setup(){
  Serial.begin(115200);
  delay(1000); //Take some time to open up the Serial Monitor

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  //Print the wakeup reason for ESP32
  print_wakeup_reason();

  /*
  First we configure the wake up source
  We set our ESP32 to wake up every 5 seconds
  */
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
  " Seconds");


  Serial.println("Going to sleep now");
  delay(1000);
  Serial.flush(); 
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

void loop(){
  //This is not going to be called
}

Bu koda bir göz atalım. İlk yorum, derin uyku sırasında zamanlayıcı uyandırma ile neyin kapatıldığını açıklar.

  • Bu modda CPU’lar, RAM’in çoğu,
  • Saatli tüm dijital çevre birimleri
  • APB_CLK’ten gelenler kapatılır
  • RTC denetleyicisi, RTC çevre birimleri ve RTC bellekleri açıktır

Zamanlayıcı uyandırma özelliğini kullandığınızda, çalıştırılacak parçalar RTC denetleyicisi, RTC çevre birimleri ve RTC bellekleridir.

Uyku Zamanını Tanımlamak

Bu ilk iki kod satırı, ESP32’nin uykuda kalacağı süreyi tanımlar.

#define uS_TO_S_FACTOR 1000000 /* Conversion factor for micro seconds to seconds */ 
#define TIME_TO_SLEEP 5 /* Time ESP32 will go to sleep (in seconds) */

Bu örnek, TIME_TO_SLEEP değişkeninde uyku süresini saniye olarak ayarlayabilmeniz için mikrosaniyeden saniyeye bir dönüştürme faktörü kullanır. Bu durumda örnek, ESP32’yi 5 saniyeliğine derin uyku moduna geçirecektir.

Verileri RTC Hafızasına Kaydet

ESP32 ile verileri RTC hafızalarına kaydedebilirsiniz. ESP32’nin RTC kısmında RTC hızlı bellek adı verilen 8kB SRAM bulunur. Buraya kaydedilen veriler derin uyku sırasında silinmez. Ancak, sıfırlama düğmesine (ESP32 kartında EN etiketli düğme) bastığınızda silinir.

Verileri RTC hafızasına kaydetmek için bir değişken tanımından önce RTC_DATA_ATTR eklemeniz yeterlidir. Örnek, bootCount değişkenini RTC belleğine kaydeder. Bu değişken, ESP32’nin derin uykudan kaç kez uyandığını sayar.

RTC_DATA_ATTR int bootCount = 0;
Uyanma Nedeni

Ardından kod, ESP32’nin uykudan uyandırılma nedenini yazdıran print_wakeup_reason() işlevini tanımlar.

void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch(wakeup_reason){
    case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}
setup()

setup( kısmında, kodunuzu koymanız gereken yerdir. Derin uykuda kod asla loop() ifadesine ulaşmaz. Bu yüzden setup() içindeki tüm taslağı yazmanız gerekir.

Bu örnek, seri iletişimi 115200 baud hızında başlatarak başlar.

Serial.begin(115200);

Ardından, her yeniden başlatmada bootCount değişkeni bir artırılır ve bu sayı seri monitörde yazdırılır.

++bootCount;
Serial.println("Boot number: " + String(bootCount));

Ardından kod, print_wakeup_reason() işlevini çağırır, ancak istediğiniz bir görevi gerçekleştirmek için istediğiniz herhangi bir işlevi çağırabilirsiniz. Örneğin, bir sensörden bir değer okumak için ESP32’nizi günde bir kez uyandırmak isteyebilirsiniz.

Ardından kod, aşağıdaki işlevi kullanarak uyandırma kaynağını tanımlar:

esp_sleep_enable_timer_wakeup(time_in_us)

Bu fonksiyon, daha önce gördüğümüz gibi, uyku süresini mikrosaniye cinsinden argüman olarak kabul eder.

Bizim durumumuzda, aşağıdakilere sahibiz:

esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);

Ardından, tüm görevler gerçekleştirildikten sonra ESP32 aşağıdaki işlevi çağırarak uyku moduna geçer:

esp_deep_sleep_start()
loop()

ESP32, kodun bu bölümüne ulaşmadan önce uyku moduna geçeceğinden loop() bölümü boştur. Bu nedenle, tüm çiziminizi setup()’a yazmanız gerekir.

Örnek çizimi ESP32’nize yükleyin. Doğru kartın ve COM bağlantı noktasının seçili olduğundan emin olun.

Zamanlayıcı Uyanmasını Test Etme

115200 baud hızında Seri Monitörü açın.

Her 5 saniyede bir ESP uyanır, seri monitöre bir mesaj yazdırır ve tekrar derin uykuya geçer.

ESP her uyandığında bootCount değişkeni artar. Ayrıca aşağıdaki şekilde gösterildiği gibi uyanma nedenini de yazdırır.

ESP32 Derin Uyku Kullanımı ve Uyandırma Kaynakları esp32 derin uyku,esp32 deep sleep

Ancak, ESP32 kartındaki EN düğmesine basarsanız, önyükleme sayısını yeniden 1’e sıfırladığını unutmayın.

Sağlanan örneği değiştirebilir ve bir mesaj yazdırmak yerine ESP’nizin başka herhangi bir görevi yapmasını sağlayabilirsiniz. Zamanlayıcı uyandırma, ESP32 ile günlük görevler gibi periyodik görevleri fazla güç tüketmeden gerçekleştirmek için kullanışlıdır.

Dokunarak Uyandırmak

Dokunmatik pinleri kullanarak ESP32’yi derin uyku modundan uyandırabilirsiniz. Bu bölüm, Arduino IDE kullanarak bunun nasıl yapılacağını gösterir.

Dokunma Uyandırmayı Etkinleştirmek

ESP32’nin bir touchpin kullanarak uyanmasını sağlamak basittir. Arduino IDE’de aşağıdaki işlevi kullanmanız gerekir:

esp_sleep_enable_touchpad_wakeup()

Arduino Kodu

Bunun kütüphaneden bir örnek kullanarak nasıl çalıştığını görelim. Arduino IDE’nizi açın ve Dosya > Örnekler > ESP32 > Deep Sleep‘e gidin ve TouchWakeUp kodunu açın.

#define Threshold 40 /* Greater the value, more the sensitivity */

RTC_DATA_ATTR int bootCount = 0;
touch_pad_t touchPin;
/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch(wakeup_reason)
  {
    case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}

/*
Method to print the touchpad by which ESP32
has been awaken from sleep
*/
void print_wakeup_touchpad(){
  touchPin = esp_sleep_get_touchpad_wakeup_status();

  switch(touchPin)
  {
    case 0  : Serial.println("Touch detected on GPIO 4"); break;
    case 1  : Serial.println("Touch detected on GPIO 0"); break;
    case 2  : Serial.println("Touch detected on GPIO 2"); break;
    case 3  : Serial.println("Touch detected on GPIO 15"); break;
    case 4  : Serial.println("Touch detected on GPIO 13"); break;
    case 5  : Serial.println("Touch detected on GPIO 12"); break;
    case 6  : Serial.println("Touch detected on GPIO 14"); break;
    case 7  : Serial.println("Touch detected on GPIO 27"); break;
    case 8  : Serial.println("Touch detected on GPIO 33"); break;
    case 9  : Serial.println("Touch detected on GPIO 32"); break;
    default : Serial.println("Wakeup not by touchpad"); break;
  }
}

void callback(){
  //placeholder callback function
}

void setup(){
  Serial.begin(115200);
  delay(1000); //Take some time to open up the Serial Monitor

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  //Print the wakeup reason for ESP32 and touchpad too
  print_wakeup_reason();
  print_wakeup_touchpad();

  //Setup interrupt on Touch Pad 3 (GPIO15)
  touchAttachInterrupt(T3, callback, Threshold);

  //Configure Touchpad as wakeup source
  esp_sleep_enable_touchpad_wakeup();

  //Go to sleep now
  Serial.println("Going to sleep now");
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

void loop(){
  //This will never be reached
}

Yapmanız gereken ilk şey, dokunmatik pinler için bir eşik değeri belirlemektir. Bu durumda Eşik değerini 40 olarak ayarlıyoruz. Projenize bağlı olarak eşik değerini değiştirmeniz gerekebilir.

#define Threshold 40

Dokunmaya duyarlı bir GPIO’ya dokunduğunuzda sensör tarafından okunan değer azalır. Böylece, dokunma algılandığında bir şeyin olmasını sağlayan bir eşik değeri belirleyebilirsiniz.

Burada ayarlanan eşik değeri, dokunmaya duyarlı GPIO tarafından okunan değer 40’ın altına düştüğünde ESP32’nin uyanması gerektiği anlamına gelir. Bu değeri istediğiniz hassasiyete göre ayarlayabilirsiniz.

Kesmeler Eklemek

Dokunmaya duyarlı pinlere kesintiler eklemeniz gerekir. Belirli bir GPIO’da dokunma algılandığında, bir geri arama işlevi yürütülür. Örneğin, aşağıdaki satıra bir göz atın:

touchAttachInterrupt(T3, callback, Threshold); 

T3’te (GPIO 15) okunan değer, Eşik değişkeninde ayarlanan değerden düşük olduğunda, ESP32 uyanır ve callback işlevi yürütülür.

callback() işlevi yalnızca ESP32 uyanıksa yürütülür.

ESP32 uykudaysa ve T3’e dokunursanız, ESP uyanır – dokunmatik pine basıp bırakırsanız callback() işlevi yürütülmez;
ESP32 uyanıksa ve T3’e dokunursanız, callback işlevi yürütülür. Bu nedenle, ESP32’yi uyandırdığınızda callback() işlevini yürütmek istiyorsanız, işlev yürütülene kadar bir süre o pine dokunmanız gerekir.
Bu durumda callback() işlevi boştur.

void callback(){
}

ESP32’yi farklı dokunmatik pinler kullanarak uyandırmak istiyorsanız, bu pinlere kesmeler eklemeniz yeterlidir.

Ardından, dokunmatik pinleri uyandırma kaynağı olarak ayarlamak için esp_sleep_enable_touchpad_wakeup() işlevini kullanmanız gerekir.

esp_sleep_enable_touchpad_wakeup()

Şematik

ESP32 Derin Uyku Kullanımı ve Uyandırma Kaynakları esp32 derin uyku,esp32 deep sleep

Örneği Test Etmek

Kodu ESP32’nize yükleyin ve Seri Monitörü 115200 baud hızında açın.

ESP32 derin uyku moduna geçer.

Touch Pin 3’e bağlı kabloya dokunarak uyandırabilirsiniz.

Pine dokunduğunuzda, ESP32 Seri Monitörde görüntülenir:

Harici Uyandırma

Zamanlayıcı ve dokunmatik pinlerin yanı sıra, bir düğmeye basmak gibi bir pin üzerindeki sinyalin değerini değiştirerek ESP32’yi derin uykudan uyandırabiliriz. Buna harici uyandırma denir. İki harici uyandırma olanağınız vardır: ext0 ve ext1.

Harici Uyandırma (ext0)

Bu uyandırma kaynağı, ESP32’yi uyandırmak için bir pin kullanmanıza izin verir.

ext0 uyandırma kaynağı seçeneği, uyanmak için RTC GPIO’ları kullanır. Bu nedenle, bu uyandırma kaynağı talep edilirse, derin uyku sırasında RTC çevre birimleri açık tutulacaktır.

Bu uyandırma kaynağını kullanmak için aşağıdaki işlevi kullanırsınız:

esp_sleep_enable_ext0_wakeup(GPIO_NUM_X, level)

Bu fonksiyon, kullanmak istediğiniz pini bu formatta GPIO_NUM_X olarak ilk argüman olarak kabul eder; burada X, o pinin GPIO numarasını temsil eder.

İkinci argüman, seviye, 1 veya 0 olabilir. Bu, uyanmayı tetikleyecek GPIO’nun durumunu temsil eder.

Not: Bu uyandırma kaynağıyla yalnızca RTC GPIO’ları olan pinleri kullanabilirsiniz.

Harici Uyandırma (ext1)

Bu uyandırma kaynağı, birden fazla RTC GPIO kullanmanıza olanak tanır. İki farklı mantık işlevi kullanabilirsiniz:

  • Seçtiğiniz pinlerden herhangi biri yüksekse ESP32’yi uyandır;
  • Seçtiğiniz tüm pinler düşükse ESP32’yi uyandır.

Bu uyandırma kaynağı, RTC denetleyicisi tarafından uygulanır. Böylece RTC çevre birimleri ve RTC bellekleri bu modda kapatılabilir.

Bu uyandırma kaynağını kullanmak için aşağıdaki işlevi kullanırsınız:

esp_sleep_enable_ext1_wakeup(bitmask, mode)

Bu işlev iki bağımsız değişkeni kabul eder:

  • Uyanmaya neden olacak GPIO numaralarının bit maskesi;
  • Mod: ESP32’yi uyandırma mantığı::
  • ESP_EXT1_WAKEUP_ALL_LOW: tüm GPIO’lar düştüğünde uyanır;
  • ESP_EXT1_WAKEUP_ANY_HIGH: GPIO’lardan herhangi biri yükselirse uyanır.

Not: Bu uyandırma kaynağıyla yalnızca RTC GPIO’ları olan pinleri kullanabilirsiniz.

Arduino Kodu

ESP32 kütüphanesi ile gelen örneği inceleyelim. Dosya > Örnekler > ESP32 > Deep Sleep > ExternalWakeUp‘a gidin:

#define BUTTON_PIN_BITMASK 0x200000000 // 2^33 in hex

RTC_DATA_ATTR int bootCount = 0;

/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch(wakeup_reason)
  {
    case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}

void setup(){
  Serial.begin(115200);
  delay(1000); //Take some time to open up the Serial Monitor

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  //Print the wakeup reason for ESP32
  print_wakeup_reason();

  esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1); //1 = High, 0 = Low

  //If you were to use ext1, you would use it like
  //esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);

  //Go to sleep now
  Serial.println("Going to sleep now");
  delay(1000);
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

void loop(){
  //This is not going to be called
}

Bu örnek, GPIO 33’ü yüksek olarak tetiklediğinizde ESP32’yi uyandırır. Kod örneği, her iki yöntemin de nasıl kullanılacağını gösterir: ext0 ve ext1. Kodu olduğu gibi yüklerseniz ext0 kullanacaksınız. Ext1’i kullanma işlevi yorumlanır. Size her iki yöntemin de nasıl çalıştığını ve nasıl kullanılacağını göstereceğiz.

Bu kod, bu makaledeki önceki kodlara çok benzer. setup() içinde, seri iletişimi başlatarak başlarsınız:

Serial.begin(115200); 
delay(1000);

Ardından, bootCount değişkenine bir artırın ve bu değişkeni Seri Monitör’de yazdırın.

++bootCount;
Serial.println("Boot number: " + String(bootCount));

Ardından, daha önce tanımlanan print_wakeup_reason() işlevini kullanarak uyandırma nedenini yazdırırsınız.

print_wakeup_reason();

Bundan sonra, uyandırma kaynaklarını etkinleştirmeniz gerekir. Uyandırma kaynaklarının her birini, ext0 ve ext1’i ayrı ayrı test edeceğiz.

ext0

Bu örnekte, GPIO 33 yüksek seviyeye tetiklendiğinde ESP32 uyanır:

esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1);

GPIO 33 yerine başka bir RTC GPIO pini kullanabilirsiniz.

Şematik

Bu örneği test etmek için, sonraki şematik diyagramı izleyerek ESP32’nize bir buton bağlayın. Düğme, 10K Ohm’luk bir aşağı çekme(pull-down) direnci kullanılarak GPIO 33’e bağlanır.

ESP32 Derin Uyku Kullanımı ve Uyandırma Kaynakları esp32 derin uyku,esp32 deep sleep

Not: Uyandırma kaynağı olarak yalnızca RTC GPIO’lar kullanılabilir. Düğmenizi bağlamak için GPIO 33 yerine herhangi bir RTC GPIO pinini de kullanabilirsiniz.

Örneği Test Etme

Bu örneği test edelim. Örnek kodu ESP32’nize yükleyin. Doğru kartın ve COM bağlantı noktasının seçili olduğundan emin olun. 115200 baud hızında Seri Monitörü açın.

ESP32’yi uyandırmak için düğmeye basın.

Bunu birkaç kez deneyin ve her düğmeye basıldığında önyükleme sayısının arttığını görün.

ESP32 Derin Uyku Kullanımı ve Uyandırma Kaynakları esp32 derin uyku,esp32 deep sleep

Bu yöntemi kullanmak, örneğin belirli bir görevi yapmak için bir düğme kullanarak ESP32’nizi uyandırmak için kullanışlıdır. Ancak bu yöntemle, uyandırma kaynağı olarak yalnızca bir GPIO kullanabilirsiniz.

Ya farklı düğmelere sahip olmak istiyorsanız, hepsi ESP’yi uyandırıyor, ancak farklı görevler yapıyorsa? Bunun için ext1 yöntemini kullanmanız gerekir.

ext1

ext1, farklı düğmeler kullanarak ESP’yi uyandırmanıza ve bastığınız düğmeye bağlı olarak farklı görevler gerçekleştirmenize olanak tanır.

esp_sleep_enable_ext0_wakeup() işlevini kullanmak yerine esp_sleep_enable_ext1_wakeup() işlevini kullanırsınız. Kodda, bu işlev yorumlanmıştır:

//esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);

Bu işlevin yorumunu kaldırın, böylece şunlara sahip olursunuz:

esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);

İşlevin ilk argümanı, uyandırma kaynağı olarak kullanacağınız GPIO’ların bir bit maskesidir ve ikinci argüman, ESP32’yi uyandırma mantığını tanımlar.

Bu örnekte, kodun başında tanımlanan BUTTON_PIN_BITMASK değişkenini kullanıyoruz:

#define BUTTON_PIN_BITMASK 0x200000000 // 2^33 in hex

Bu, uyandırma kaynağı olarak yalnızca bir pini tanımlar, GPIO 33. Uyandırma kaynağı olarak daha fazla GPIO yapılandırmak için bit maskesini değiştirmeniz gerekir.

GPIO Bitmask

GPIO’ların bit maskesini almak için sonraki adımları izleyin:

  • 2(GPIO Numarası) hesaplayın. Sonucu ondalık olarak kaydedin;
  • Buradaki araca gidin ve ondalık sayıyı hex’e çevirin;
  • BUTTON_PIN_BITMASK değişkeninde elde ettiğiniz onaltılı sayıyı değiştirin.

Tek GPIO İçin

GPIO’ların bit maskesini nasıl alacağınızı anlamanız için bir örnek üzerinden gidelim. Kütüphaneden gelen kodda, buton GPIO 33’e bağlıdır. GPIO 33 için maskeyi almak için:

233 = 8589934592 olarak hesaplarsınız.

Bu sayıyı (8589934592) onaltılık sayıya dönüştürün. Bunu yapmak için bu dönüştürücüye gidebilirsiniz:

ESP32 Derin Uyku Kullanımı ve Uyandırma Kaynakları esp32 derin uyku,esp32 deep sleep

Onaltılık sayıyı BUTTON_PIN_BITMASK değişkenine kopyalayın:

#define BUTTON_PIN_BITMASK 0x200000000

Birden Fazla GPIO İçin Maske

Uyandırma kaynağı olarak GPIO 2 ve GPIO 15’i kullanmak istiyorsanız aşağıdakileri yapmanız gerekir:

22 + 215 hesaplayınca 32772 alırız.
Bu sayıyı hex’e dönüştürürsek şunu alırız: 8004
Bu numarayı BUTTON_PIN_BITMASK‘ta aşağıdaki gibi değiştirin:

#define BUTTON_PIN_BITMASK 0x8004

Uyandırma Kaynağı Olarak Kullanılan GPIO’yu Belirleme

ESP32’yi uyandırmak için birkaç pin kullandığınızda, uyanmaya hangi pinin neden olduğunu bilmek faydalıdır. Bunun için aşağıdaki işlevi kullanabilirsiniz:

esp_sleep_get_ext1_wakeup_status()

Bu işlev, üs olarak GPIO numarasıyla birlikte 2 tabanlı bir sayı döndürür: 2(GPIO). Bu nedenle, GPIO’yu ondalık olarak almak için aşağıdaki hesaplamayı yapmanız gerekir:

GPIO = log(RETURNED_VALUE)/log(2)

Harici Uyandırma – Birden Çok GPIO

Şimdi, farklı düğmeler kullanarak ESP32’yi uyandırabilmeli ve hangi düğmenin uyanmaya neden olduğunu belirleyebilmelisiniz. Bu örnekte, uyandırma kaynağı olarak GPIO 2 ve GPIO 15 kullanacağız.

Şematik

ESP32’nize iki düğme bağlayın. Bu örnekte GPIO 2 ve GPIO 15 kullanıyoruz, ancak düğmelerinizi herhangi bir RTC GPIO’ya bağlayabilirsiniz.

ESP32 Derin Uyku Kullanımı ve Uyandırma Kaynakları esp32 derin uyku,esp32 deep sleep

Arduino Kodu

Daha önce kullandığımız örnek kodda bazı değişiklikler yapmanız gerekiyor:

GPIO 15 ve GPIO 2’yi kullanmak için bir bit maskesi oluşturun. Bunu nasıl yapacağınızı üstte göstermiştik;
ext1’i uyandırma kaynağı olarak etkinleştirin;
uyanmayı tetikleyen GPIO’yu almak için esp_sleep_get_ext1_wakeup_status() işlevini kullanın.


#define BUTTON_PIN_BITMASK 0x8004 // GPIOs 2 and 15

RTC_DATA_ATTR int bootCount = 0;

/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch(wakeup_reason)
  {
    case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}

/*
Method to print the GPIO that triggered the wakeup
*/
void print_GPIO_wake_up(){
  uint64_t GPIO_reason = esp_sleep_get_ext1_wakeup_status();
  Serial.print("GPIO that triggered the wake up: GPIO ");
  Serial.println((log(GPIO_reason))/log(2), 0);
}
  
void setup(){
  Serial.begin(115200);
  delay(1000); //Take some time to open up the Serial Monitor

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  //Print the wakeup reason for ESP32
  print_wakeup_reason();

  //Print the GPIO used to wake up
  print_GPIO_wake_up();

  /*
  First we configure the wake up source
  We set our ESP32 to wake up for an external trigger.
  There are two types for ESP32, ext0 and ext1 .
  ext0 uses RTC_IO to wakeup thus requires RTC peripherals
  to be on while ext1 uses RTC Controller so doesnt need
  peripherals to be powered on.
  Note that using internal pullups/pulldowns also requires
  RTC peripherals to be turned on.
  */
  //esp_deep_sleep_enable_ext0_wakeup(GPIO_NUM_15,1); //1 = High, 0 = Low

  //If you were to use ext1, you would use it like
  esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);

  //Go to sleep now
  Serial.println("Going to sleep now");
  delay(1000);
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

void loop(){
  //This is not going to be called
}

GPIOs maskesini kodun başında tanımlarsınız:

#define BUTTON_PIN_BITMASK 0x8004 

Uyanmaya neden olan GPIO’yu yazdırmak için bir işlev yaratırsınız:

void print_GPIO_wake_up(){
  int GPIO_reason = esp_sleep_get_ext1_wakeup_status();
  Serial.print("GPIO that triggered the wake up: GPIO ");
  Serial.println((log(GPIO_reason))/log(2), 0);
}

Son olarak, uyandırma kaynağı olarak ext1’i etkinleştirirsiniz:

esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ANY_HIGH);

Kodu Test Etmek

115200 baud hızında Seri Monitörü açın. ESP32’yi uyandırmak için düğmelere basın.

Seri monitörde benzer bir şey almalısınız.

ESP32 Derin Uyku Kullanımı ve Uyandırma Kaynakları esp32 derin uyku,esp32 deep sleep

Özetle

Bu yazıda, ESP32 ile derin uykunun nasıl kullanılacağını ve onu uyandırmanın farklı yollarını gösterdik. ESP32’yi bir zamanlayıcı, dokunmatik pinler veya bir GPIO durumundaki bir değişiklik kullanarak uyandırabilirsiniz.

Her uyandırma kaynağı hakkında gördüklerimizi özetleyelim:

Zamanlayıcı İle

  • Zamanlayıcı uyanmasını etkinleştirmek için esp_sleep_enable_timer_wakeup(time_in_us) işlevini kullanırsınız;
  • Derin uykuyu başlatmak için esp_deep_sleep_start() işlevini kullanırsınız.

Dokunmatik Pinler İle

  • Uyandırma kaynağı olarak dokunmatik pinleri kullanmak için, önce touchAttachInterrupt(Touchpin, callback, Threshold) kullanarak touch pinlerine kesmeler eklemeniz gerekir.
  • Ardından, aşağıdakileri kullanarak dokunmatik pimleri uyandırma kaynağı olarak etkinleştirirsiniz: esp_sleep_enable_touchpad_wakeup()
  • Son olarak, ESP32’yi derin uyku moduna geçirmek için esp_deep_sleep_start() işlevini kullanırsınız.

Harici Uyandırma İle

  • RTC GPIO’ları yalnızca harici uyandırma olarak kullanabilirsiniz;
  • İki farklı yöntem kullanabilirsiniz: ext0 ve ext1;
  • ext0, tek bir GPIO pini kullanarak ESP32’yi uyandırmanızı sağlar;
  • ext1, birkaç GPIO pini kullanarak ESP32’yi uyandırmanızı sağlar.