XIAO nRF52840 & Wio-SX1262 Kit failures

I have had 2 kits failing in the same way. I am using the kits in remote weather sensors to broadcast readings via LoRa to a central hub. For several weeks, they work fine, and then a fault appears: the software keeps running as normal, and at startup the current consumption is 19 µA. As soon as the SX1262 module has been used to send a broadcast, sleep current consumption rises from 19 µA to 5300 µA and nothing I do will reduce it. Replacing the XIAO nrf52840 board fixes the problem, but for how long?

It seems like the SX1262 is being kept awake by the nRF52840 but nothing I do will fix the problem - SPI.end(), resetting the SX1262, combinations of standby and sleep etc.

1 Like

Hi there,

So I went back and took a look at the ping -Pong enhanced Demo after some review.

Prove whether the radio is actually asleep
After TX, issue the normal radio sleep path, then measure current. If it stays at ~5.3 mA, that strongly suggests the SX1262 never reached real sleep or was instantly reawakened. Since the module’s expected sleep current is around 1.62 µA, 5.3 mA is not a “slightly bad sleep” problem :face_with_hand_over_mouth: it is an awake radio problem.

Reconfigure SPI pins before MCU sleep
Don’t just call SPI.end(). Make sure the SPI pins are left in a state that cannot poke the radio awake. The Seeed forum report specifically calls out putting the nRF52840 SPI interface to sleep as necessary to avoid waking the transceiver repeatedly. So there is that along with, that stupid switch. (IMHO) :grin:

Check the antenna-switch / extra control pins
That same Seeed report notes the RF-switch pin can add current if left asserted. Not enough by itself to explain 5.3 mA, but enough to muddy the numbers and point to bad end-state pin handling.

Verify BUSY really goes idle before sleep
If code cuts corners after TX and sleeps the chip before the SX1262 is fully done, the next command sequence can get out of sync. That can leave the radio in a bad state that survives until a true hardware reset.

Use a hard radio reset test
Do a real SX1262 reset pulse, then immediately measure current before reinitializing.

  • If current falls back low after reset, the radio state machine was wedged.
  • If current stays high until the XIAO is replaced, the host pins or the XIAO hardware may be what’s holding it awake.

My best diagnosis

If I had to bet :thinking: and without seeing any of the code in question, I’d bet on this:

The nRF52840 is leaving one or more interface/control pins in a state that prevents true SX1262 sleep or wakes it right back up after TX.

That fits:

  • the current number,
  • the fact that it happens after the radio has been used,
  • and the Seeed report about SPI needing to be put to sleep on this exact platform.

The practical fix direction

I’d steer toward:

  • full radio sleep command
  • then wait for BUSY idle
  • then deassert / park NSS
  • then set SPI pins to a benign state
  • then make sure any RF switch / TCXO related lines are not left enabled
  • then enter MCU sleep

Replacing the XIAO “fixing it” does not prove the XIAO is damaged. It may simply reset all GPIO and peripheral state back to sane defaults.

That’s the old trap with these low-power radio builds — a board swap can hide a firmware end-state bug.

HTH
GL :slight_smile: PJ :v:

I have 2 boards with identical software and bootloader and using the same SX1262 module. They behave differently. I have been through the code in detail, and with a new board the code works as it should. I wonder whether the boards are developing a hardware fault that prevents the SX1262 sleeping - a noisy bus or something?

I am using the Radiolib library, and it does most of the above. The only thing left for me to try is to disable SPI and reconfigure the pins.

Hi there,

Hmmm, So odd of a failure mode for me is all.
I would agree though – a noisy bus or GPIO near the ANT maybe could leave it not how it needs to be.
On a one shot test, does it go sideways current wise right away or after some delay?
Can you use the RGB LED as a Radio STATE status the Xiao is Great for this and have no USB connected?
Do the values change a little or a lot?

Stay at it, keep testing. actually it is a great troubleshooting exercise. You’ll get it sorted one way or the other, either the Hardware is BAD or something else is intermittent and sneaking in there. :crossed_fingers:

HTH
GL :slight_smile: PJ :v:

Currently, it broadcasts a short data packet every 2 minutes, sleeping in between. The radio is active for approximately 4.75 milliseconds during transmission at 45 milliamps current, then listens for a short ack for up to 10 milliseconds (normally 5 milliseconds) at 5 milliamps current. The board is supplying a low current tunnel-magnetoresistance sensor as well as the on-board battery voltage divider, and has an external interrupt enabled so sleep current is just under 20 microamps.

