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. 
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.
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:
- DIO1 interrupt line not fully quiescing
- a pending interrupt/event not being fully cleared
- the CPU staying in a fast-idle/run state instead of proper sleep
- 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
PJ 
Great work BTW 