XIAO ESP32S3 Deep Sleep cannot wake up after random cycles

I’m using deep sleep to wake up xiao esp32s3 and send some data from sensor via lora every 300 seconds. But after random power cycles, xiao esp32s3 will stop working and cannot wake up anymore, no matter how long I wait. I powered it with battery, and there is still sufficient voltage (4v). Here is my code, any ideas?

#include <Wire.h>
#include "esp_sleep.h"
// #include "driver/rtc_io.h"
#include "config.h"

#define PD_PIN GPIO_NUM_3
#define I2C_ADDR 0x6D

float pressure;  // celsius
float temperature;  // gauge pressure in kPa

void setup() {
  // turn on debug led
  // pinMode(LED_BUILTIN, OUTPUT);
  // digitalWrite(LED_BUILTIN, LOW);
  
  // add watch dog
  esp_task_wdt_deinit();
  esp_task_wdt_init(&wdt_config);
  esp_task_wdt_add(NULL);

  // turn on sensor
  // rtc_gpio_deinit(PD_PIN);
  pinMode(PD_PIN, OUTPUT);
  digitalWrite(PD_PIN, LOW);
  Wire.begin();
  delay(5);

  // default interval
  uint32_t uplinkIntervalSeconds = 300UL;

  // init lora
  radio.begin();
  radio.setRfSwitchPins(38, RADIOLIB_NC);
  node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
  node.activateOTAA();
  node.setDwellTime(true, 400);

  // collect data
  uint8_t reg[0xD0] = {0};  
  if (readRegisters(0x00, reg, sizeof(reg))) {
    processSensorData(reg);
  }

  // package data
  uint8_t temperature_est = (uint8_t)(temperature + 128);
  uint16_t pressure_est = (pressure > 0) ? (uint16_t)pressure : 0;
  uint8_t uplinkPayload[3];
  uplinkPayload[0] = temperature_est;
  uplinkPayload[1] = highByte(pressure_est);
  uplinkPayload[2] = lowByte(pressure_est);
  
  // send data
  if (node.sendReceive(uplinkPayload, sizeof(uplinkPayload)) != RADIOLIB_ERR_NONE) {
    uplinkIntervalSeconds = 60UL;
  };
  
  // sleep
  radio.sleep();
  esp_sleep_enable_timer_wakeup(uplinkIntervalSeconds * 1000000UL);
  esp_deep_sleep_start();
}

void loop() {}

bool readRegisters(uint8_t startAddr, uint8_t *data, uint8_t length) {
  Wire.beginTransmission(I2C_ADDR);
  Wire.write(startAddr);
  if(Wire.endTransmission() != 0) {
    return false;
  }
  
  Wire.requestFrom(I2C_ADDR, length);
  for(int i=0; i<length && Wire.available(); i++) {
    data[i] = Wire.read();
  }
  return true;
}

void processSensorData(uint8_t *Reg) {
  // pressure data
  int32_t pdata = (((uint32_t)Reg[0x06] << 16) | 
                 ((uint32_t)Reg[0x07] << 8) | 
                  Reg[0x08]) & 0xFFFFFF;
  if(Reg[0x06] & 0x80) pdata |= 0xFF000000;

  // temperature data
  int32_t tdata = (((uint32_t)Reg[0x09] << 16) | 
                 ((uint32_t)Reg[0x0A] << 8) | 
                  Reg[0x0B]) & 0xFFFFFF;
  if(Reg[0x09] & 0x80) tdata |= 0xFF000000;

  // calc temp in C
  temperature = (float)tdata / 65536.0 + 25.0;

  uint8_t decimal_places = (Reg[0xCF] >> 5) & 0x07;
  int16_t rangeL_raw = (Reg[0xC5] << 8) | Reg[0xC6];
  int16_t rangeH_raw = (Reg[0xC7] << 8) | Reg[0xC8];
  
  float rangeL = (float)rangeL_raw / pow(10, decimal_places);
  float rangeH = (float)rangeH_raw / pow(10, decimal_places);

  // calc pressure in MPa
  pressure = (rangeH - rangeL) * 
          ((float)(pdata - 8388608 * 0.1) / (8388608 * 0.8)) + 
           rangeL;

  // MPa to kPa
  pressure *= 1000;
}

Hi there,

So I see the GPIO 3 is what you are using and on the S3 that pin likes to be floating on Boot or it thinks its in JTAG mode. Can you try with a different pin and post a picture of the connections ?

HTH
GL :slight_smile: PJ :v:

strapping pins for the S3 a GPIO 0, 3, 45, 46 avoid using those when possible or be sure of there state when booting! :+1:

Thanks for your advice! I will change PD to GPIO 4 and see if it works. Here is my current connections:

Blue: PD ↔ GPIO3 (LOW enables sensor, HIGH disables sensor)
Green: SDA
Yello: SDL
Red: 3v3
Black: GND

Hi there,

I assembled 4 sets and tested them for 8 days. 2 of 4 worked 8 days without any problem. But other 2 sets stopped working in day 2 and never woke up. They have same code (except devEUI) and same connections (PD is connected to GPIO 4).

I also measured voltage. The voltage of batteries in worked esp32s3 dropped from 4.2v to 3.6v after 8 days. However, the voltage of batteries in other 2 stuck esp32s3 is only 2v, which means 0% left.

Do you have any ideas what is happening? What state are these stuck esp32s3 in? Why are they draining power without executing code?

Thanks,
TiSpH

Hi there,

SOunds like something is getting Stuck on. I would try and use an LED (RGB) and indicated states when a timer or Watchdog times out in transmit routines, or where there is a waiting in the loop. Once the condition get’s bellow a certain SOC on the ESP it just keeps flailing in either transmit or rebooting constantly (use an LED and do you track the battery SOC in the code to avoid trying on a low or near low battery)?

HTH
GL :slight_smile: PJ :v:

Does your device sensors require a warm-up time ?

Hello PJ_Classo,

I keep the led on between wakeup and sleep (immediately after wakeup and automatically off when sleep is called). Normally the led will be on for ~4 seconds and then go to sleep with the esp. But it doesn’t light up when it’s stuck (still enough battery voltage at this point). It looks like no code is executed but power is wasted.

My sensor has a very short warm-up time and I added delay(5) in the code.

I think the esp goes into some kind of wait state, like the JTAG mode you mentioned before. How do I determine the state?

Thanks,
TiSpH

Hi there,

Ok, Well that’s smart and good going using the LED. :+1:
Check the Strapping pins Section of the Technical reference guide.
Sounds like that to me also. Maybe switch pins and see if it behaves the same way.

Your on it though, so you get it.

HTH
GL :slight_smile: PJ :v:

Worse case and no pin switch is possible, there a fuse bits to ONE time BURN and it will disable the Jtag and only work with USB. SO read all of it. :stuck_out_tongue_winking_eye: