본문 바로가기
ESP32/ESP32

ESP32 Deep Sleep 구현하기 -Touch Wake Up

by 빈이쥬 2024. 10. 22.

ESP32를 Deep Sleep Mode에서 터치 핀을 사용하여 깨우는 방법을 알아보겠습니다.

 

Touch Wake Up

Touch Wake Up 활성화

touchSleepWakeUpEnable(TOUCH_PIN, THRESHOLD);
 

코드

Arduino IDE를 열고, File > Examples > ESP32 Deep Sleep로 이동하여 TouchWakeUp 스케치를 엽니다.

 

#if CONFIG_IDF_TARGET_ESP32
#define THRESHOLD 40   /* 값이 클수록 민감도 증가 */
#else                  //ESP32-S2 및 ESP32-S3 + 다른 칩에 대한 기본값 (조정 필요)
#define THRESHOLD 5000 /* 값이 작을수록 민감도 증가 */
#endif

RTC_DATA_ATTR int bootCount = 0;
touch_pad_t touchPin;
/*
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;
  }
}

/*
ESP32가 수면에서 깨어난 터치패드를 출력하는 메서드
*/
void print_wakeup_touchpad() {
  touchPin = esp_sleep_get_touchpad_wakeup_status();

#if CONFIG_IDF_TARGET_ESP32
  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;
  }
#else
  if (touchPin < TOUCH_PAD_MAX) {
    Serial.printf("Touch detected on GPIO %d\n", touchPin);
  } else {
    Serial.println("Wakeup not by touchpad");
  }
#endif
}

void setup() {
  Serial.begin(115200);
  delay(1000);  // Serial 모니터를 열기 위해 잠시 대기합니다.

  // 부트 번호를 증가시키고 매 재부팅 시 출력합니다.
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  // ESP32의 웨이크업 원인과 터치패드도 출력합니다.
  print_wakeup_reason();
  print_wakeup_touchpad();

#if CONFIG_IDF_TARGET_ESP32
  // 터치 패드 3 + 7 (GPIO15 + GPIO 27)에서 수면 웨이크업 설정
  touchSleepWakeUpEnable(T3, THRESHOLD);
  touchSleepWakeUpEnable(T7, THRESHOLD);

#else  //ESP32-S2 + ESP32-S3
  // 터치 패드 3 (GPIO3)에서 수면 웨이크업 설정
  touchSleepWakeUpEnable(T3, THRESHOLD);

#endif

  // 이제 잠에 들어갑니다.
  Serial.println("Going to sleep now");
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

void loop() {
  // 이 함수는 호출되지 않습니다.
}

 

임계값 설정

터치 핀의 임계값을 설정합니다. 

#if CONFIG_IDF_TARGET_ESP32
#define THRESHOLD 40   /* 값이 클수록 민감도 증가 */
#else                  //ESP32-S2 및 ESP32-S3 + 다른 칩에 대한 기본값 (조정 필요)
#define THRESHOLD 5000 /* 값이 작을수록 민감도 증가 */
#endif
 

터치 핀에서 읽은 값은 터치할 때 감소합니다. 임계값은 터치 핀에서 읽은 값이 40 이하일 때 ESP32가 깨어나도록 설정합니다.

원하는 민감도에 따라 이 값을 조정할 수 있습니다.

중요: ESP32-S2 또는 ESP32-S3 모델을 사용하는 경우, 방식이 약간 다르게 작동합니다. 그래서 코드에서 이 보드를 위한 다른 임계값을 정의하는 섹션이 있습니다. 이 경우, 값이 낮을수록 민감도가 증가합니다.


Wake Up 터치 핀 설정

터치 핀을 웨이크업 소스로 설정하려면, 터치 핀과 보드를 깨우는 임계값을 인수로 받아들이는 touchSleepWakeUpEnable() 함수를 사용할 수 있습니다.

#if CONFIG_IDF_TARGET_ESP32
  // 터치 패드 3 + 7 (GPIO15 + GPIO 27)에서 수면 웨이크업 설정
  touchSleepWakeUpEnable(T3, THRESHOLD);
  touchSleepWakeUpEnable(T7, THRESHOLD);

#else  //ESP32-S2 + ESP32-S3
  // 터치 패드 3 (GPIO3)에서 수면 웨이크업 설정
  touchSleepWakeUpEnable(T3, THRESHOLD);

#endif

GPIO 15 (T3)와 GPIO 27 (T7)을 동일한 임계값으로 웨이크업 소스로 설정합니다.

 
 

 

 
 
각 코드에 대해서 자세히 설명해 보겠습니다. 
 

bootCount: RTC(Real-Time Clock) 메모리에 저장되는 부트 카운터로, ESP32가 재부팅될 때마다 증가합니다.

touchPin: 터치패드의 상태를 저장하는 변수입니다.

RTC_DATA_ATTR int bootCount = 0;
touch_pad_t touchPin;

 

 

웨이크업 원인 출력 함수:

esp_sleep_get_wakeup_cause() 함수를 호출하여 ESP32가 깨어난 원인을 가져옵니다.

switch 문을 사용하여 각 원인에 대해 적절한 메시지를 출력합니다. 예를 들어, 외부 신호, 타이머, 터치패드, ULP(ultra-low power) 프로그램 등으로 깨어날 수 있습니다.

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

터치패드 웨이크업 상태 출력 함수:

esp_sleep_get_touchpad_wakeup_status()를 호출하여 터치패드의 상태를 확인합니다.

ESP32의 경우 switch 문을 사용하여 특정 GPIO 핀에서 감지된 터치를 출력합니다. 다른 ESP32 버전에서는 범위를 확인하여 터치 감지가 이루어졌는지 확인합니다.

void print_wakeup_touchpad() {
  touchPin = esp_sleep_get_touchpad_wakeup_status();

#if CONFIG_IDF_TARGET_ESP32
  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;
  }
#else
  if (touchPin < TOUCH_PAD_MAX) {
    Serial.printf("Touch detected on GPIO %d\n", touchPin);
  } else {
    Serial.println("Wakeup not by touchpad");
  }
#endif
}

 

