Xiao ESP32S3 & SX1262 - Deep Sleep Current problem

I recently received my my Xiao ESP32S3 & SX1262 combo. I’m using it for a lora P2P battery powered project. The lora side all worked as expetced. However I had issues with Deep Sleep current usage. Using the following code to test.
First,

  • I used a bench supply @3.8V connect to the battery pads on the underside of the ESP32S3 in series with an ampmeter.
  • I removed the lora sx1262 module connected via the B2B connector
  • Current reading 15.9 micro amps - all good!
    Next,
    I replaced the lora sx1262 into the B2B connector. The current reading in deep sleep is 2.2mA. Too high for sustainable battery use.

Effectively I’ve ruled out the green led and it’s external pull down resistor and the External switch on GPIO1 as the issue. As the ESP only draws 15.9Micro Amps. The issues is the excessive current draw, when the sx1262 is in circuit.
Grateful for any input

#include "driver/rtc_io.h"
#include <RadioLib.h>

#define USE_EXT0_WAKEUP          1               // 1 = EXT0 wakeup, 0 = EXT1 wakeup
#define WAKEUP_GPIO              GPIO_NUM_1     // Only RTC IO are allowed - ESP32 Pin example
RTC_DATA_ATTR int bootCount = 0;

// Pins number for SX1262 Chip
#define LORA_MISO 8
#define LORA_SCK 7
#define LORA_MOSI 9
#define LORA_CS 41  //NSS
#define LORA_DIO2 38
#define LORA_DIO1 39  // irq
#define LORA_RESET 42
#define LORA_BUSY 40

const uint8_t greenLed = 6;

void setup() {
  Serial.begin(115200);
  delay(1000);  //Take some time to open up the Serial Monitor

  ++bootCount;
  Serial.print("Boot number");
  Serial.println(bootCount);
  delay(500);
  pinMode(greenLed, OUTPUT);
  digitalWrite(greenLed, HIGH);
  delay(500);
  digitalWrite(greenLed, LOW);

  SX1262 radio = new Module(LORA_CS, LORA_DIO1, LORA_RESET, LORA_BUSY);

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

  rtc_gpio_pullup_dis(WAKEUP_GPIO);
  rtc_gpio_pulldown_en(WAKEUP_GPIO);

  //Go to sleep now
  Serial.println("Putting Radio to Sleep");
  radio.sleep();

  Serial.println("Going to sleep now");
  esp_deep_sleep_start();
}
void loop() {
  
}
4 Likes

I believe RadioLib library supports the function sleep(). You might want to check it out.

Yes. I’ve got radio.sleep() in the code posted.
I’ve had some success by externally pulling NSS high with a 10K resistor. I’m yet to fully test it but the current in deep sleep is now 20 micro amps.
Interesting, removing radio.sleep() raises the current usage to 330mA in deep sleep. Cheers

1 Like

HI there,

And Welcome here…

So looks like that was the issue, and can be marked as the solution by @msfujino , please do. Also please edit the Posts and use the Code tags " </> " above , just paste it in there. Makes it easier to read and allows others to find it fast. 20uA. is pretty stellar iMO :grin: :+1:

What is the distance your getting , If I may ask?
Sounds good any Sensors?

HTH
GL :slight_smile: PJ :v:

Thanks PJ.
Sorted the formatting.
The application only requires a distance of 200mtrs, up and over a hill. It performs very reliably for such a low cost mcu and radio.

1 Like

Hi there,

That’s Awesome, And thanks for the contribution, Seems the Lora stuff is getting a foot hold so that is good Stuff… :+1:

GL :slight_smile: PJ :v:

Solution - Pin 41 on the XIAO ESP32S3 connects to NSS on the SX1262 via the B2B connector (sense) . The pin is active LOW for Chip Select (CS/NSS) it needs to be held high via a 10K ohn resistor. Pin 41 isn’t physically accessable on the ESP32S3. So if you couple the boards together via the B2B connector the only way to hold it high is solder a lead from NSS on SX1262 to 3v3 via 10K resistor.
It’s only an issue if you want to achive ~20uA Deep Sleep current.
Hope that helps someone !

I have measured the sleep current and there is a phenomenon that I do not understand.
After executing radio.sleep(), wait 5 seconds and then execute esp_deep_sleep_start(), but it appears that radio is not sleeping during these 5 seconds. When S3 sleeps, the overall sleep current is 10uA, as expected.

The module I am using is slightly different from the one you are using, but the basic operation should be the same.
I am applying 3.8V to the S3 battery pad and measuring at ppk2.

