Power Savings using AVR code

My setup is an UNO receiving data via NRF24L01+ while connected to a laptop USB and an LCD which is being used for verification purposes (to make sure fresh data is being sent). The sender is a nano with an NRF24 and a DHT11 powered from 2x18650 batteries being controlled by a bms which is wired to a solar panel, but the solar panel is facing down on a desk so it doesnt charge the battery pack at present. The nano is about 20 cms away from the UNO for now.

I tried this code with 5 cycles and power savings were clear. (8.3 to 7.7 in 24 hrs vs 8.4 to 8.2 in 36 hrs). But then I tried 225 cycles and the results were the same as with 5 cycles. I understand there is a limit to power savings, but could that be it? Sending data I understand is power-consuming, but if Im going from sending every (5x8) 40 seconds to every (5x225) 30 minutes, I would have expected there to be a greater savings:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <DHT.h>

#include <avr/wdt.h>            // library for default watchdog functions
#include <avr/interrupt.h>      // library for interrupts handling
#include <avr/sleep.h>          // library for sleep
#include <avr/power.h>          // library for power control

#define DHTTYPE DHT11   // DHT 11 
#define DHT11_PIN 6
#define CE_PIN 7
#define CSN_PIN 8

const byte slaveAddress[5] = {'R','x','A','A','A'};


struct package
  float humedad = 0;
  float temperatura = 0;
typedef struct package Package;
Package data;

RF24 radio(CE_PIN, CSN_PIN); // Create a Radio
unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 1000; // send once per second

int nbr_remaining; // how many times remain to sleep before wake up
#define led 13

// interrupt raised by the wdt firing (when the wdt fires during sleep, this function will be executed).  remember that interrupts are disabled in ISR functions
ISR(WDT_vect){// not hanging, just waiting
        wdt_reset();// reset the watchdog

// function to configure the wdt: let it sleep 8 seconds before firing.  when firing, configure it for resuming program execution
void configure_wdt(void){
  cli();                           // disable interrupts for changing the registers
  MCUSR = 0;                       // reset status register flags
                                   // Put timer in interrupt-only mode:                                       
  WDTCSR |= 0b00011000;            // Set WDCE (5th from left) and WDE (4th from left) to enter config mode,
                                   // using bitwise OR assignment (leaves other bits unchanged).
  WDTCSR =  0b01000000 | 0b100001; // set WDIE: interrupt enabled = seconds
                                   // clr WDE: reset disabled
                                   // and set delay interval (right side of bar) to 8 seconds
  sei();                           // re-enable interrupts

void sleep(int ncycles) {// Put the Arduino to deep sleep. Only an interrupt can wake it up.  
  nbr_remaining = ncycles; // defines how many cycles should sleep
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);// Set sleep to full power down.  Only external interrupts or the wdt timer can wake the CPU!
  power_adc_disable();  // Turn off the ADC while asleep.
  while (nbr_remaining > 0){ // while some cycles left, sleep!
    sleep_mode();  // Enable sleep and enter sleep mode.
    // CPU is now asleep. program execution completely halts!  Once awake, execution will resume at this point if the wdt is configured for resume rather than restart
    sleep_disable();  // When awake, disable sleep mode
    nbr_remaining = nbr_remaining - 1;   // we have slept one time more 
  power_all_enable();  // put everything on again

void setup(){  
  pinMode(led, OUTPUT);
  //Initialize the DHT sensor

  radio.setDataRate( RF24_250KBPS );
  radio.setRetries(3,5); // delay, count
  digitalWrite(led, LOW); //turn off led13
  configure_wdt();  // configure the watchdog.  wdt is set to bite, unless you pet it...

  digitalWrite(led, HIGH);     // blink twice
  digitalWrite(led, LOW);   
  digitalWrite(led, HIGH);   
  digitalWrite(led, LOW);   


void loop(){
  sleep(5);  // sleep for a given number of cycles (here, 5 * 8 seconds) in lowest power mode
  // usefull stuff should be done here before next long sleep, like send() and blink 3x before going back to sleep
  send(); //then sleep
  digitalWrite(led, HIGH);   
  digitalWrite(led, LOW);   
  digitalWrite(led, HIGH);   
  digitalWrite(led, LOW);   
  digitalWrite(led, HIGH);   
  digitalWrite(led, LOW);   

void send() {

  //take measurement
  data.humedad = dht.readHumidity();
  data.temperatura = dht.readTemperature();
    bool rslt;
    rslt = radio.write( &data, sizeof(data) );
        // Always use sizeof() as it gives the size as the number of bytes.
        // For example if dataToSend was an int sizeof() would correctly return 2

    Serial.print("Data Sent ");
    if (rslt) {
        Serial.println("  Acknowledge received");
    else {
        Serial.println("  Tx failed");

void updateMessage() {


Perhaps there is a clue to be found by measuring the current consumption of the board when its idle ?

You're suggesting that may be it's lower limit in power consumption but when in sleep mode it should consume much less than in idle no?

I believe I measured it once at 280mA in idle and 150 in sleep mode.

I did not look at the code, you cannot tell from the code how much power the device is actually using.

You have the board in front of you, so the first step in trying to work out why the batteries dont last as long as you think they should, is to carry out basic current measurments and work out how many mAhr the project is actually using.