ESP32 Deep Sleep, using millis in Arduino IDE, and then trying to do something in between

knightridar
Posts: 32
Joined: Sun Nov 25, 2018 10:05 pm
Contact:

ESP32 Deep Sleep, using millis in Arduino IDE, and then trying to do something in between

Postby knightridar » Mon Jul 06, 2020 8:43 am

ESP32 Deep Sleep, using millis in Arduino IDE, and then trying to do something in between

I want to be able to take 4 analog readings and 1 I2C reading and then have the ESP32 go into deep sleep mode and wake up every 20 seconds or so, but right now I am keeping it simple just to try out the code where it prints "hello world" in between the deep sleep mode.

I want to do all this using millis instead of delay to avoid using blocking code.
I have the code below but I suspect that it's not printing "hello world" because the setup code puts the device to sleep before it can print. Any idea how I can get this working so that it's able to print and then go to sleep?

Code: Select all

/*

  Deep Sleep Timer Wake Up Example by Pranav Cherukupalli
  https://randomnerdtutorials.com/esp32-deep-sleep-arduino-ide-wake-up-sources/

*/

#include "esp32-hal-cpu.h"

#define uS_TO_S_FACTOR 1000000  /* Conversion factor for micro seconds to seconds */
#define TIME_TO_SLEEP  5        /* Time ESP32 will go to sleep (in seconds) */

RTC_DATA_ATTR int bootCount = 0;

uint32_t previousTime = 0;
uint32_t loopInterval = 3000; //milliseconds


void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);

  setCpuFrequencyMhz(40); //Set CPU clock to 40 MHz
  Serial.print(getCpuFrequencyMhz()); //Get CPU clock
  Serial.println();

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  //Print the wakeup reason for ESP32
  print_wakeup_reason();

  /*
  First we configure the wake up source
  We set our ESP32 to wake up every 5 seconds
  */
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  Serial.println("Setup ESP32 to sleep for every " + String(TIME_TO_SLEEP) +
  " Seconds");

  /*
  Next we decide what all peripherals to shut down/keep on
  By default, ESP32 will automatically power down the peripherals
  not needed by the wakeup source, but if you want to be a poweruser
  this is for you. Read in detail at the API docs
  http://esp-idf.readthedocs.io/en/latest/api-reference/system/deep_sleep.html
  Left the line commented as an example of how to configure peripherals.
  The line below turns off all RTC peripherals in deep sleep.
  */
  //esp_deep_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
  //Serial.println("Configured all RTC Peripherals to be powered down in sleep");

  /*
  Now that we have setup a wake cause and if needed setup the
  peripherals state in deep sleep, we can now start going to
  deep sleep.
  In the case that no wake up sources were provided but deep
  sleep was started, it will sleep forever unless hardware
  reset occurs.
  */
  Serial.println("Going to sleep now");
  Serial.flush(); 
  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}


void loop() {

  if ( millis() - previousTime > loopInterval )
  {
    previousTime = millis();

    Serial.print("hello world!");
   }
}

/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
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;
  }
}
Free CAD files for hobby and engineering projects:
https://grabcad.com/has-2

lbernstone
Posts: 829
Joined: Mon Jul 22, 2019 3:20 pm

Re: ESP32 Deep Sleep, using millis in Arduino IDE, and then trying to do something in between

Postby lbernstone » Mon Jul 06, 2020 9:33 pm

