요약
ESP32를 아두이노에서 deep sleep mode를 사용하여 전력관리 하는 방법에 대해서 알아보겠습니다.
Timer, Touch, External 3가지 방법이 있으며 이번 시간에는 ext0로 구현해 보겠습니다.
ext0는 해당 핀의 HIGH, LOW 값으로 제어한다고 생각하면 되겠습니다.
wokwi에서 deep sleep mode 사용하는 방법
wokwi에서 프로젝트 설정하는 방법은 ESP32 → 장치설정 → ESP32 웹에서 간단히 시뮬레이션 테스트 wokwi에서 확인하실 수 있습니다. (아래 링크로도 확인 가능합니다.)
wokwi에 접속해서 먼저 프로젝트를 생성합니다.
바로 SAVE 하셔서 deepsleepext 이름으로 지정해 줍니다.
Public으로 저장하시면 됩니다.(유료 결제하면 Private 할 수 있으나 그냥 Public으로 진행하는 게 좋습니다.
ext0 기능으로 deep sleep mode 코드 작성
ext0를 HIGH / LOW 기능이 필요하므로 버튼과 저항을 추가하겠습니다.
wokwi에서는 deep sleep mode가 정상적으로 확인하기가 어렵습니다.
자체 내부 회로를 소프트웨어로 기능적으로만 구현한 것이라고 생각됩니다.
※ 그래도 회로의 안정성을 위해 wokwi에서 먼저 구현하고 실제 보드로 진행하겠습니다.
(+) 버튼을 눌러서 그림과 같이 버튼과 저항을 추가합니다.
33번 핀에 버튼을 연결해 주고 3V3에 저항을 연결합니다.
이렇게 되면 GPIO 33번 핀은 항상 HIGH(1) 값을 가지고 버튼을 클릭하면 LOW(0) 값을 가지게 됩니다.
※ 나중에 배우겠지만 GPIO 33번은 내부 풀업이 있기에 저항을 추가 안 해줘도 setup에서 그림과 같은 기능을 구현할 수 있습니다.
아래의 코드를 복사 붙여 넣기 해서 실행하면 됩니다.
#define BUTTON_PIN_BITMASK 0x200000000 // 2^33 in hex
RTC_DATA_ATTR int bootCount = 0; // 딥 슬립 모드에서도 값이 유지되는 변수 설정
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);
++bootCount;
Serial.println("Boot number: " + String(bootCount)); // 부팅 번호 출력
print_wakeup_reason(); // 웨이크업 원인 출력
esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,0); //1 = High, 0 = Low
Serial.println("Going to sleep now");
esp_deep_sleep_start(); // 딥 슬립 모드로 진입
Serial.println("This will never be printed"); // 이 부분은 출력되지 않음
}
void loop(){
}
이제 시작을 눌러서 실행하면 됩니다.
wokwi에서는 소프트웨어로 구현한 것이라 내부 하드웨어를 구현이 안됩니다. (ULP, RTC Coprocessor 등)
그래서 계속 무한 재부팅됩니다.
잘못된 게 아니니까 그러려니 하시면 됩니다.
그림과 같이 계속 무한반복 됩니다만 뭐 이대로 진행합시다.
Wakeup was not caused by deep sleep : 0 ← 이 부분은 실제 보드에서 할 경우 Wakeup caused by external signal using RTC_IO 라고 표시가 뜹니다.
아두이노 세팅 및 코드 작성
ESP32를 아두이노 세팅하는 방법은 ESP32 → 장치설정 → ESP32 아두이노 2 설치를 찾아가셔도 되고 아래의 링크로도 확인 가능합니다.
[ESP32/장치설정] - ESP32 아두이노 2 설치
코드는 wokwi에서 사용한 코드 그대로를 복사 붙여 넣기 해주면 됩니다.
업로드하시고 결과를 확인하면 wokwi와는 다르게 boot number 숫자가 계속 증가합니다.
그리고 Wakeup caused by external signal using RTC_IO라고 타이머에 의해 깨어났다고 표시됩니다.
여기서 ESP32 개발보드 자체에 있는 reset 버튼을 누르면 어떻게 될까요?
이전 시간에 ESP32 deep sleep mode (Timer)에서 확인했지만 다시 확인해보겠습니다.
아래와 같이 버튼 형태로 RESET이라고 적혀 있는 걸 눌러보세요.
그림과 같이 Boot number가 2에서 1로 초기화되고 Wakeup was not caused by deep sleep : 0라고 표시됩니다.
deep sleep이 아닌 전원 파워를 리셋했기 때문입니다.
아래 그림과 같이 DEEPSLEEP_RESET으로 할 경우 boot numer가 증가하고 POWERON_RESET으로 할 경우 초기화가 됩니다.
deep sleep mode는 주 사용되는 CPU는 꺼지지만 초저전력(ULP) 코프로세서는 wake up에 필요한 센서 값을 읽는 중이므로 주 CPU를 깨울 수 있습니다.
그리고 주 CPU와 함께 주 메모리도 비활성화되어 코드 내에서 메모리에 저장된 값이 모두 삭제되고 접근할 수 없습니다.
하지만 RTC_DATA_ATTR int bootCount = 0 코드는 RTC 메모리를 활성 상태로 유지하므로 bootCount 값은 유지됩니다.
아래의 사이트를 참고하시면 deep sleep에 대해서 좀 더 자세히 알 수 있습니다.
이렇게 ESP32에서 ext0를 활용하여 deep sleep mode를 구현하는 방법을 배웠습니다.
전력소모가 active mode 일 때 wifi 사용하면 160~260mA를 소모합니다.
AA 건전지 2개 직렬로 연결하면 평균 2500mAh 이므로 active mode 사용하면 대략 10시간 사용 가능합니다.
하지만 deep sleep mode를 구현하여 필요할 때 잠깐 깨우면 10uA 소모로 대략 10,000시간 넘게 사용할 수 있습니다.
wifi 데이터 ID, PW를 RTC 메모리에 저장하고 켤 때마다 wifi 접속도 가능하니 모든 시스템에 적용할 수 있습니다.
개발하실 때 시스템의 배터리 용량에 맞게 전력관리를 적절히 해주시면 됩니다.
오늘도 긴 글 읽어주셔서 감사합니다!
'ESP32 > 장치설정' 카테고리의 다른 글
[아두이노] ESP32 deep sleep mode 전력관리 (ext1) (0) | 2024.03.10 |
---|---|
[아두이노] ESP32 deep sleep mode 전력 관리 (Timer) (0) | 2024.03.06 |
[아두이노] ESP32 Multi Thread 구현하는 방법 (easy RTOS) (2) | 2024.03.06 |
[아두이노] ESP32 MAC, CHIP ID, 고유 식별 값 읽는 방법 (3) | 2024.03.05 |
[아두이노] ESP32 웹에서 간단히 시뮬레이션 테스트 wokwi (2) | 2024.02.18 |