After configuration of the XIAO nrF52840 board and SX1262 LoRa module, the device goes to sleep, waking every 2 minutes to broadcast data before going to sleep. On 2 occasions now, this has worked for several weeks before going into a state where the sleep current is 5 milliamps instead of 20 microamps. Apart from this, it continues to work as normal taking and broadcasting measurements.

The device is powered from 3 AA batteries with no USB connection.

I’ll try changing the mode of the SPI pins and also see if I can get the radio state. Even a radio reset does not help.

Thanks for your suggestions. Will report back.

Russ

EDIT:

Something else to add is that I have a sensor using a XIAO nRF52840 PLUS and this has continued to work faultlessly. This has a different board layout to the XIAO nRF52840 although the components are the same.

did you buy the sandwitch together as a package?

… whenever time is an issue you have to think of timers in the code… there is a 16bit upper limit to the units ability to count… if this is not handled correctly this can cause strange lockups

also battery power brownout can sometimes cause processing problems.. maybe try powering the device and see if the same problem happens FYI

Yes, I bought some of the kits and also some individual XIAO nRF52840 PLUS boards.

I have spent days crawling over the code and am sure that timing and logic of the main loop is fine. I also monitor the battery voltage to 0.01 V as part of the code, and it is 4.5V.

The thing is, it works fine on a fresh board and 2 boards starting working fine but both failed in the same way after several weeks.

I have just tried changing the pinMode of the SPI pins to INPUT_PULLDOWN after shutting down SPI, and that has made no difference.

Just looking at the Radiolib code now, to see what information I can extract about the SX1262 status.

interesting… i will check with seeed to see if they know anything

try installing meshtastic firmware…

https://flasher.meshtastic.org/

my has been running for like years and i have

not noticed anything… but i do not study the power to that level of detail

Hi there,

Ok , Wow that is Very good Leg work on your part.
WHat frequency bands are we talking about.?

I just had a flashback of someone with these Lora boards near a cell tower and only when the co. did maintenance on a backhaul channel that the Lora was near it was cellular range EU if i recall, blew out the front ends of his RX’s or some crazy thing.
and like you it was only a certain set that was failing after some time.
I think he over came it with some shielding and some additional timing delay between RX & TX. and maybe even a band plan change away from the cellular stuff.

keep looking and Testing, you’ll get it. :+1:

GL :slight_smile: PJ :v:

from the PLUS working better or being immune to the HAvana-syndrome :face_with_spiral_eyes: .:backhand_index_pointing_left: :grin: your units are having.
Thing is nutty , it’s not a softbrick or anything to the NRF, more of the RAdio not acting right it seems. Does a manual reset of the Nrf52840 make it come back to normal sleep current the next cycle?

:wink:

I have it running on 868.3 MHz. Yes, when I reset the nRF52840 it resumes low power state until the next transmission. I wish I had some test gear that I could have a look at the SPI and control lines with.

1 Like

Hi there,

So , OK that is good info and good to know and add to the troubleshooting AI tree.
:grin:
You are so Spot on, Someone once said

" Tools don’t replace experience — they expose who has it.”

forsure a scope would help.
Use the RGB LED in the CODE if you can , take some best guesses where its might be failing add some LED colors to the states See if you can narrow it down more.
I like the LED because you can remove any serial console interference that can occur also, even if nothing is connected (physically) :crossed_fingers: toggling the colors is cake. Check out the Drag and drop RGB tester(Uf2) on here, demo with code.
if you set SPI begin with options and add some COLOR or status , you may be able to get a better handle on where it’s crashing , save the state to the NVram and check it in the loop if it crashes the last state can be saved. or something along those lines,
We use it to save and count the reboots.

I could be Soaked , All Wet but anything that may turn on the light is worth
checking out if possible…

Keep looking :v:

GL :+1: PJ

I am still getting the fault but it is intermittent. I don’t think it is the radio module not sleeping. When it happens, the CPU does not halt when waiting for the binary semaphore, instead running round the loop. All the interrupts and code work as normal, so the sensor node runs fine but draws too much current. It only does it on battery power. I notice that the battery leads run close to the antenna - I wonder if the transmission injects a lot of noise back into the board via the a battery leads and puts it into an odd state?

1 Like

Hi there,

Ok, that is more good info and I’m feeling like,
I agree this is more likely a power-path / transient problem than the battery leads simply acting like an antenna. But that is Gold on troubleshooting closer.

