ESP32를 Deep Sleep 모드로 전환하는 방법을 알아보겠습니다.
Deep Sleep 모드 소개
ESP32는 다음과 같은 다양한 전원 모드로 전환할 수 있습니다
- Active mode
- Modem Sleep mode
- Light Sleep mode
- Deep Sleep mode
- Hibernation mode
ESP32 데이터시트에서 5가지 모드를 비교할 수 있습니다.
ESP32 데이터시트에서 다음과 같은 다양한 모드의 전력 소비를 비교하는 표를 확인할 수 있습니다.
활성 모드에서의 전력 소비를 비교한 표 입니다.
왜 Deep Sleep 모드를 사용해야 할까요
ESP32를 활성 모드로 배터리로 운영하는 것은 이상적이지 않습니다. 배터리의 전력이 매우 빨리 소모될 것입니다.
ESP32를 Deep Sleep 모드로 전환하면 전력 소비가 줄어들어 배터리가 더 오래 지속됩니다.
Deep Sleep 모드에서는 CPU와 Wi-Fi 활동이 중단되지만, 초저전력(ULP) 보조 프로세서는 여전히 전원이 공급될 수 있습니다.
Deep Sleep 모드에서 RTC 메모리(RTC 메모리)는 계속 전원이 공급되므로, ULP 보조 프로세서 프로그램을 작성하고 RTC 메모리에 저장하여 주변 장치, 내부 타이머 및 내부 센서에 접근할 수 있습니다. 이 작동 모드는 외부 이벤트, 타이머 또는 둘 다에 의해 메인 CPU를 깨우면서 최소한의 전력 소비를 유지해야 할 때 유용합니다.
RTC_GPIO 핀
Deep Sleep 모드 동안 ESP32의 일부 핀은 ULP 보조 프로세서에 의해 사용될 수 있습니다.
RTC핀은 파란색 상자로 확인 할수 있습니다. 있습니다.
Wake up 방법
ESP32를 Deep Sleep 모드로 전환한 후에는 여러 가지 방법으로 깨울 수 있습니다:
- 타이머를 사용하여 ESP32를 정해진 주기로 깨우기
- 터치 핀 사용
- 외부 웨이크업 소스를 사용: 단일 외부 웨이크업 또는 여러 외부 웨이크업 소스 중에서 선택 가능
- ULP 보조 프로세서를 사용하여 깨우기
Deep Sleep 스케치 작성
ESP32를 Deep Sleep 모드로 전환하고 다시 깨우는 스케치를 작성하려면 다음 사항을 염두에 두어야 합니다
- 어떤 것이 ESP32를 깨울지 설정해야 하며, 하나 또는 여러 개의 웨이크업 소스를 사용할 수 있습니다.
- Deep Sleep 동안 어떤 주변 장치를 종료하거나 유지할지 결정할 수 있습니다. 기본적으로 ESP32는 정의된 웨이크업 소스와 필요 없는 주변 장치의 전원을 자동으로 차단합니다.
- 마지막으로 esp_deep_sleep_start() 함수를 사용하여 ESP32를 Deep Sleep 모드로 전환합니다.
Timer Wake UP
ESP32는 Deep Sleep 모드에 들어가고 정해진 주기로 다시 깨울 수 있습니다.
Timer Wake UP 활성화
Arduino IDE에서는 다음 함수를 사용하여 마이크로초 단위로 수면 시간을 지정하여 정해진 시간 후에 깨우도록 설정합니다.
esp_sleep_enable_timer_wakeup(time_in_us)
코드
다음은 라이브러리의 예제를 사용하여 이 기능을 구현하는 방법을 살펴보겠습니다.
Arduino IDE를 열고 파일 > 예제 > ESP32 Deep Sleep로 가서 TimerWakeUp 스케치를 엽니다.
#define uS_TO_S_FACTOR 1000000 /* 마이크로초를 초로 변환하기 위한 변환 계수 */
#define TIME_TO_SLEEP 5 /* ESP32가 수면 상태로 들어가는 시간 (초 단위) */
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 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); // Serial 모니터를 열기 위해 잠시 대기합니다.
// 부트 번호를 증가시키고 매 재부팅 시 출력합니다.
++bootCount;
Serial.println("부트 번호: " + String(bootCount));
// ESP32의 깨어나는 원인을 출력합니다.
print_wakeup_reason();
/*
먼저 웨이크업 소스를 구성합니다.
ESP32가 매 5초마다 깨우도록 설정합니다.
*/
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");
/*
이제 모든 주변 장치의 전원을 끄거나 켜둘지를 결정합니다.
기본적으로 ESP32는 웨이크업 소스에 필요하지 않은 주변 장치의
전원을 자동으로 차단하지만, 전력 사용자라면
이 부분이 유용할 것입니다. API 문서에서 자세히 읽어보세요.
http://esp-idf.readthedocs.io/en/latest/api-reference/system/deep_sleep.html
아래의 줄은 딥 슬립에서 모든 RTC 주변 장치를 끄도록 설정합니다.
*/
//esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
//Serial.println("Configured all RTC Peripherals to be powered down in sleep");
/*
이제 웨이크 원인을 설정했으며 필요하다면
딥 슬립 중 주변 장치 상태를 설정했으므로,
이제 딥 슬립 모드로 들어갑니다.
웨이크업 소스가 제공되지 않았지만 딥 슬립이 시작되면,
하드웨어 리셋이 발생할 때까지 무한정 잠들게 됩니다.
*/
Serial.println("Going to sleep now");
delay(1000);
Serial.flush();
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
void loop(){
// 이 함수는 호출되지 않습니다.
}
코드설명
수면 시간 정의
ESP32가 수면에 들어갈 기간을 정의합니다.
#define uS_TO_S_FACTOR 1000000 /* 마이크로초를 초로 변환하기 위한 변환 계수 */
#define TIME_TO_SLEEP 5 /* ESP32가 수면 상태로 들어가는 시간 (초 단위) */
마이크로초를 초로 변환하기 위해 uS_TO_S_FACTOR 변수를 정의하고, 수면 기간을 5초로 설정했습니다.
RTC_DATA_ATTR 메모리 속성
RTC_DATA_ATTR를 사용하여 부트 카운트를 정의합니다. 이 메모리 속성을 사용하면 ESP32가 다시 시작되더라도 이 데이터는 메모리에 유지됩니다.
RTC_DATA_ATTR int bootCount = 0;
bootCount 변수는 부트할 때마다 1씩 증가합니다. Serial Monitor에 출력합니다.
깨어나는 이유
print_wakeup_reason()는 잠에서 깨어나게 한 원인을 출력하는 함수입니다.
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() 함수
다음과 같이 구성됩니다.
- Serial 포트를 초기화하고 1초간 대기한 후 부트 카운트를 증가시킵니다.
- print_wakeup_reason() 메서드를 사용하여 ESP32가 수면에서 깨어난 이유를 출력합니다.
- ESP32가 5초마다 깨우도록 타이머를 구성합니다.
- Serial 포트로 수면에 들어가겠다는 메시지를 출력하고, ESP32를 수면 상태로 전환합니다.
void setup(){
Serial.begin(115200);
delay(1000); // Serial 모니터를 열기 위해 잠시 대기합니다.
// 부트 번호를 증가시키고 매 재부팅 시 출력합니다.
++bootCount;
Serial.println("부트 번호: " + String(bootCount));
// ESP32의 깨어나는 원인을 출력합니다.
print_wakeup_reason();
/*
먼저 웨이크업 소스를 구성합니다.
ESP32가 매 5초마다 깨우도록 설정합니다.
*/
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");
}
테스트
코드를 업로드한 후 Serial Monitor를 열고 보드가 수면 상태에 들어가고 다시 깨워질 때 Serial Monitor의 출력 결과를 확인하세요. 이 출력을 통해 타이머 웨이크업의 작동을 확인할 수 있습니다.
'ESP32 > ESP32' 카테고리의 다른 글
ESP32 Deep Sleep 구현하기 - 외부 웨이크업(External Wake Up) (0) | 2024.10.23 |
---|---|
ESP32 Deep Sleep 구현하기 -Touch Wake Up (0) | 2024.10.22 |
ESP32 인터럽트(Interrupt) 구현하기 - PIR(인체감지센서) (2) | 2024.10.17 |
ESP32 Timer 구현하기 - millis()함수 사용하기 (4) | 2024.10.16 |
ESP32 ADC - 아날로그 값 읽기 (0) | 2024.10.16 |