//----------------------------------------------------------------------------------------------
//Board Library : esp32 by Espressif 3.2.0
//Board Select  : XIAO_ESP32S3
//----------------------------------------------------------------------------------------------
#include <RadioLib.h>

#define LORA_DIO1   D1
#define LORA_RESET  D2
#define LORA_BUSY   D3
#define LORA_CS     D4    // 3.3k pullup
#define LORA_RFSW   D5

SX1262 radio = new Module(LORA_CS, LORA_DIO1, LORA_RESET, LORA_BUSY);

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  delay(500);
  digitalWrite(LED_BUILTIN, HIGH);

  radio.begin(922.6, 125.0, 12, 5, 0x12, 13, 8, 1.7, 0);  // need radio.begin(), example parameters
  radio.sleep();
  delay(5000);                                            // 3.8V battery current = 34mA

  esp_sleep_enable_ext0_wakeup(GPIO_NUM_1, LOW);
  esp_deep_sleep_start();                                 // 3.8V battery current = 10uA
}

void loop() {}

1 Like

Geez I need to get a ppk2. Looks like it makes life easier!
Not sure what’s going on there. A couple of observations:

  • I’d try putting a delay between radio.begin() and radio.sleep() maybe the radio is in an indeterminate state when sleep() is called?
  • 3.3k Ohm pull up may be a bit strong. Although it obviously works
  • Is there a reason for the delay(5000) post radio.sleep() ?
    Anyway, deep sleep current looks fine

It is 5 seconds to measure the current when only SX1268 sleeps
.

I’d try putting a delay between radio.begin() and radio.sleep() maybe the radio is in an indeterminate state when sleep() is called?

Putting delay() has no effect.

I will do some more research.

EDIT:
Since the current of radio is as small as 1 mA compared to the 30 mA of S3 current, the current just seemed to change very little when
radio.sleep() was executed.

Thanks @Graeme for this solution, I’ll try it out ASAP.

But just out of curiosity: where did you find the information for this? I looked at the data sheets and the do mention SPI_NSS but don’t say anything about the chip select, etc?

Edit: works perfectly, you’re a life (battery har har) safer! thanks!

1 Like

@quintesse , ha ha pleased it helped you out. I suspected it was a floating gpio, so i went through and made sure they were tied to the correct logic level. Bingo… the sleep current dropped to the advertised level

So could that be the same problem I’m having when I use the user button on the sx1262 to wake up the system from deep sleep? When I add a esp_sleep_enable_ext1_wakeup(1ULL << 21, ESP_EXT1_WAKEUP_ANY_LOW); to my code the sleep current shoots up by a whole 1mA.

I also have the Xiao ESP32S3 & SX1262 kit, with the two connected via the B2B connector. I’m trying to implement deep sleep but haven’t found a good guide on this. I’d appreciate if anyone can point me in the right direction there.

I’ve tried the code that @Graeme provided in this topic, but it doesn’t work. When the call to radio.sleep() occurs, I get these errors on the serial:

[ 65144][E][esp32-hal-gpio.c:176] __digitalWrite(): IO 41 is not set as GPIO. Execute digitalMode(41, OUTPUT) first.
[ 65155][E][esp32-hal-gpio.c:176] __digitalWrite(): IO 41 is not set as GPIO. Execute digitalMode(41, OUTPUT) first.

I can fix that by adding a pinMode(41, OUTPUT) earlier in the setup, but sleep still fails. It immediately wakes back up due to ESP_SLEEP_WAKEUP_EXT0, even though the radio should be sleeping.

Does anyone have a link to a guide or some insight that could assist?

[Mods might like to move this to a new topic?]

Hi there,

Just a hunch , but do you “Flush the serial” before sleep…LOL :grin:
I think on ESP it’s like mom saying brush your teeth before bed. ?
also the EXT0 and EXT1 is another way. There is a thread of course I can’t find it now… but it has “ESP Sleep EXT0” info. Try that search term …

HTH
GL :slight_smile: PJ :v:

It’s something pesky or syntax and the matter it wakes immediately back up is the indicator. :face_with_hand_over_mouth: try the flush.

Thanks for the suggestion, @PJ_Glasso. I tried that, and it didn’t seem to help. Here’s my current code (slight changes from @Graeme’s):

#include "driver/rtc_io.h"
#include <RadioLib.h>
#include <string>