The clue for me is that the fault only appears on battery power, and after it happens the node still runs normally, but current stays high because the CPU no longer blocks properly on the semaphore. That certainly explains why the MCU is not getting back into a low-power wait state, and Nordic has documented that uncleared events/interrupts can keep an nRF52840 from sleeping.

That said, the measured current is still an important clue. A fault current around 5 mA is much closer to an SX1262 left active than to a sleeping radio plus only a slightly busy CPU. The SX1262 sleep current is in the low-µA range, while active receive current is in the mA range, so this still looks like something in the radio path or its support circuitry is being left on, not just “firmware looping a bit.”

Because it only happens on battery, I would look very hard at TX burst droop / transient injection first. The SX1262 transmit current can be substantial at high power, so a battery source with more impedance than a bench supply can dip or ring during TX and leave the system in an odd state afterward. That seems more plausible to me than simple RF coupling from the battery leads near the antenna.

So my current theory would be:

  1. A TX power transient on battery causes a bad state transition.
  2. After that, either the SX1262 or related control path is not fully returned to sleep, or an interrupt/event is left pending.
  3. The node still “works,” but the CPU never gets back into its proper blocked sleep state, so current remains high.

What I would test next:

  • Compare behavior on battery vs bench supply while watching supply dip during TX.
  • Add bulk capacitance close to the board and shorten / tidy the battery leads.
  • After TX, verify the radio path is really parked: BUSY idle, NSS deasserted, SPI pins benign, radio sleep command completed.
  • When the fault occurs, log which interrupt/event/semaphore source is still active, because that may only be the symptom of the radio/power glitch rather than the original cause.

I do think something is being left on, but I suspect the trigger is battery droop during TX, not just the CPU spontaneously deciding not to sleep.

Onward.. :grin:
do you need to transmit at such High power try a little lower too. :crossed_fingers:

HTH
GL :slight_smile: PJ :v:

A TX burst at up to 125 mA typical at +22 dBm is a real pulse load on the module, and battery wiring, source impedance, and local decoupling all matter during that event. If battery operation is the only case that triggers the fault, I would suspect supply droop / transient behavior before I’d blame radiated RF coupling into the battery leads.

1 Like

meanwhile, I know folks having good results using this $12-13$ device,

HTH
GL :slight_smile: PJ :v:

I use the simple built-in logic analyzer in the PPK2 for basic stuff, and a protocol analyzer for heavier lifting , CAN-FD, ISOC, SDLC etc. but these have decoders that come with it (see video) to decode serial , SPI, and others. thirteen buc’s WOW. :grin:
very easy on the wallet :money_mouth_face:

I think this is the same ,but a couple bucs more for the cool adapters and leads..:v:
$19

1 Like

Thanks for the detailed reply. I thought that I had fixed it by moving the battery leads away from the antenna and cutting the power to -9 dB: that stops it entering the strange mode where it won’t halt at the semaphore and draws 5.3 mA. Now it seems to be sleeping - I use the LED to flash every time it wakes up. I left it running while - it was OK for half an hour, drawing 19 microamps. Then I went for a break and the sleep current has jumped up to 2.5 mA but it does seem to be sleeping, or at least halting at the semaphore. Will investigate more tomorrow as my brain is getting tired.

2 Likes

OK, so I have spent the weekend testing everything again. There is definitely a problem caused by the antenna being too close to the battery leads. Re-routing the leads has fixed this. The other problem is the board going into an odd state when it receives a packet interrupt from the SX1262. I have 4 boards - 1 of them works properly (going back to low current sleep after the packet transmission) and the other 3 do not. All identical software, using the same SX1262 module. I connected the kit together using leads so I could pull the power to the SX1262 when it went into the high current state: the current draw did not change, suggesting that the SX1262 was sleeping as commanded, and the current draw was coming from the nRF52840.

I am considering moving the ESP32S3 as the sleep current is almost as low as the nRF52840 and the documentation is better.

The test code I have used:

#include <Arduino.h>
#include <nrf_timer.h>
#include <Adafruit_SPIFlash.h> 
#include <RadioLib.h>
#include <InternalFileSystem.h>
#include <Adafruit_LittleFS.h>
#include <hw_rng.h>

const unsigned long kSerialSpeed = 115200;