esp32 is not an arduino. Trying to count millis in your loop is far more likely to block your execution than any delay() call. If you want a timer, I would suggest using the Ticker library (https://github.com/espressif/arduino-es ... ies/Ticker). If you want something to happen before the sleep, then you need to have that code in the flow before you put the device into sleep.
If this does not help, then please read https://en.wikipedia.org/wiki/XY_problem

boarchuz
Posts: 606
Joined: Tue Aug 21, 2018 5:28 am

Re: ESP32 Deep Sleep, using millis in Arduino IDE, and then trying to do something in between

Postby boarchuz » Tue Jul 07, 2020 12:19 am

You're complicating it. Just do the readings and go back to sleep. There's practically nothing to be gained by even spinning up separate tasks.

Code: Select all

void setup() {
  Serial.begin(115200);
  analogRead x4
  i2c
  Serial.println("Going to sleep now");
  Serial.flush();
  esp_deep_sleep(TIME_TO_SLEEP * uS_TO_S_FACTOR);
}
void loop() {
  //don't put anything here
}
This is good if you want to learn more about FreeRTOS: https://www.freertos.org/FreeRTOS-quick ... guide.html

knightridar
Posts: 32
Joined: Sun Nov 25, 2018 10:05 pm
Contact:

Re: ESP32 Deep Sleep, using millis in Arduino IDE, and then trying to do something in between

Postby knightridar » Sat Jul 18, 2020 8:48 pm

Thanks.
I did what you said and put the flow of the deep sleep after reading 4 analog values and 1 I2C value.
Without using ESP-Now and just reading 1 analog value without smoothing the values I was able to get a reading and put it to sleep.

Since I'm using the ESP-Now protocol to transfer those values wirelessly, I'm getting another error.
My transmitter says "Failed to add peer" in the serial monitor.
I set my deep sleep time to 10 seconds on both the transmitter and receiver.
I tried to upload the code on both ESP-32 Pico-Kit modules at the same time.
I know for sure the analog values and I2C value are not appearing in Serial print port on both the transmitter side and receiver side.

Any ideas what could be wrong?
I thought millis is useful for multitasking?
I've read that using delay is not best practice so I wanted to familiarize myself with using millis and get use to it.

In this case I'm taking 64 samples of analog readings (for smoothing values) for 4 analog sensors and also 64 readings for an I2C IMU sensor.I want to take compass readings next so that will be the 2nd I2C value after calibrating it.

Since the code is really long I've summarized it a bit for transmitter side:
I basically have this embedded in my for loop

Code: Select all

variables declared before void setup
uint32_t previousTime = 0;
uint32_t loopInterval = 2000;

// Define the number of samples to keep track of. The higher the number, the
// more the readings will be smoothed, but the slower the output will respond to
// the input. Using a constant rather than a normal variable lets us use this
// data to determine the size of the readings array.
const uint8_t numReadings = 64;
const uint8_t numSensors = 4;
const uint8_t numSensorsFloat = 1;

// interval to stabilize analog input smoothing readings
// ADC1 Channel read time ~9.5µs per sample --> 64 readings x 9.5 = 608 µs = .608 ms
// period of 2000 ms above is long enough to take in readings mentioned above
uint8_t numReadingsInterval = 2;
uint32_t numReadingsStart = 0;

............
void setup code starts
.............

void loop starts
..............
declared variables 
multidimensional array for smoothing values
IMU code
........................

  if ( millis() - previousTime > loopInterval )
  {
    previousTime = millis();
....... serial print values of 4 analog sensors and 1 I2C command
........use esp now send value command
........// Send message via ESP-NOW
          esp_err_t result = esp_now_send(peerMacAddress, (uint8_t *) &outgoingReadings, sizeof(outgoingReadings));
  }
deep sleep code here
void loop finishes
Free CAD files for hobby and engineering projects:
https://grabcad.com/has-2

knightridar
Posts: 32
Joined: Sun Nov 25, 2018 10:05 pm
Contact:

Re: ESP32 Deep Sleep, using millis in Arduino IDE, and then trying to do something in between

Postby knightridar » Sat Jul 18, 2020 11:42 pm

So I also have another reason for using millis on both the transmitter and receiver side.
I used millis to slow down the output of the serial monitor readout so I can keep track of what is going on in the code.

Here is what is happening when I removed millis from both transmitter side and receiver side.
I only put the transmitter side to deep sleep.

The transmitter still says "failed to add peer"
However it also says "sent with success"
It only outputs a max 12 bit value (0-4095) with a range of 0-63 (when I place a phone light over it it refuses to go any higher than 63) when transmitting values.
This was not the case when I was using millis above.

I know a certain about of time is needed for 4 analog values and 64 readings each per sensor, plus 1 I2C values.
I based this calc based on a (9.5 us per reading) 16mhz arduino, but not sure what it is for ESP32.
https://knowledge.ni.com/KnowledgeArtic ... A2&l=en-US
Based on this article if I have 4 analog readings and 1 I2C reading.
I'm taking 64 samples (multisampling or smoothing)
https://docs.espressif.com/projects/esp ... s/adc.html
64 x 5 sensors = 320 readings
According to ESP_Puff sampling frequency for ESP32 ADC is 6khz
https://esp32.com/viewtopic.php?t=1075

So 1/T = 6000 / 320 = 18.75 --> T = .053 seconds ????
According to the NI website to analyze shape of signal you need freq. of at least 10 times the highest freq. component in setup.
To get accuracy in readings it needs to 2 times the highest freq. component in setup.
In my case I don't think it's necessary, I'm just reading sunlight signals from a photodiode and angle position.
Even if I use 10x I get a value of T = .533 seconds

Code: Select all

rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 188777542, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:8896
load:0x40080400,len:5816
entry 0x400806ac

CPU Frequency is: 80 Mhz
Mac Address in Station: xx:A0:1D:xx:xx:xx
ESPNow Init Success
Failed to add peer
AzimuthClockWise: 63
AzimuthCounterClockWise: 63
ElevationClockWise: 63
ElevationCounterClockWise: 63
ElevationAngle: 0.11
Sent with success
Wakeup caused by timer

Last Packet Send Status:	Delivery Success
Setup ESP32 to sleep for every 10 Seconds
Going to sleep now
Free CAD files for hobby and engineering projects:
https://grabcad.com/has-2

knightridar
Posts: 32
Joined: Sun Nov 25, 2018 10:05 pm
Contact:

Re: ESP32 Deep Sleep, using millis in Arduino IDE, and then trying to do something in between

Postby knightridar » Sun Jul 19, 2020 5:39 am

Well I solved the issue of my values updating successfully and being able to keep my serial readout at a pace that I wanted to read/transfer it at.

I added these variables before void setup:

uint32_t previousTime1 = 0;
uint32_t deepsleepInterval = readingsInterval + 100;

Then I added my deepsleep code inside of this millis function

Code: Select all

  if ( millis() - previousTime1 > deepsleepInterval )
  {
    previousTime1 = millis();

  .....code....
  }
Free CAD files for hobby and engineering projects:
https://grabcad.com/has-2

Who is online

Users browsing this forum: brebisson and 68 guests