nRF24L01+ hang when sending data

Hi !

In my project I’ve replaced the cheap nRF24L01+ I was using for dev by your nRF24L01+ “high end” model, sadly they work not as good as the cheap one…

They hang (require a reset) when sending data around 30% of the time.

I’ve tried to add a little delay(10) befor sending data and a 22uF cap, it help a little, but it’s not 100% crash proof.

Any idea why your module crash and not the cheap one ?

As I bought a dozen of them I tested a few, they all behave the same.

void sendToMaster(int cmd) {

	bool rslt;

	Data_Sent.msg = cmd;
	
	radio.stopListening();

	delay(10); //added to reduce crash occurrences with SF modules

	rslt = radio.write(&Data_Sent, sizeof(Data_Sent));
	
	radio.startListening();

	Data_Sent.rnd++;
	
	if (rslt) {
		if (radio.isAckPayloadAvailable()) {
		}
		else {
			Serial.println("  Acknowledge but no data ");
		}
	}
	else {
		Serial.println("  Tx failed");
	}
}

On an Adafruit ItsyBitsy 32u4 8Mhz

https://i.imgur.com/g1PHwWZ.jpg

Any help appreciated.

Regards

Hi !

I really expect support as I’m facing lot of issues with your RF modules.

Not only they sometimes crash while sending data, but they also sometimes not initialize correctly and are running damn slow.

I really need to understand what’s wrong with your modules or with my code and/or circuit and solve these issues.

Just to mention again that the 2$ Chinese circuit are working flawlessly.

This is how I setup the RF module :

void setupRF24() {
	delay(1000);
	radio.begin();
	radio.setDataRate(RF24_250KBPS);
	radio.setPALevel(RF24_PA_MAX);
	radio.setChannel(125);
	radio.openReadingPipe(1, thisButtonAddress);
	radio.enableAckPayload();
	radio.setRetries(5, 15); // delay, count
	radio.startListening();
	radio.openWritingPipe(masterAddress);
}

To save the maximum power I turn off the power pin while sleeping :

void sleepNow() {  // here we put the arduino to sleep   

	digitalWrite(RF_POWER_PIN, LOW);	// turn off RF module
	led.state = LED_OFF;					//Set LED to OFF state

	attachInterrupt(2, wakeUpNow, CHANGE); // use interrupt

	power_timer0_disable();
	power_timer1_disable();
	power_spi_disable();

	set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here

	sleep_enable();          // enables the sleep bit in the mcucr register
	sleep_mode();            // here the device is actually put to sleep!!
							 // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
	sleep_disable();         // first thing after waking from sleep:
							 // disable sleep...
	detachInterrupt(2);      // disables interrupt 
}

then, on wake up code I turn on power pin back on and call the RF setup code again :

if (wakeUP) {
			lastActionMillis = millis();

			digitalWrite(RF_POWER_PIN, HIGH);		// turn off RF module
			setupRF24();

			led.state = LED_BLINK;
			led.blinkCount = 3;

			wakeUP = false;
		}

I’ve also tried not to fully turn off the module but to just use radio.powerDown(); and radio.powerUp(); sadly t behave the same.

When the system wake up the RF module is running very very slowly on data sending, receiving is working at expected speed.

What’s wrong ?

Thanks for your support solving this issue

I’m trying to trace what’s happening, and I’ve discovered that your module doesn’t keep the settings.

If I leave the module inactive for more than 12 sec the Tx doesn’t works anymore, then the speed is changed.

Start the module

Mashed !

speed: 2

Acknowledge but no data

Mashed !

speed:2

Acknowledge but no data

Mashed !

speed:2

Acknowledge but no data

Wait >12s

Mashed !

speed:2

Tx failed

Mashed !

speed:1

Tx failed

Something similar should happens on wake up.

Hope this can be fixed

If I use higher voltage 4V instead of 3.6V and add a 47uF cap it solve this issue of the module not working after 12s.

But it still sometime (that’s not reproducible 100%) went slow after wake up…

Hard to trace as I’ve no more serial connection after sleep.

Here is a video on how the system behave :

https://youtu.be/DRIaGC7TSno

Hello Alkerion

We’ve not seen anyone with this issue before and I wonder if it might be caused by the way you’re powering the nRF24L01+.

Have you tried using an external 5 volt power supply for just the nRF24L01+ rather than a GPIO pin? I’m wondering if the nRF24L01+ is being starved of power and locking up.

Hi Chris,

Yes I’ve tried with 5V from USB and I now use the 4V from Vhi + capacitor, not from external AA.

You module is not working well even at 4V if I don’t add the cap.

Everything is now “working as expected” but the slow speed on wake up.