// Transceiver pin connections
const uint32_t kPinNSS = D4;
const uint32_t kPinDI01 = D1;
const uint32_t kPinRST = D2;
const uint32_t kPinMOSI = D10;
const uint32_t kPinMISO = D9;
const uint32_t kPinSCK = D8;
const uint32_t kPinBUSY = D3;
const uint32_t kPinRF_SW = D5;

const u_int8_t kInterruptPin = D6;      // pin to receive pulses from anemometer - not much choice on Xiao nRF52840!
const u_int32_t kPinBatEnable = 14;     // Send LOW to enable voltage divider for battery monitor
const u_int32_t kPinBatADC = PIN_VBAT;  // ADC pin connected to XIAO on-board battery voltage divider

// LoRa modem settings
const float kTransFreq = 868.3;
const float kLoRaBandwidth = 500.0;     // maximum bandwidth gives maximum data rate, reducing on-air time and power consumptio
const uint8_t kSpreadingFactor = 5;     // minimum spreading factor gives maximum data rate
const uint8_t kCodingRate = 8;          // maximum forward error correction to maximise noise immunity
const uint8_t kLoRaSyncWord = RADIOLIB_SX126X_SYNC_WORD_PRIVATE;  // standard sync word
const int8_t kOutputPower = 14;        // maximum legal power in EU & UK 25 mW
const size_t kPreambleSensor = 12;      // default preamble, receiver constantly listening so no need to lengthen
const size_t kPreambleHub = 32;         // hub ack preamble - longer than default to give sensor more chance to detect
const uint8_t kLoRaCRC = 2;             // enable 2 byte CRC
const bool kRxBoostedGainMode = true;   // slightly improves receiver gain at the expense of extra 0.6 mA current consumption
const float kTCXOVoltage = 1.6;          // control voltage for TCXO, 0 to disable


SX1262 radio = new Module(kPinNSS, kPinDI01, kPinRST, kPinBUSY);

using namespace Adafruit_LittleFS_Namespace;
// Flash Class instance - used to put flash to sleep and save power
Adafruit_FlashTransport_QSPI flashTransport;

// semaphore used to make processor wait and sleep
// - gives fast wake response following interrupt
SemaphoreHandle_t xSemaphore;

// Radio interrupt flag set after packet sent or packet received.
volatile bool flag_radio_interrupt = false;

/**
 * Interrupt service routine for radio module
 */
void RadioIRQHandler(void) {
  // disable interrupts for critical code, then renable
  UBaseType_t uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
  flag_radio_interrupt = true;
  taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);


  BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);
  portYIELD_FROM_ISR(xHigherPriorityTaskWoken); 
}

// Clock interrupt flag set after every kSleepInterval seconds.
volatile bool flag_clock_interrupt = false;  

/**
 * Interrupt service routine for RTC timer.
 * NB extern to avoid C++ name mangling
 */
extern "C" void RTC2_IRQHandler(void)
{
  if ((NRF_RTC2->EVENTS_COMPARE[0] != 0) && ((NRF_RTC2->INTENSET & 0x10000) != 0)) {
  // disable interrupts for critical code, then renable
    UBaseType_t uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();

    NRF_RTC2->EVENTS_COMPARE[0] = 0;  // clear compare register 0 event
    NRF_RTC2->TASKS_CLEAR = 1;        // clear counter

    flag_clock_interrupt = true;
  
    taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);

    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken); // immediate context switch (don't wait for tick)
  }
}

/**
 * Initialise low frequency RTC and configure interrupt
 * @param[in] RTCcount time interval in seconds * 1024
 */
void InitialiseLFRTC(const uint32_t& RTCcount) 
{
  NRF_CLOCK->TASKS_LFCLKSTOP = 1;
  NRF_CLOCK->LFCLKSRC = 1;       // select LFXO
  NRF_CLOCK->TASKS_LFCLKSTART = 1;
  while(NRF_CLOCK->LFCLKSTAT != 0x10001)
  
  NRF_RTC2->TASKS_STOP = 1;      // stop counter 
  NRF_RTC2->TASKS_CLEAR = 1;     // clear counter
  NRF_RTC2->PRESCALER = 31;      // set counter prescaler, fout=32768/(1+PRESCALER) 1024Hz
  NRF_RTC2->CC[0] = RTCcount;    // set value for TRC compare register 0
  NRF_RTC2->INTENSET = 0x10000;  // enable interrupt CC[0] compare match event
  NRF_RTC2->EVTENCLR = 0x10000;  // clear counter when CC[0] event
  NVIC_SetPriority(RTC2_IRQn,3); // Higher priority than SoftDeviceAPI
  NVIC_EnableIRQ(RTC2_IRQn);     // enable interrupt  
  NRF_RTC2->TASKS_START = 1;     // start Timer
}

