espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.79k stars 7.31k forks source link

ESP NOW current consumption (IDFGH-3015) #5044

Closed sagar448 closed 4 years ago

sagar448 commented 4 years ago

Environment

Problem Description

I have a custom board with an esp32 chip. Everything is working perfectly except for the current consumption of the ESP NOW protocol. It says that the current is meant to be 60ma maximum, whereas the chip is drawing 90ma! This is too much, how would I be able to solve this?

Alvin1Zhang commented 4 years ago

@sagar448 Thanks for reporting, we will look into. Thanks.

sagar448 commented 4 years ago

@Alvin1Zhang Thanks for the reply Alvin, is there something I can do on my end? The problem is that espressif does not have one location where it states everything that can be turned on or off to reduce power consumption. Is there some functions you know I can use to turn on or off to reduce the power consumption? Thanks!

Alvin1Zhang commented 4 years ago

@sagar448 Thanks for the follow-up. May need your help to understand I have a custom board with an esp32 chip, here, does the custom board refer to ESP32-DevKitC-V4 or any other board? If other board, would you please help share the name of the board? Thanks.

ArnieO commented 4 years ago

I see the same. I am testing ESP-NOW using the transmitter code from https://randomnerdtutorials.com/esp-now-esp32-arduino-ide/ I run it on a barebone ESP32-WROOM module without any other circuits. Continuous current consumption 88 mA (at 160 MHz). Note: I use Arduino IDE, but since I found the same issue in this forum, this is maybe inherited?

sagar448 commented 4 years ago

Hello @Alvin1Zhang

The custom board is essentially a esp32-wroom-32D soc module. On a custom PCB.

@ArnieO I think your issue maybe related to running the esp32 full out right ...if you were on IDF you can turn off certain features, lowering the power consumption.

ArnieO commented 4 years ago

@sagar448 thank you for the follow-up ! I had difficulties finding good example code that demonstrates low consumption using ESP-NOW.

But I have made good progress now, and found that the key is to de-initialize ESP-NOW at the transmitter side as soon as the message is sent. This cuts the consumption down to 21/28 mA (CPU at 80/160 MHz), measured on a barebone ESP32-WROOM module. I measured the total transmit duration (including initialization and de-initialization) to be 31-33 ms (mostly 32 ms).

If the application allows, a Light Sleep cycle (either timed or using ext0/ext1 wakeup) enables reducing the consumption to below 1 mA.

This is my test code for the transmitter:

/*
  ESP32 ESP-NOW transmit with Light sleep 
  ***************************************

  Made by: https://github.com/ArnieO 
  Modified from: https://www.youtube.com/watch?v=cIKX19esGQU

  Code can be used to test alternatives:
  - Timed light sleep (5 sec)
  - External wake light sleep, ext0 (Push Button to GPIO 33 pulled down with a 10K Ohm resistor and a 100 nF cap for debounce)
  - 5 second delay (no sleep)

  Choose option by commenting out code.

*/
#include <WiFi.h>
#include <esp_now.h>

// Make a pulse in this GPIO to trigger oscilloscope after wakeup from Light sleep
#define OSCPIN 17

// static uint8_t broadcastAddress[] = { 0xC4, 0x4F, 0x33, 0x2F, 0xF3, 0x91 };   //ESP-NOW receiver MAC adr. Targeting one specific receiver
static uint8_t broadcastAddress[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };   //ESP-NOW receiver MAC adr. Using FF's enables multiple receivers.
long wakeTimeMillis, sleepTimeMillis;

//Structure for storing 250 bytes including zero termination
char payload[250];

static void msg_send_cb(const uint8_t* mac, esp_now_send_status_t sendStatus)
{
  switch (sendStatus)
  {
    case ESP_NOW_SEND_SUCCESS:
      Serial.println("Send success"); break;
    case ESP_NOW_SEND_FAIL:
      Serial.println("Send Failure"); break;
    default:
      break;
  }
}

esp_now_peer_info_t peerInfo;

void setup() {
  wakeTimeMillis = esp_timer_get_time() / 1000;
  setCpuFrequencyMhz(160);
  Serial.begin(115200);

  WiFi.mode(WIFI_STA);

  Serial.println();
  Serial.print("My MAC-address: ");
  Serial.println(WiFi.macAddress());

  // Register peer info
  memcpy(peerInfo.peer_addr, broadcastAddress, sizeof(broadcastAddress));
  peerInfo.channel = 0;
  peerInfo.encrypt = false;

  // Oscilloscope trigger pin
  pinMode(OSCPIN, OUTPUT);

  //Initialize payload char array (Dummy string)
  for (int i = 0; i < 249; i++) {
    payload[i] = random(65, 90);  // [A .. Z]
  }
  payload[249] = 0; // Zero termination

}

void loop() {
  //(Re-)initialize ESP-NOW
  WiFi.mode(WIFI_STA);
  if (esp_now_init() != ESP_OK) {
    Serial.println("ESP_ERR_ESPNOW_INTERNAL");
  }
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add peer");
    return;
  }

  // Set up callback function
  if (esp_now_register_send_cb(msg_send_cb) != ESP_OK)
  {
    Serial.println("Could not register send callback");
  }

    //send data (payload array)
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &payload, sizeof(payload));

  if (result != ESP_OK) {
    Serial.print("esp_now_send() failed, error code: 0x");
    Serial.println(result, HEX);
  }

  // Prepare for sleep
  delay(10); //Short delay to finish transmit before esp_now_deinit()
  if (esp_now_deinit() != ESP_OK) {   //De-initialize ESP-NOW. (all information of paired devices will be deleted)
    Serial.println("esp_now_deinit() failed");
  }
  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);

  // Light sleep
  //************************************************************************
  sleepTimeMillis = esp_timer_get_time() / 1000;
  Serial.print("Light sleep start after having worked for ");
  Serial.print(sleepTimeMillis - wakeTimeMillis);
  Serial.println(" ms.");
  delay(10); //Short delay to finish Serial.println before sleep
  esp_sleep_enable_timer_wakeup(5000000); //5 seconds               // Use this line for timed Light Sleep 5 seconds
  //esp_sleep_enable_ext0_wakeup(GPIO_NUM_33,1); //1 = High, 0 = Low    // Use this line for external wake (ext0) using GPIO33
  esp_light_sleep_start();
  Serial.println();
  Serial.println("Light sleep end");
  wakeTimeMillis = esp_timer_get_time() / 1000;
  //Oscilloscope pin pulse after wakeup
  digitalWrite(OSCPIN, 1);
  delay(10);
  digitalWrite(OSCPIN, 0);
  //************************************************************************/

  //delay(5000);  //Use this line in stead of above section to make 5 seconds delay in stead of Light sleep

}
zhangyanjiaoesp commented 4 years ago

@ArnieO Yes, you are right. If the ESP-NOW device just send data, de-initialize ESP-NOW at the transmitter side as soon as the message is sent will cut the current consumption. Light sleep will also help.

@ArnieO @sagar448 For more infomation, you can refer to the docs for power management https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/power_management.html

Alvin1Zhang commented 4 years ago

Thanks for reporting, feel free to reopen.