I’ve tried again with the Chinese model, and it is also slower, but not as much, it’s lot less noticeable for unknown reasons.

I’ve tried my code on a Pro Micro 16Mhz, same behavior, so it’s not the ItsyBitsy.

Even if I cut down the power totally and initialize again on wake up it is slow.

What’s strange, is that if I click on the button right after the wake up the first Tx is OK, it means that it’s only after a very short period (~2-3s) that the Tx become slow.

After all the tests I’ve performed I don’t think it’s due to the RF module, something that is happening inside the device during sleep is impacting the RF transmissions, but what ?

Here is my full code :

    #include <SPI.h>
    #include <nRF24L01.h>
    #include <RF24.h>
    #include <ctype.h>
    #include <avr/sleep.h>
    #include <avr/power.h>
    #include <Bounce2.h>
    #include <LowPower.h>

    #define BUTTON_PIN 0
    #define LED_PIN 1
    #define CE_PIN A4
    #define CSN_PIN A5
    #define LOW_POWER_MODE_PIN 8

    #define BLINK_INTERVAL 1000 
    #define SLEEP_DELAY 480000

    //LED states
    #define LED_OFF 0
    #define LED_ON 1
    #define LED_BLINK 2

    //LED blink speed
    #define LED_SLOW 1000

    //LED Brightness
    #define LED_MAX_BRIGHTNESS 255
    #define LED_MED_BRIGHTNESS 150
    #define LED_MIN_BRIGHTNESS 50

    //**************************************************************************************
    float version = 2.06;
    //**************************************************************************************

    //RF24
    const uint8_t masterAddress[6] = "SRV00";
    uint8_t thisButtonAddress[6];

    const uint8_t DIPSwitchPins[] = { 7, 9, 10, 11 };

    RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

    volatile int ledState = LOW;

    volatile bool do_blinkLed = false;

    volatile bool wakeUP = false;

    //volatile bool turnedON = true;

    long previousMillis = 0;

    long lastActionMillis = 0;

    Bounce debouncer = Bounce();

    int RcvCnt = 0;

    int buttonNumber = 0;

    //Struct for LED
    struct LED {
       byte state;
       int blinkSpeed;
       int blinkCount;
       int brightness;
       unsigned long lastStateChange;
    };

    //Struct for data to send
    typedef struct {
       uint8_t rnd;
       uint8_t type;
       uint8_t msg;
    }
    A_t;

    //Struct for data received
    typedef struct {
       uint8_t rnd;
       uint8_t type;
       uint8_t msg;
    }
    B_t;

    A_t Data_Sent;
    B_t Data_Received;

    struct LED led = { LED_BLINK, LED_FAST, 3, 0, 0 };

    //****************************************

    void setup() {

       Serial.begin(9600);

       pinMode(LED_PIN, OUTPUT); //Led pin

       pinMode(13, OUTPUT);// onboard LED
       digitalWrite(13, LOW);

       pinMode(LOW_POWER_MODE_PIN, INPUT_PULLUP); //Low power mode pin

       getButtonNr();

       delay(500);

       radio.begin();

       delay(500);// Give RF module some time to run.

       setupRF24();

       debouncer.attach(BUTTON_PIN, INPUT_PULLUP);
       debouncer.interval(5); // interval in ms

       // No power save if Button is pressed or if Jumper is present
       if (digitalRead(BUTTON_PIN) ? 1 : 0 || digitalRead(LOW_POWER_MODE_PIN) ? 0 : 1) {
          digitalWrite(13, HIGH);//turn ON on board led to indicate that we are well connected to USB
       }
       else {
          //save power
          ADCSRA = 0;
          power_adc_disable();
          power_twi_disable();
          power_usart0_disable();
          power_usart1_disable();
          power_timer2_disable();
          power_timer3_disable();
          // disable the USB
          USBCON |= _BV(FRZCLK);  //freeze USB clock
          PLLCSR &= ~_BV(PLLE);   // turn off USB PLL
          USBCON &= ~_BV(USBE);   // disable USB
          power_usb_disable();
       }
    }

    //****************************************

    void loop() {

       if (wakeUP) {

          radio.powerUp();

          delay(500);

          pinMode(BUTTON_PIN, INPUT_PULLUP);

          led.state = LED_BLINK;
          led.blinkCount = 3;

          wakeUP = false;

          lastActionMillis = millis();

       }

       do {

          LED();

          debouncer.update();      // Update the Bounce instance

          // Wait for button being pressed
          if (debouncer.read() == HIGH) {
             if (millis() - lastActionMillis > 200) {
                if (led.state == LED_OFF || !LED_BLINK) {
                   sendToMaster(buttonNumber);
                }
             }

             lastActionMillis = millis();
          }

          //Go to sleep if no actions for some times
          if (millis() - lastActionMillis > SLEEP_DELAY) {
             sleepNow();   //Time to go to  sleep to save some power, wake up when button pressed
          }

       } while (!radio.available());

       radio.read(&Data_Received, sizeof(Data_Received));

       int order = Data_Received.msg;

       switch (Data_Received.msg) {

       case 0://test

          break;

       case 10://Make the led blinking
          led.state = LED_BLINK;
          led.blinkCount = 65000;
          led.brightness = 0;
          break;

       case 11://Turn light on
          led.state = LED_ON;
          break;

       case 12://Turn light off
          led.state = LED_OFF;
          break;

       case 55://Force to go to sleep
          sleepNow();
          break;

       case 66://Reset button
          led.state = LED_OFF;
          led.blinkCount = 0;
          break;
          break;

       case 99://Answer Hello I'm alive
          break;
       }
       lastActionMillis = millis();
    }

    //****************************************

    void setupRF24() {
       radio.setDataRate(RF24_250KBPS);
       radio.setPALevel(RF24_PA_MAX);
       radio.setChannel(125);
       radio.openReadingPipe(1, thisButtonAddress);
       radio.enableAckPayload();
       radio.setRetries(5, 15); // delay, count
       radio.startListening();
       radio.openWritingPipe(masterAddress);
    }
    //****************************************

    void sendToMaster(int cmd) {

       if (Data_Sent.rnd == 0) {
          srandom(random() ^ ((uint32_t)analogRead(4) << 22) ^ micros());
          Data_Sent.rnd = random(0, 5000);
       }
       else {
          Data_Sent.rnd++;
       }

       Data_Sent.msg = cmd;

       radio.stopListening();

       delay(10);

       radio.write(&Data_Sent, sizeof(Data_Sent));

       radio.startListening();
       
    }

    //****************************************

    void blinkLED() {
       unsigned long currentMillis = millis();

       if (currentMillis - previousMillis > BLINK_INTERVAL) {

          // save the last time you blinked the LED

          previousMillis = currentMillis;

          // set the LED with the ledState of the variable:
          digitalWrite(LED_PIN, ledState);

          ledState = !ledState;
       }
    }


    //****************************************

    void blinkLED(int d) {
       digitalWrite(LED_PIN, HIGH);
       delay(d);
       digitalWrite(LED_PIN, LOW);
    }

    //****************************************

    void blinkLED(int d, int t) {
       for (int i = 0; i < t; i++) {
          blinkLED(d);
          delay(d);
       }
    }

    //****************************************

    //Read the button number from the DIP switch
    void getButtonNr() {

       for (int i = 0; i < sizeof(DIPSwitchPins); ++i) {
          // Setup pin
          pinMode(DIPSwitchPins[i], INPUT_PULLUP);

          uint8_t curState = digitalRead(DIPSwitchPins[i]) ? 0 : 1;
          buttonNumber += (curState << i);
       }

       snprintf(thisButtonAddress, 6, "BTN%02d", buttonNumber);
    }

    //****************************************

    void LED() {

       unsigned long date = millis();
       int valeurPWM;

       switch (led.state) {

       case LED_OFF:
          analogWrite(LED_PIN, 0);
          break;

       case LED_ON:
          analogWrite(LED_PIN, LED_MAX_BRIGHTNESS);
          break;

       case LED_BLINK:
          if (date - led.lastStateChange >= led.blinkSpeed) {
             led.lastStateChange = date;

             switch (led.brightness) {
             case 0:
                led.brightness = 250;
                break;
             case 250:
                led.brightness = 0;
                led.blinkCount--;
                break;
             }
             analogWrite(LED_PIN, led.brightness);

             if (led.blinkCount == 0)
                led.state = LED_OFF;
          }
          break;
       }
    }

    //****************************************

    void wakeUpNow() {
       power_timer0_enable();
       power_timer1_enable();
       power_spi_enable();
       wakeUP = true;
    }

    //****************************************

    void sleepNow() { 

       radio.powerDown();

       blinkLED(300, 2);

       led.state = LED_OFF;

       attachInterrupt(2, wakeUpNow, CHANGE);

       power_timer0_disable();
       power_timer1_disable();
       power_spi_disable();

       set_sleep_mode(SLEEP_MODE_PWR_DOWN);

       sleep_enable();

       sleep_mode();

       sleep_disable();
                         
       detachInterrupt(2);

    }

HI !

Any news regarding why your RF module become slow after a deep sleep ?

Thanks

Regards

I’m not sure what causes that unfortunately.