/**
 * Power down the flash memory.
 * (Saves approximately 10 µA.)
 */
void PowerDownFlash(void) {
  flashTransport.begin();
  flashTransport.runCommand(0xB9); 
  delayMicroseconds(5);
  flashTransport.end();  
}

/**
 * Flashe on-board LED.
 * @param led_colour pin address of LED to flash
 * @param duration duration of LED flash in milliseconds
 * @param num_flashes how many flashes to perform
 */
void FlashLED(const uint32_t& led_colour, const uint32_t& duration, const uint16_t& num_flashes) {
  pinMode(led_colour, OUTPUT);
  for (int i = 0; i < num_flashes; i++) {
    digitalWrite(led_colour, LOW);
    delay(duration);       
    digitalWrite(led_colour, HIGH);
    delay(duration);
  }
}

void setup() {
  FlashLED(LED_GREEN, 50, 5);
  
  Serial.begin(kSerialSpeed);
  //while (!Serial);
  Serial.println("Starting up.");
  Serial.flush();

  // Use DC-DC converter to save power - best improvement is on high duty cycle
  NRF_POWER->DCDCEN = 1;   

  // power down flash - saves a few microamps
  flashTransport.begin();
  flashTransport.runCommand(0xB9); 
  delayMicroseconds(5);
  flashTransport.end();

  pinMode(kPinRF_SW, OUTPUT);
  digitalWrite(kPinRF_SW, HIGH);

  // configure radio
  radio.reset(true);
  radio.begin(kTransFreq, kLoRaBandwidth, kSpreadingFactor, kCodingRate, kLoRaSyncWord, kOutputPower, kPreambleSensor, kTCXOVoltage);
  radio.setCRC(kLoRaCRC);
  radio.setDio2AsRfSwitch(true);
  radio.setRxBoostedGainMode(kRxBoostedGainMode, true);
  //radio.setOutputPower(kOutputPower, true);
  radio.setDio1Action(RadioIRQHandler);

  // put radio to sleep
  radio.standby(RADIOLIB_SX126X_STANDBY_RC);
  radio.sleep(true);

  // leaving RF switch pin high increases current consumption by 55 µA!
  digitalWrite(kPinRF_SW, LOW);

  // stop SPI to prevent transceiver wakes
  SPI.end();
 
  // RTC interval timer interrupts
  InitialiseLFRTC(1024 * 5);  // 5 second interval

  xSemaphore = xSemaphoreCreateBinary();

  FlashLED(LED_BLUE, 50, 5);

  while(true) {

    xSemaphoreTake(xSemaphore, portMAX_DELAY);

    // draws 15 microamps when sleeping

    Serial.println("wake."); 
    if (flag_clock_interrupt) {
      Serial.println("clock"); 
    }
    if (flag_radio_interrupt) {
      Serial.println("radio"); 
    }
    Serial.flush();

    if (flag_clock_interrupt) {
      flag_clock_interrupt = false;
      FlashLED(LED_BLUE, 10, 1);
      Serial.println("Sending payload");
      Serial.flush();

      // bring up SPI, enable RF switch, wake radio
      SPI.begin();
      digitalWrite(kPinRF_SW, HIGH);
      radio.standby();

      // send payload
      radio.startTransmit("123456789");
    }
    
    if (flag_radio_interrupt) {
      // packet sent interrupt
      // tidy up and go to sleep
      flag_radio_interrupt = false;
      radio.finishTransmit();
      radio.standby();
      radio.sleep();
      digitalWrite(kPinRF_SW, LOW);
      SPI.end();
      Serial.println("Payload sent.");
      Serial.flush();
    }
    // current consumption jumps to 2400 microamps after radio interrupt
  }
}

void loop() {
}

Hi there,

Ok, Nice work digging into this, Closer & Closer. Nice especially catching the antenna/battery lead interaction. That’s a real effect, and rerouting those leads absolutely can clean up RF-induced weirdness.

That said, I don’t think that’s the whole story here. :thinking:

Based on your latest results, the bigger issue looks like it’s happening after the SX1262 packet interrupt, not during normal operation or sleep entry.

