ESP32의 Deep Sleep 모드에서 깨어나는 방법 중 하나는 외부 신호로 깨우는 방식입니다. 이 방법은 버튼을 누르거나, GPIO 핀의 상태 변화를 감지하여 ESP32를 깨울 수 있습니다. 외부 신호로 깨우는 방식에는 ext0와 ext1 두 가지 옵션이 있습니다.
External Wake Up 방식
1. External Wake Up (ext0)
이 방법은 RTC GPIO를 사용하여 ESP32를 깨웁니다. 이때, RTC 주변 장치가 계속 켜져 있어야 하며, RTC_IO를 사용하여 핀의 상태에 따라 ESP32를 깨울 수 있습니다.
esp_sleep_enable_ext0_wakeup(GPIO_NUM_X, level)
첫 번째 인자: GPIO_NUM_X 형식으로 사용하고자 하는 핀 번호를 입력합니다.
두 번째 인자: level 값은 0 또는 1이 될 수 있으며, 1은 핀이 HIGH 상태일 때, 0은 LOW 상태일 때 ESP32를 깨우게 됩니다.
주의: ext0 모드를 사용할 때는 반드시 RTC GPIO 핀만 사용할 수 있습니다.
2. External Wake Up (ext1)
ext1 방식은 RTC 컨트롤러를 사용해 ESP32를 깨우며, 이 방식에서는 RTC 주변 장치 및 메모리를 꺼도 문제가 없습니다.
esp_sleep_enable_ext1_wakeup_io(bitmask, mode);
첫 번째 인자: wake up을 유발할 GPIO의 비트마스크
두 번째 인자: wake up 조건 모드
- ESP_EXT1_WAKEUP_ALL_LOW: 모든 GPIO 핀이 LOW일 때 깨움
- ESP_EXT1_WAKEUP_ANY_HIGH: GPIO 핀 중 하나라도 HIGH일 때 깨움
주의: ext1 모드 역시 RTC GPIO 핀만 사용 가능합니다.
External Wake Up (ext0) 구현하기
회로도
코드
ESP32 라이브러리에는 외부 신호로 Deep Sleep에서 깨우는 예시 코드가 있습니다.
이 코드를 통해 ext0와 ext1 방식을 각각 어떻게 사용하는지 배울 수 있습니다.
#include "driver/rtc_io.h"
#define BUTTON_PIN_BITMASK(GPIO) (1ULL << GPIO)
#define USE_EXT0_WAKEUP 1
#define WAKEUP_GPIO GPIO_NUM_33
RTC_DATA_ATTR int bootCount = 0;
void print_wakeup_reason() {
esp_sleep_wakeup_cause_t 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;
default:
Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason);
break;
}
}
void setup() {
Serial.begin(115200);
delay(1000);
++bootCount;
Serial.println("Boot number: " + String(bootCount));
print_wakeup_reason();
#if USE_EXT0_WAKEUP
esp_sleep_enable_ext0_wakeup(WAKEUP_GPIO, 1);
rtc_gpio_pullup_dis(WAKEUP_GPIO);
rtc_gpio_pulldown_en(WAKEUP_GPIO);
#else
esp_sleep_enable_ext1_wakeup_io(BUTTON_PIN_BITMASK(WAKEUP_GPIO), ESP_EXT1_WAKEUP_ANY_HIGH);
rtc_gpio_pulldown_en(WAKEUP_GPIO);
rtc_gpio_pullup_dis(WAKEUP_GPIO);
#endif
Serial.println("Going to sleep now");
esp_deep_sleep_start();
}
void loop() {}
이 코드는 GPIO 33을 HIGH 상태로 만들면 ESP32가 깨어나는 방식으로 동작합니다. USE_EXT0_WAKEUP을 1로 설정하면 ext0 모드로, 0으로 설정하면 ext1 모드로 실행됩니다.
각 코드에 대해서 자세히 알아보겠습니다.
헤더 및 전역 변수 정의:
#include "driver/rtc_io.h"
#define BUTTON_PIN_BITMASK(GPIO) (1ULL << GPIO)
#define USE_EXT0_WAKEUP 1
#define WAKEUP_GPIO GPIO_NUM_33
RTC_DATA_ATTR int bootCount = 0;
- #include "driver/rtc_io.h": RTC GPIO 관련 기능을 사용하기 위해 rtc_io.h 헤더 파일을 포함합니다.
- BUTTON_PIN_BITMASK(GPIO): 주어진 GPIO 번호를 비트마스크로 변환하는 매크로입니다. 이는 ext1 모드에서 GPIO 핀을 여러 개 사용할 때 필요합니다.
- USE_EXT0_WAKEUP: 이 값을 1로 설정하면 ext0 모드로 작동하고, 0으로 설정하면 ext1 모드로 작동합니다.
- WAKEUP_GPIO: 깨우기에 사용할 GPIO 번호를 정의합니다. 여기서는 GPIO 33을 사용합니다.
- RTC_DATA_ATTR int bootCount = 0;: RTC_DATA_ATTR은 Deep Sleep 후에도 값을 유지할 수 있는 메모리 공간에 변수를 저장하는 어트리뷰트입니다. bootCount는 ESP32가 깨어난 횟수를 기록하는 변수입니다.
웨이크업 원인 출력 함수:
void print_wakeup_reason() {
esp_sleep_wakeup_cause_t 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;
default:
Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason);
break;
}
}
- esp_sleep_get_wakeup_cause(): ESP32가 Deep Sleep에서 깨어난 원인을 반환하는 함수입니다.
- 이 함수는 switch 문을 통해 ESP32가 깨어난 이유를 시리얼 모니터에 출력합니다.
- ESP_SLEEP_WAKEUP_EXT0: ext0 모드로 깨웠을 때 출력됩니다.
- ESP_SLEEP_WAKEUP_EXT1: ext1 모드로 깨웠을 때 출력됩니다.
- ESP_SLEEP_WAKEUP_TIMER: 타이머로 인해 깨어났을 때 출력됩니다.
- ESP_SLEEP_WAKEUP_TOUCHPAD: 터치 패드로 인해 깨어났을 때 출력됩니다.
- 그 외의 경우는 알 수 없는 이유로 깨어난 것으로 처리됩니다.
setup() 함수:
void setup() {
Serial.begin(115200);
delay(1000);
++bootCount;
Serial.println("Boot number: " + String(bootCount));
print_wakeup_reason();
- Serial.begin(115200): 시리얼 통신을 115200 baud rate로 시작합니다.
- delay(1000): 1초간 대기합니다.
- ++bootCount: ESP32가 부팅될 때마다 bootCount 값을 증가시킵니다. 이 값은 Deep Sleep 후에도 계속 유지됩니다.
- print_wakeup_reason(): ESP32가 Deep Sleep에서 깨어난 이유를 출력합니다.
외부 신호로 깨우기 설정
#if USE_EXT0_WAKEUP
esp_sleep_enable_ext0_wakeup(WAKEUP_GPIO, 1);
rtc_gpio_pullup_dis(WAKEUP_GPIO);
rtc_gpio_pulldown_en(WAKEUP_GPIO);
#else
esp_sleep_enable_ext1_wakeup_io(BUTTON_PIN_BITMASK(WAKEUP_GPIO), ESP_EXT1_WAKEUP_ANY_HIGH);
rtc_gpio_pulldown_en(WAKEUP_GPIO);
rtc_gpio_pullup_dis(WAKEUP_GPIO);
#endif
- ext0 모드:
esp_sleep_enable_ext0_wakeup(WAKEUP_GPIO, 1)은 GPIO 33 핀이 HIGH 상태일 때 ESP32를 깨우도록 설정합니다. 이 경우, RTC GPIO 핀을 사용해야 하며, rtc_gpio_pullup_dis()와 rtc_gpio_pulldown_en()으로 핀의 풀업과 풀다운 저항을 설정합니다. - ext1 모드:
esp_sleep_enable_ext1_wakeup_io(BUTTON_PIN_BITMASK(WAKEUP_GPIO), ESP_EXT1_WAKEUP_ANY_HIGH)은 GPIO 33 핀이 HIGH로 변할 때 ESP32를 깨우도록 설정합니다. 이 모드에서는 여러 GPIO 핀을 동시에 사용할 수 있습니다. 풀업/풀다운 저항도 설정합니다.
Deep Sleep 모드 진입
Serial.println("Going to sleep now");
esp_deep_sleep_start();
- esp_deep_sleep_start(): ESP32를 Deep Sleep 모드로 전환합니다. 이 상태에서는 대부분의 기능이 비활성화됩니다.
External Wake Up (ext1) 구현하기 - 여러 GPIO 사용하기
회로도
코드
#include "driver/rtc_io.h"
#define BUTTON_PIN_BITMASK(GPIO) (1ULL << GPIO) // GPIO 번호에 해당하는 2의 거듭제곱 값을 16진수로 나타냄
#define WAKEUP_GPIO_2 GPIO_NUM_2 // RTC IO만 허용됨 - ESP32 핀 예시
#define WAKEUP_GPIO_15 GPIO_NUM_15 // RTC IO만 허용됨 - ESP32 핀 예시
// 여러 GPIO를 위한 비트마스크 정의
uint64_t bitmask = BUTTON_PIN_BITMASK(WAKEUP_GPIO_2) | BUTTON_PIN_BITMASK(WAKEUP_GPIO_15);
RTC_DATA_ATTR int bootCount = 0;
/*
깨어난 GPIO를 출력하는 함수
*/
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);
}
/*
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");
print_GPIO_wake_up();
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); // 시리얼 모니터를 열기 위해 잠시 대기
// 부팅 횟수를 증가시키고 매 부팅마다 출력
++bootCount;
Serial.println("Boot number: " + String(bootCount));
// ESP32의 깨어난 이유 출력
print_wakeup_reason();
// ext1을 깨우기 소스로 사용
esp_sleep_enable_ext1_wakeup_io(bitmask, ESP_EXT1_WAKEUP_ANY_HIGH);
// 풀다운 저항을 활성화하고 풀업 저항을 비활성화
rtc_gpio_pulldown_en(WAKEUP_GPIO_2);
rtc_gpio_pullup_dis(WAKEUP_GPIO_2);
rtc_gpio_pulldown_en(WAKEUP_GPIO_15);
rtc_gpio_pullup_dis(WAKEUP_GPIO_15);
// 이제 수면 모드로 진입
Serial.println("Going to sleep now");
esp_deep_sleep_start();
Serial.println("This will never be printed");
}
void loop() {
// 이 함수는 호출되지 않음
}
각 코드에 대해서 자세히 알아보겠습니다.
이 코드는 ESP32의 여러 GPIO 핀을 이용해 외부 신호로부터 깨우는 기능을 구현한 예제입니다.
EXT1 외부 신호를 사용하여 ESP32를 깊은 수면 상태에서 깨어나게 하고, 어떤 GPIO가 깨우는 신호를 발생시켰는지 출력합니다.
GPIO 비트마스크 설정:
코드의 처음 부분에서 사용할 GPIO 핀들의 비트마스크를 정의합니다. 여기서는 GPIO 2번과 15번 핀이 사용됩니다.
#define BUTTON_PIN_BITMASK(GPIO) (1ULL << GPIO)
#define WAKEUP_GPIO_2 GPIO_NUM_2
#define WAKEUP_GPIO_15 GPIO_NUM_15
uint64_t bitmask = BUTTON_PIN_BITMASK(WAKEUP_GPIO_2) | BUTTON_PIN_BITMASK(WAKEUP_GPIO_15);
비트마스크는 여러 GPIO 핀을 한꺼번에 사용할 수 있도록 설정된 값으로, 각 GPIO 핀 번호에 해당하는 비트를 1로 설정하여 이를 표현합니다.
wake_up GPIO 출력:
print_GPIO_wake_up() 함수는 어떤 GPIO가 ESP32를 깨운 것인지를 출력합니다.
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);
}
웨이크업 원인 출력 함수:
print_wakeup_reason() 함수는 ESP32가 깊은 수면에서 깨어난 이유를 출력합니다. 특히 EXT1 신호로 깨워진 경우 print_GPIO_wake_up()을 호출해 어떤 GPIO가 신호를 발생시켰는지 출력합니다.
void print_wakeup_reason() {
esp_sleep_wakeup_cause_t 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;
default:
Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason);
break;
}
}
EXT1 외부 신호로 깨우기 설정
EXT1을 외부 신호로 사용하기 위해 GPIO 비트마스크와 깨우기 모드를 설정합니다.
esp_sleep_enable_ext1_wakeup_io(bitmask, ESP_EXT1_WAKEUP_ANY_HIGH);
해당 GPIO 핀의 풀업 저항을 비활성화하고 풀다운 저항을 활성화합니다.
rtc_gpio_pulldown_en(WAKEUP_GPIO_2);
rtc_gpio_pullup_dis(WAKEUP_GPIO_2);
rtc_gpio_pulldown_en(WAKEUP_GPIO_15);
rtc_gpio_pullup_dis(WAKEUP_GPIO_15);
Deep Sleep 모드 진입
Serial.println("Going to sleep now");
esp_deep_sleep_start();
- esp_deep_sleep_start(): ESP32를 Deep Sleep 모드로 전환합니다. 이 상태에서는 대부분의 기능이 비활성화됩니다.
이상으로 외부 장치를 사용하여 ESP32 Deep Sleep 하는 방법을 알아보았습니다.
'ESP32 > ESP32' 카테고리의 다른 글
ESP32 Deep Sleep 구현하기 -Touch Wake Up (0) | 2024.10.22 |
---|---|
ESP32 Deep Sleep 구현하기 - Timer Wake Up (1) | 2024.10.21 |
ESP32 인터럽트(Interrupt) 구현하기 - PIR(인체감지센서) (2) | 2024.10.17 |
ESP32 Timer 구현하기 - millis()함수 사용하기 (4) | 2024.10.16 |
ESP32 ADC - 아날로그 값 읽기 (0) | 2024.10.16 |