#define USE_EXT0_WAKEUP          1               // 1 = EXT0 wakeup, 0 = EXT1 wakeup
#define WAKEUP_GPIO              GPIO_NUM_1     // Only RTC IO are allowed - ESP32 Pin example
RTC_DATA_ATTR int bootCount = 0;

// Pins number for SX1262 Chip
#define LORA_MISO 8
#define LORA_SCK 7
#define LORA_MOSI 9
#define LORA_CS 41  //NSS
#define LORA_DIO2 38
#define LORA_DIO1 39  // irq
#define LORA_RESET 42
#define LORA_BUSY 40

SX1262 radio = new Module(LORA_CS, LORA_DIO1, LORA_RESET, LORA_BUSY);

void setup() {
    Serial.begin(115200);

    struct timeval tv_now;
    gettimeofday(&tv_now, nullptr);

    delay(5000);  //Take some time to open up the Serial Monitor

    Serial.print("Boot time: ");
    Serial.println(tv_now.tv_sec * 1000 + tv_now.tv_usec / 1000);

    pinMode(41, OUTPUT);

    ++bootCount;
    Serial.print("Boot number: ");
    Serial.println(bootCount);
    esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
    switch(wakeup_reason) {
    case ESP_SLEEP_WAKEUP_UNDEFINED:
        Serial.println("Wakeup was not caused by deep sleep");
        break;
    case ESP_SLEEP_WAKEUP_EXT0:
        Serial.println("Wakeup caused by ESP_SLEEP_WAKEUP_EXT0");
        break;
    case ESP_SLEEP_WAKEUP_EXT1:
        Serial.println("Wakeup caused by ESP_SLEEP_WAKEUP_EXT1");
        break;
    case ESP_SLEEP_WAKEUP_TIMER:
        Serial.println("Wakeup caused by ESP_SLEEP_WAKEUP_TIMER");
        break;
    default:
        Serial.print("Wakeup cause unknown: ");
        Serial.println(wakeup_reason);
    }

    // SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI);

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

    rtc_gpio_pullup_dis(WAKEUP_GPIO);
    rtc_gpio_pulldown_en(WAKEUP_GPIO);

    // Go to sleep now
    Serial.println("Putting Radio to Sleep");
    radio.sleep();

    gettimeofday(&tv_now, nullptr);
    Serial.print("Going to sleep at: ");
    Serial.println(tv_now.tv_sec * 1000 + tv_now.tv_usec / 1000);
    Serial.flush();
    Serial.end();

    esp_deep_sleep_start();
}

void loop() {
}

And the output I’m getting:

Boot time: 13
Boot number: 1
Wakeup was not caused by deep sleep
Putting Radio to Sleep
Going to sleep at: 5014
Disconnected (read failed: [Errno 6] Device not configured)
Reconnecting to /dev/cu.usbmodem101 	 Connected!
Boot time: 5070
Boot number: 2
Wakeup caused by ESP_SLEEP_WAKEUP_EXT0
Putting Radio to Sleep
Going to sleep at: 10071
Disconnected (read failed: [Errno 6] Device not configured)
Reconnecting to /dev/cu.usbmodem101 	 Connected!
Boot time: 10126
Boot number: 3
Wakeup caused by ESP_SLEEP_WAKEUP_EXT0
Putting Radio to Sleep
Going to sleep at: 15126
Disconnected (read failed: [Errno 6] Device not configured)
Reconnecting to /dev/cu.usbmodem101 	 Connected!
Boot time: 15182
Boot number: 4
Wakeup caused by ESP_SLEEP_WAKEUP_EXT0
Putting Radio to Sleep
Going to sleep at: 20182
...

So - I just reviewed the schematics for the Xiao-ESP32S3 and Wio-SX1262, and I don’t see how this can ever work using the B2B connector. Here’s the diagram:

Based on this, GPIO1 isn’t even connected to the Wio-SX1262, so it can’t possibly be used as a wakeup. It’s probably floating, hence my code wakes up immediately.

What’s more, it seems the Wio-SX1262 pins that could be used for wakeup (i.e. LORA_DIO1 and maybe LORA_BUSY) are NOT connected to RTC GPIOs on the ESP32S3 via the B2B connector - they’re connected to regular GPIOs, which can’t be used for deep sleep wakeup.

Interestingly, the schematic for the Wio-SX1262 does show that the B2B connector has access to GPIO14-18, but I guess they weren’t chosen to connect to the SX1262. That’s a design choice that seems to limit the ability to deep sleep these devices and wakeup for packet reception.

1 Like