A few key observations from what you described:

  • You have 1 board behaving correctly, 3 not, with identical software
  • The issue starts after a packet interrupt from the SX1262
  • Powering down the SX1262 does not reduce the current
  • The excess current is clearly coming from the nRF52840, not the radio

That is a nice find and strongly suggests the problem is not “radio not sleeping,” but rather that the MCU is not returning to a true low-power state after the interrupt. :backhand_index_pointing_left: MY guess.

The most probable culprit is the radio interrupt path (DIO1) and how it’s being handled/cleared or the time it takes.

In this kind of setup, if:

  • The IRQ source isn’t fully cleared
  • The DIO1 line doesn’t return cleanly to idle
  • Or the MCU keeps getting retriggered
    (nordic also has doc’s for power on Edge triggered vs. Level can save some ua.)
    then the CPU can stay awake (or keep waking repeatedly), even though your main loop looks like it’s blocking on a semaphore.

That lines up perfectly with:

low current before TX → interrupt occurs → current jumps → never returns to baseline

From the code, these are the main things that stand out.

First, the failure lines up with the radio IRQ handling path, not the transmit path itself. The code wakes on flag_radio_interrupt, does:

  • radio.finishTransmit();
  • radio.standby();
  • radio.sleep();
  • digitalWrite(kPinRF_SW, LOW);
  • SPI.end();

Then it goes back to xSemaphoreTake(...). If current stays high after that, the likely suspects are:

  1. DIO1 interrupt line not fully quiescing
  2. a pending interrupt/event not being fully cleared
  3. the CPU staying in a fast-idle/run state instead of proper sleep
  4. some peripheral or clock left enabled after the IRQ path

The strongest candidate, in my view, is the DIO1 / interrupt side.
You attach the interrupt through RadioLib:

radio.setDio1Action(RadioIRQHandler);

but I do not see any explicit verification that the SX1262 IRQ source is fully cleared and that DIO1 actually returns inactive afterward. If the line stays asserted, or is noisy on some boards, the MCU can keep getting poked awake.

That is one of the first things I would check on a scope or logic analyzer:

  • DIO1 before TX
  • DIO1 at TX-done
  • DIO1 after finishTransmit()
  • DIO1 several milliseconds later

If that pin is not cleanly returning to idle on the bad boards, you found the real trail then Count interrupts

  • Add a counter for radio IRQs
  • If you gets more IRQs than expected per transmit, that is a smoking gun

WE know also SPI.end() does not guarantee all lines are in a benign state
Ending SPI is fine, but it does not automatically mean the pins are now in the lowest-leakage or least-coupled condition.
Depending on board/module wiring, floating or weakly-driven lines can leave things in odd states.

On the bad boards, I would test forcing:

  • NSS
  • SCK
  • MOSI
  • RST
  • RF switch control

to known idle states after sleep, not just calling SPI.end().

When identical software behaves differently across nominally identical boards, I start thinking:

  • DIO1 edge shape / rise time / ringing
  • module wiring differences
  • grounding/layout variance
  • antenna coupling
  • battery wiring injection
  • weak pull resistor issue
  • one board has just enough margin, the others do not

That does not mean the software is innocent. It means the software may be too trusting of marginal hardware behavior.

I would not expect the ESP32-S3 to be the better long-term answer for lowest sleep current here. If anything, this is the kind of problem that should be fixed on the nRF52840, because the nRF52840 is a better fit for a battery LoRa node when the sleep/wake path is done properly.

switching to an ESP32-S3 is not likely to magically fix this, and it is not the right conclusion from these results. On paper and in practice, a properly-behaved nRF52840 should usually give you better true low-power behavior than an ESP32-S3 in this kind of duty-cycled sensor node. (I found the same with muy Sensor_Node Demo)
The S3 can do respectable sleep current, but board-level reality, radio stack behavior, peripherals, and wake handling usually make it harder to get consistently ultra-low current than on Nordic. Better docs do not equal lower sleep current.

You are making progress.

HTH
GL :slight_smile: PJ :v:

Great work BTW :+1:

2 Likes

good info… i am definatly going to link this thread to seeed to see what they say about all this… but dont hold your breath!

1 Like

It seems to be after the radio interrupt. For example, if I call radio.finishTransmit() immediately after radio.startTransmit(), transmission is aborted before the packet is sent so no interrupt is generated and the board does not enter the high current state.

I have posted on the Radiolib support page to see whether the author has an suggestions. He is normally quite responsive.

2 Likes