초기화 함수:

Serial 통신을 시작하고, 1초 지연 후 Serial 모니터를 열기 위한 대기 시간을 설정합니다.

void setup() {
  Serial.begin(115200);
  delay(1000);  // Serial 모니터를 열기 위해 잠시 대기합니다.

 

 

부트 카운트 증가:

부트 카운트를 증가시키고, 현재 부트 번호를 출력합니다.

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

웨이크업 원인 출력:

이전에 정의한 두 함수 호출을 통해 ESP32의 웨이크업 원인과 터치패드 상태를 출력합니다.

  print_wakeup_reason();
  print_wakeup_touchpad();

 

터치패드 웨이크업 설정:

ESP32의 경우 T3와 T7 터치패드에서 웨이크업을 허용하고, 다른 ESP32 버전에서는 T3에서만 웨이크업을 허용합니다. touchSleepWakeUpEnable 함수는 터치패드를 웨이크업 소스로 설정하는 함수입니다.

#if CONFIG_IDF_TARGET_ESP32
  touchSleepWakeUpEnable(T3, THRESHOLD);
  touchSleepWakeUpEnable(T7, THRESHOLD);

#else  //ESP32-S2 + ESP32-S3
  touchSleepWakeUpEnable(T3, THRESHOLD);

#endif

 

 

 수면 모드 진입:

ESP32를 깊은 수면 모드로 전환합니다. 이 후의 출력은 실행되지 않으며, 마이크로컨트롤러가 수면에 들어갑니다.

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

회로도

이 예제를 테스트하려면, GPIO 15에 케이블을 연결합니다. 아래의 회로도와 같이 연결합니다.

터치 웨이크업 신호 회로 배선

ESP32-S2 또는 ESP32-S3 모델을 사용하는 경우, 터치 핀의 위치를 확인하세요.

 

테스트

코드를 업로드한 후 Serial Monitor를 열고 보드가 수면 상태에 들어가고 다시 깨워질 때 Serial Monitor의 출력 결과를 확인하세요. 이 출력을 통해 웨이크업의 작동을 확인할 수 있습니다.