2023年7月26日 星期三

ESP32 Deep Sleep and Wake-up

Purpose:

利用電池整合的ESP32產品, 因為 WiFi 跟 Bluetooth都在動作, 所以電池電量很快就耗盡. 所以就決定試看看用深度睡眠模式(Deep Sleep mode)的方式來減少運行的功耗, 再利用GPIO外部喚醒方式來運作. 

Using the ESP32 product integrated with the battery, because the WiFi and Bluetooth are both active, the battery power will be exhausted soon. So I decided to try to use the Deep Sleep mode to reduce the power consumption of the operation, and then use the GPIO External wake-up mode to operate.


ESP32有基本的sample範例

 esp_sleep_wakeup_cause_t wakeup_reason;

 wakeup_reason = esp_sleep_get_wakeup_cause();

 esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1); //1 = High, 0 = Low



注意只有橘色RTC_GPIO可以當作外部觸發的腳位, 因為Deep_sleep_mode 只有RTC memory跟RTC周邊還在工作
Fundamental:
ESP32 Deep Sleep Mode
In this mode, only two of the seven main ESP32 parts remain active and the rest are deactivated. These two parts are:
1 Ultra Low Power Coprocessor (ULP Coprocessor) 
2 timer (RTC)

Power consumption compare table


The table below details the power modes

Circuit:

Code Introduce:
//--------- Flag structure --------------------------------------
typedef struct _vFlag
{
  uint8_t BTFlag = 0;
  uint8_t CANFlag = 0;
  uint8_t I2C_Flag = 0;
  uint8_t BMP180Flag = 0;
  uint8_t LEDFlag = 1;
  uint8_t sensor_Flag = 0;
  uint8_t initial_Flag = 0;
  uint8_t FunctionFlag = 3;
  uint8_t SendFlag = 0;
  uint8_t LEDCnt = 0;
  uint8_t Wakeup = 0;
} vFlag;
vFlag *flag_Ptr;
vFlag flag;
//----------uart--------------
#define LINE_BUFFER_LENGTH 64
//--------- uart structure --------------------------------------
typedef struct _vUart
{
  char c;
  int lineIndex = 0;
  int line1Index = 0;
  int BTlineIndex = 0;
  bool lineIsComment;
  bool lineSemiColon;
  //char *line;
  char line[128];
  //char line1[128];
  char BTline[20];
  //char R_line[20];
  //char L_line[20];
  String inputString;
  String BTinputString;
  String S1inputString;
  int V[16];
  char ctemp[30];
  char I2C_Data[80];
  int DC_Spped = 50;
  float Voltage[16];
  int Buffer[128];
  int StartCnt = 0;
  int ReadCnt = 0;
  int sensorValue = 0;
} vUart;
vUart *Uart_Ptr;
vUart Uart;
//---------------------------------------------------
#define LED_BUILTIN 2
//#define WAKE_UP_PIN 33
int buttonpin = 33;

//-------------------------------------------------
void setup()
{
  Serial.begin(9600);
  Serial.println(F("init"));
  pinMode(LED_BUILTIN, OUTPUT);
  //pinMode(buttonBpin, INPUT_PULLDOWN);

  esp_sleep_wakeup_cause_t wakeup_reason;
  wakeup_reason = esp_sleep_get_wakeup_cause();
  esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1); //1 = High, 0 = Low

  //Serial.println("esp_deep_sleep_start");
  //esp_deep_sleep_start();
}
//-----------------------------------------
void loop()
{
 
  Serial.print(F("Main at core:"));
  Serial.println(xPortGetCoreID());
  while(1)
  {
    if (digitalRead(buttonpin) == HIGH)
    {
      flag.LEDCnt=0;
      Serial.println("esp_wake_up");
      Serial.println("LED flash");
    }
    //---------------------------------------------
    if(flag.LEDFlag == 1)
    {
      digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
      vTaskDelay(300);
      digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
      vTaskDelay(300);

      if(flag.LEDCnt !=20)
      {
        flag.LEDCnt++;
        Serial.print(flag.LEDCnt);
        Serial.print("--");
        Serial.println("esp_no_sleep");
      }
      else
      {
        Serial.println("esp_deep_sleep_start");
        esp_deep_sleep_start();
      }
     
    }
    while (Serial.available() > 0)
    {
      Uart.c = Serial.read();

      if ((Uart.c == '\n') || (Uart.c == '\r'))
      { // End of line reached
        if (Uart.lineIndex > 0)
        { // Line is complete. Then execute!
          Uart.line[Uart.lineIndex] = '\0'; // Terminate string
          //Serial.println( F("Debug") );
          //Serial.println( Uart.inputString );
          processCommand(Uart.line); // do something with the command
          //傳輸給藍芽
         
          Uart.lineIndex = 0;
          Uart.inputString = "";
        }
        else
        {
          // Empty or comment line. Skip block.
        }
        Uart.lineIsComment = false;
        Uart.lineSemiColon = false;
        Serial.println(F("ok>"));
      }
      else
      {
        //Serial.println( c );
        if ((Uart.lineIsComment) || (Uart.lineSemiColon))
        {
          if (Uart.c == ')')
            Uart.lineIsComment = false; // End of comment. Resume line.
        }
        else
        {
          if (Uart.c == '/')
          { // Block delete not supported. Ignore character.
          }
          else if (Uart.c == '~')
          { // Enable comments flag and ignore all characters until ')' or EOL.
            Uart.lineIsComment = true;
          }
          else if (Uart.c == ';')
          {
            Uart.lineSemiColon = true;
          }
          else if (Uart.lineIndex >= LINE_BUFFER_LENGTH - 1)
          {
            Serial.println("ERROR - lineBuffer overflow");
            Uart.lineIsComment = false;
            Uart.lineSemiColon = false;
          }
          else if (Uart.c >= 'a' && Uart.c <= 'z')
          { // Upcase lowercase
            Uart.line[Uart.lineIndex] = Uart.c - 'a' + 'A';
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += (char)(Uart.c - 'a' + 'A');
          }
          else
          {
            Uart.line[Uart.lineIndex] = Uart.c;
            Uart.lineIndex = Uart.lineIndex + 1;
            Uart.inputString += Uart.c;
          }
        }
      }
    } //while (Serial.available() > 0)
  }
}
//----------------------------------------
void processCommand(char *data)
{
  int len, xlen, ylen, zlen, alen;
  int tempDIO;
  String stemp;

  len = Uart.inputString.length();
  //---------------------------------------
  if (strstr(data, "VER") != NULL)
  {
    Serial.println(F("ESP32_20230726"));
  }
}
//-----------------------------------------
YouTube Demonstration:


3 則留言: