niedziela, 24 września 2017

[3] ESP32 - Sposoby usypiania układu

Ten post chciałbym poświęcić na opisanie sposobów usypiania układu ESP32.

[Źródło: www.banggood.com]

Sposoby usypiania:


Do usypiania możliwa jest opcja wprowadzająca układ w stan głębokiego uśpienia. Aby ją zastosować należy ustawić np. jeden z dwóch przerwań od portów, timer, kontroler dotykowy na bądź koprocesor. 

W tym trybie działa jedynie kontroler RTC, układy RTC w tym koprocesor ULP oraz dostęp do pamięci RTC szybkiej i wolnej. Sposoby wybudzania oraz usypiania mogą zostać ze sobą powiązane. np. można wybudzać za pomocą portu GPIO oraz timera. 

Należy pamiętać o poprawnej konfiguracji zasilania. Oznacza to że opcja którą chce się używać w celu wybudzenia układu.

W celu konfiguracji należy zapoznać się z następującymi funkcjami:

esp_deep_sleep_pd_config - pozwala na ustawienie poszczególnych elementów które są zasilane. 

  1. esp_err_t esp_deep_sleep_pd_config(esp_deep_sleep_pd_domain_t domain, esp_deep_sleep_pd_option_t option);

W przypadku nie wywołania tej funkcji ustawiony jest parametr ESP_PD_OPTION_AUTO.

Funkcja zwraca ESP_OK w przypadku poprawnej konfiguracji, bądź ESP_ERR_INVALID_ARG w przypadku gdy argument jest nieodpowiedni.

Jako parametry podaje się w pierwszym miejscu domenę do konfiguracji. Do wyboru są:

  • ESP_PD_DOMAIN_RTC_PERIPH - uruchomione są piny gpio RTC, czujniki oraz koprocesor ULP.
  • ESP_PD_DOMAIN_RTC_SLOW_MEM - uruchomienia jest wolna pamięć RTC. Zawiera ona globalne i statyczne zmienne, które są wykorzystywane przez kod z pamięci RTC. 
  • ESP_PD_DOMAIN_RTC_FAST_MEM - uruchomiony dostęp do szybkiej pamięci RTC. Jest ona zarezerwowana dla kodu wykonywanego po obudzeniu procesora z głębokiego uśpienia. 
  • ESP_PD_DOMAIN_MAX - liczba domen.


Drugim elementem są opcje wyłączenia zasilania. W tym przypadku do wyboru są trzy elementy:

  • ESP_PD_OPTION_OFF - wyłącz podaną domenę w czasie głębokiego uśpienia.
  • ESP_PD_OPTION_ON - utrzymuj zasilanie na podanej domenie.
  • ESP_PD_OPTION_AUTO - automatyczne ustawienie. Otrzymuje zasilania na domenach wymaganych do wybudzenia. W innym przypadku je wyłącza.


esp_deep_sleep_enable_timer_wakeup - uruchomienie timera do wybudzania układu z uśpienia.

  1. esp_err_t esp_deep_sleep_enable_timer_wakeup(uint64_t time_in_us);

Jako argument podawany jest czas mikrosekundach, Natomiast jego dokładność zależy od zegara RTC SLOW_CLOCK. Do wybudzenia nie trzeba zasilać pamięci RTC podczas uśpienia. Wartości zwracane są takie sam jak w przypadku esp_deep_sleep_pd_config.

esp_deep_sleep_enable_ext0_wakeup - uruchamianie wybudzenia poprzez podany podany pin.

  1. esp_err_t esp_deep_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level);

Funkcja zwraca takie same argumenty jak funkcje opisane powyżej. 

Jako argumenty podaje się numery pinów. Do wyboru są tylko te piny które posiadają funkcjonalność RTC (0, 2, 4, 12 - 15, 25 - 27, 32 - 39). Drugi argument podaje się stan jakim ma być obudzony układ. 0 dla stanu niskiego, 1 dla stanu wysokiego.

esp_deep_sleep_start - uruchamianie uśpienia. 

  1. void esp_deep_sleep_start();

Przed jej wywołaniem należy skonfigurować sposoby wybudzania. Bez konfiguracji wybudzenie nie będzie możliwe.  Funkcja nie zwraca żadnych wartości.

esp_deep_sleep_get_ext0_wakeup_status - pozwala na sprawdzenie czy wybudzenie zostało wywołane z pinów przypisanych do ext0.

esp_deep_sleep_get_ext0_wakeup_status - to samo co dla funkcji powyżej tylko z innego przerwania.

Implementacja w programie:


Poniżej funkcje znajdujące się w przygotowanej bibliotece. Funkcja pozwalająca na uruchomienie wybranego pinu:

  1. static uint8_t configGpioForEnableInterrupt(gpio_num_t gpio_num, uint8_t enablePullUp, uint8_tenablePullDown)
  2. {
  3.     esp_err_t status;
  4.     if(enablePullUp == enablePullDown) {
  5.         return 1; /* Return Error */
  6.     }
  7.     if(gpio_num > 2) {
  8.         return 1; /* Return Error */
  9.     }
  10.     if(enablePullUp == 1)   { gpio_pullup_en(gpio_num);     }
  11.     else                    { gpio_pullup_dis(gpio_num);    }
  12.     if(enablePullDown == 1) { gpio_pulldown_en(gpio_num);   }
  13.     else                    { gpio_pulldown_dis(gpio_num);  }
  14.     if((gpio_num == 0) && enablePullUp == 1)        {   esp_deep_sleep_enable_ext0_wakeup(gpio_num, 0); }
  15.     else if(gpio_num == 0 && enablePullDown == 1)   {   esp_deep_sleep_enable_ext0_wakeup(gpio_num, 1); }
  16.     else if(gpio_num == 1 && enablePullUp == 1)     {   esp_deep_sleep_enable_ext1_wakeup(gpio_num, 0); }
  17.     else if(gpio_num == 1 && enablePullDown == 1)   {   esp_deep_sleep_enable_ext1_wakeup(gpio_num, 1); }
  18.     return 0;
  19. }

Ustawienie domeny zasilania:

  1. static uint8_t configPowerDomain()
  2. {
  3.     esp_err_t status;
  4.     status = esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_AUTO);
  5.     if(status == ESP_OK) { return 0; }
  6.     return 1;
  7. }

Uruchomienie timera w trybie uśpienia:

  1. static uint8_t enableTimerForSleepMode(uint32_t time)
  2. {
  3.     esp_err_t status;
  4.     esp_deep_sleep_enable_timer_wakeup(time * DEEP_SLEEP_DURATION);
  5.     if(status == ESP_OK) { return 0; }
  6.     return 1;
  7. }

Przykładowa konfiguracja do uruchomienia timera oraz jednego pinu do wybudzania z uśpienia:

  1. void SleepFunction(void)
  2. {
  3.     configGpioForEnableInterrupt(IO_TRIGGER, 1, 0);
  4.     enableTimerForSleepMode(3000000LL);
  5.     esp_deep_sleep_start();
  6. }

Można je konfigurować osobno jak i połączone razem. Można je wywoływać osobno jak i razem. W przykładzie umieszczonym powyżej wybudzenie może nastąpić po przez sygnał niski z pinu lub po przekroczeniu czasu w timerze.