RF24 Only Works Once

I'm trying to develop a remote control for my garage using 2 of Nanos, breakout boards and RF24s. It looked good for the first operation then proved to be consistently unreliable. My approach in these situations is to take it back to basics, ensure it works and then build on from there.
I used some Ralf Bacon example code, this generates a random number from 0 to 254 and transmits it. The receiver takes that value, increments it by 1 and passes it back. The serial port on the transmitter shows the incremented number. This works solidly and proves my wiring; firm foundations.
My remote control garage door is simpler. A button on the transmitter supplies 8 volts to the Arduino. All the code is in setup, it just creates and unsigned char, assigns 1 and writes it. Two LEDs (red and green) show if an acknowledgement was received or not.

The receiver reads the data and if it is 1 (which is should be) it currently lights an LED for a second to show it works.
First attempt: Press button on transmitter, green light shows an acknowledgement. The receiver LED goes on. Success!
Second and subsequent attempts: Press button on transmitter, green light shows an acknowledgement. The receiver light remains off.
Powering off the transmitter appears to stop the receiver working, even when the transmitter is powered on again.

Fixes
Powering off the receiver and powering it back on again allows one more press of the transmitter to work.
Powering the transmitter by the USB and then pressing reset will light the green light on the transmitter (an acknowledgement) and the light on the receiver. Remove the USB cable leaving it without power and then press the button to power it on and it works again. However once the power to the transmitter has been lost ,it works for one more button press and is then dysfunctional again.
Note: pressing the reset button on the receiver does not remedy anything, it only works by powering it down.

Note: If I power down the receiver and then press the button on the transmitter, the transmitter red light goes on, showing no acknowledgement was received. That proves the acknowledgement is working correctly.

I've put Serial.println's in my receiver code to see what is happening. Once everything is reset and the transmitter button is pressed, the serial window reports that the radio is available, the value of my data is 1 and then states Open.
However on a subsequent press of the transmitter button no text is displayed so radio.available is false. However I do get an acknowledgement LED on the transmitter

Here is the code for the transmitter

#include "Arduino.h"
#include <SPI.h>
#include <RF24.h>

// This is just the way the RF24 library works:
// Hardware configuration: Set up nRF24L01 radio on SPI bus (pins 10, 11, 12, 13) plus pins 7 & 8
RF24 radio(7, 8);

byte addresses[][6] = {"1Node", "2Node"};
const byte greenLed = 3;
const byte redLed = 4;

// -----------------------------------------------------------------------------
// SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP
// -----------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);
  Serial.println("THIS IS THE TRANSMITTER CODE - YOU NEED THE OTHER ARDIUNO TO SEND BACK A RESPONSE");
  pinMode(greenLed, OUTPUT);
  pinMode(redLed, OUTPUT);
  // Initiate the radio object
  radio.begin();

  // Set the transmit power to lowest available to prevent power supply related issues
  radio.setPALevel(RF24_PA_MIN);

  // Set the speed of the transmission to the quickest available
  radio.setDataRate(RF24_2MBPS);

  // Use a channel unlikely to be used by Wifi, Microwave ovens etc
  radio.setChannel(124);

  // Open a writing and reading pipe on each radio, with opposite addresses
  radio.openWritingPipe(addresses[1]);
  radio.openReadingPipe(1, addresses[0]);


  unsigned char data = 1;
  
  // Ensure we have stopped listening (even if we're not) or we won't be able to transmit
  radio.stopListening();

  Serial.println("About to transmit");
  // Did we manage to SUCCESSFULLY transmit that (by getting an acknowledgement back from the other Arduino)?
  // Even we didn't we'll continue with the sketch, you never know, the radio fairies may help us
  if (!radio.write( &data, sizeof(unsigned char) )) {
    Serial.println("No acknowledgement of transmission - receiving radio device connected?");
    digitalWrite(redLed, HIGH);
    delay(1000);
    digitalWrite(redLed, LOW);
  } else {
    Serial.println("Acknowledgement received");
    digitalWrite(greenLed, HIGH);
    delay(1000);
    digitalWrite(greenLed, LOW);
  }

}

void loop() {


}

Here is the code for my receiver

#include "Arduino.h"
#include <SPI.h>
#include <RF24.h>

// This is just the way the RF24 library works:
// Hardware configuration: Set up nRF24L01 radio on SPI bus (pins 10, 11, 12, 13) plus pins 7 & 8
RF24 radio(7, 8);
const byte led = 5;

byte addresses[][6] = {"1Node", "2Node"};

// -----------------------------------------------------------------------------
// SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP
// -----------------------------------------------------------------------------
void setup() {
  Serial.begin(9600);
  Serial.println("THIS IS THE RECEIVER CODE - YOU NEED THE OTHER ARDUINO TO TRANSMIT");
  //Set pin mode for LED
  pinMode(led, OUTPUT);


  // Initiate the radio object
  radio.begin();

  // Set the transmit power to lowest available to prevent power supply related issues
  radio.setPALevel(RF24_PA_MIN);

  // Set the speed of the transmission to the quickest available
  radio.setDataRate(RF24_2MBPS);

  // Use a channel unlikely to be used by Wifi, Microwave ovens etc
  radio.setChannel(124);

  // Open a writing and reading pipe on each radio, with opposite addresses
  radio.openWritingPipe(addresses[0]);
  radio.openReadingPipe(1, addresses[1]);

  // Start the radio listening for data
  radio.startListening();
}

// -----------------------------------------------------------------------------
// We are LISTENING on this device only (although we do transmit a response)
// -----------------------------------------------------------------------------
void loop() {

  // This is what we receive from the other device (the transmitter)
  //unsigned char data;

  // Is there any data for us to get?
  if ( radio.available()) {
    Serial.println("Radio is available");
    // Go and read the data and put it into that variable
    while (radio.available()) {
      unsigned char data;
      
      radio.read(&data, sizeof(char));
      Serial.print("My data is ");
      Serial.println(data);
      
      if (data == 1) {
      
        digitalWrite(led, HIGH);  //Switch it on
        delay(1000);   //wait a second
        digitalWrite(led, LOW);  //Switch it off
        Serial.print("Open ");   //flash the tx light
      }
    }

  }
}

I've really run into a brick wall. Any help would be greatly appreciated.

does not prove your LEDs are wired right... Can you share the wiring diagram?

so as soon as you release the button the power is shut off (arduino and nRF board)? how do you ensure there is enough time for the setup to complete?

Maybe also a delay, say 200mS before the radio.write() on the transmitter part to allow it to stabilize after the power up.

Thanks. On my original project I used a PNP MOSFET to with a voltage against the gate to keep it off. When the button was pressed it pulled that line to ground switching on the Nano which set a pin to high that went to an NPN MOSFET. This caused it to open, pulling the gate to the PNP MOSFET to ground and ensuring the NANO remained powered. Once the NANO had finished it's task, it set the NPN gate pin to LOW which caused a positive charge to go to the PNP gate and switched the NANO off again. When it did not work, I removed that complexity and just put a button in which passed current to the NANO VIN. This does risk switching off the NANO before it has completed the write. However I leave it pressed down until the acknowledgement LED goes green. I've tried holding it down for many seconds but it still fails.
Wiring diagram. Good call. I'll put something together. Thanks for your help

your button might be bouncing

That's a good ideal. I've put a 200ms delay but it is still the same.

Serial.println("About to transmit");
  // Did we manage to SUCCESSFULLY transmit that (by getting an acknowledgement back from the other Arduino)?
  // Even we didn't we'll continue with the sketch, you never know, the radio fairies may help us
  delay(200);
  if (!radio.write( &data, sizeof(unsigned char) )) {
    Serial.println("No acknowledgement of transmission - receiving radio device connected?");
    digitalWrite(redLed, HIGH);
    delay(1000);
    digitalWrite(redLed, LOW);
  } else {

Have increased that to 1000 but still the same.

That's worth trying; thanks. I'll put a 100nf capacitor in, along with a 10k resistor.

if the power goes through the button, the resistor will limit the current available

one way to check if this is the cause would be to add a button to your arduino, keep the system powered and use the button to trigger the message (and wait for button release)

something like this (typed here, untested of course)

#include "Arduino.h"
#include <SPI.h>
#include <RF24.h>

// This is just the way the RF24 library works:
// Hardware configuration: Set up nRF24L01 radio on SPI bus (pins 10, 11, 12, 13) plus pins 7 & 8
RF24 radio(7, 8);

byte addresses[][6] = {"1Node", "2Node"};
const byte greenLed = 3;
const byte redLed = 4;

const byte buttonPin = 2;

// -----------------------------------------------------------------------------
// SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP
// -----------------------------------------------------------------------------
void setup() {
  pinMode(greenLed, OUTPUT);
  pinMode(redLed, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);

  Serial.begin(9600);
  Serial.println("THIS IS THE TRANSMITTER CODE - YOU NEED THE OTHER ARDIUNO TO SEND BACK A RESPONSE");

  // Initiate the radio object
  radio.begin();

  // Set the transmit power to lowest available to prevent power supply related issues
  radio.setPALevel(RF24_PA_MIN);

  // Set the speed of the transmission to the quickest available
  radio.setDataRate(RF24_2MBPS);

  // Use a channel unlikely to be used by Wifi, Microwave ovens etc
  radio.setChannel(124);

  // Open a writing and reading pipe on each radio, with opposite addresses
  radio.openWritingPipe(addresses[1]);
  radio.openReadingPipe(1, addresses[0]);
  // Ensure we have stopped listening (even if we're not) or we won't be able to transmit
  radio.stopListening();
}

void loop() {
  if (digitalRead(buttonPin) == LOW) { // button pressed
    delay(15); // poor's man anti-bouce
    unsigned char data = 1;
    Serial.println("About to transmit");
    // Did we manage to SUCCESSFULLY transmit that (by getting an acknowledgement back from the other Arduino)?
    // Even we didn't we'll continue with the sketch, you never know, the radio fairies may help us
    if (!radio.write( &data, sizeof(unsigned char) )) {
      Serial.println("No acknowledgement of transmission - receiving radio device connected?");
      digitalWrite(redLed, HIGH);
      delay(1000);
      digitalWrite(redLed, LOW);
    } else {
      Serial.println("Acknowledgement received");
      digitalWrite(greenLed, HIGH);
      delay(1000);
      digitalWrite(greenLed, LOW);
    }

    while (digitalRead(buttonPin) == LOW); // active wait until button is released
    delay(15); // poor's man anti-bouce
  }
}

(button would be on pin 2 set as input pull-up , wired this way: pin 2 <---> button <----> GND)

These nRF24L01 devices are tricky enough as it is, with multiple problem reports per week appearing in this forum, and usually insufficient power is the issue.
The modules which are described as nRF24L01+PA+LNA are usually worse in this respect.

Which model have you purchased ?
When the transmitter is not powered via the USB cable, how is it powered ?

The 200ms that I suggested came from the datasheet https://www.sparkfun.com/datasheets/Components/SMD/nRF24L01Pluss_Preliminary_Product_Specification_v1_0.pdf ch 6.1.1 where a 100ms following a power on reset is required. Some clones/fakes may behave differently.

The packet states NRF24L01. I purchased ASHATA NRF24L01+ Breakout Adapter as it has a voltage regulator down to 3.3 and a capacitor to smooth out the input power. Running code in the loop which transmits every second and then get a response from the receiver works all day long. To take button bounce out of the frame I've done some more experiments. Switch both receiver and transmitter off. Power up the receiver using a transformer. Plug a USB cable into the transmitter. You get a flash response from the receiver and the acknowledgement LED flashes for a second. Pull the USB cable out of the transmitter, count to 5 and plug it back in again. The transmitter acknowledgement LED lights for a second but the receiver does not flash a response. After the first operation, if the transmitter is switched off, the receiver will acknowledge the transmission but not process the instruction. Radio.available returns false. I'm wondering if I should clear the receive buffer with flush_rx.

On the hypothesis that the transmitter part may be retaining some sort of status information during the short USB disconnects, you could try the following:

  1. An explicit radio.powerDown(); at the end of setup.
  2. If that fails, put a 1k bleed resistor between the Vcc of the nRF24L01 module and ground.

Here is my "usual suspects" for rf24 radio problems. Some have already been covered.

If you read and, closely, follow Robin2's simple rf24 tutorial you should be able to get them working. That tutorial sure helped me. Run the CheckConnection.ino (look in reply #30) to verify wiring between the radio module and its processor (Arduino).

Make sure the rf24 power supply can provide enough current. I use homemade adapters like these. They are powered by 5V and have a 3.3V regulator on the board.

If using the high powered radios make sure to separate them by a few meters. The may not work too close together.

Reset the radios by cycling power to them after uploading new code. I have found that to help. They do not reset with the Arduino.

Switch to 1MB data rate to catch the not so cloned clones.

well, OP did some homework on this before posting here. Here is what he said:

so we could assume that the powering and wiring of the rf24 is OK as his setup code is largely coming from Ralf Bacon example code


would be good to hear if the system shows the same issue if the Arduino is powered continuously and when transmission is triggered by a momentary switch. (code offered in #8 to test)

Thanks everyone. I've been called away for the weekend but will be returning to my home workbench tomorrow morning. Will try some of these useful suggestions and come back to you. I'm determined to resolve this and really appreciate all your help.

My approach has been to break the solution into it's smallest workable form. I breadboarded a new simple solution. No MOSFETS, just code that transmits a char array of "Open" for the other unit to receive and flash a light for one second. That worked fine, the serial window and light confirming it works in a loop.
On the transmitter I put a button on the VIN wire so it was powered when depressed.
Pressing this button (for plenty of time) caused the same thing to happen (looping around transmitting happily).
As I did not want my garage door to shoot up and down all day I used a boolean so the loop only ran once. It transmits "Open" sets the boolean to false and does not run again (until powered off and on again).
I pressed the button (for a long time) on the transmitter, the light on the receiver flashed to confirm success and the button was then released. Success.
However pressing the transmitter button (for a long time) again provides no response. At that point it fails.
The receiver does nothing, not even fire a println statement after a 'if (radio.available) ' statement.
Power off the receiver and back on again and it works; but only the once.
As I only need it to run once I moved all the code to Setup and left Loop empty. Still would not work on attempt 2.
So it works if you send a constant stream of transmissions but not if you send one and then power off the transmitter.
I tried flushing the receiver but it made no difference.
As multiple transmissions appeared to work, I transmitted the Char with a value of "Open" followed by a 250ms delay, then used strcpy changing Char to "Shut" and transmit that.
The conditional statement in the receiver gets the "Open" transmission and flashes the light. It then receives the "Shut" transmission and ignores it as there are no instructions to do anything with it.
However when you press the transmitter button again the receiver light flashes every time.
Conclusion: The wiring and power supply shows all is well. Sending one transmission and powering the transmitter off appears to lock the receiver. I sort of have a solution but can't see why it did not work in the first instance. If anyone can shed any light on the reason for this failure I'd be very grateful. Thanks to everyone who helped me with suggestions on this issue.

Hello
I have the same problem. Any solution?

You are using the exact same Arduino, hardware and code as the OP ?

Receiver:

//Include Libraries
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(9, 8);  // CE, CSN

const byte address[6] = "00001";

void setup()
{
    Serial.begin(9600);
  radio.begin();
  radio.setRetries(0,0);
  radio.setChannel(5);
  radio.setPALevel(RF24_PA_MIN);
  radio.openReadingPipe(0, address);
  radio.startListening();
}

void loop()
{
  if (radio.available())
  {
    char text[32] = {0};
    radio.read(&text, sizeof(text));
    Serial.println(text);
  }
}

Transmiter:

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

RF24 radio(7, 6);  // CE, CSN RF24 radio(9, 8);

const byte address[6] = "00001";

void setup()
{
  radio.begin();
  radio.setRetries(0,0);
  radio.setChannel(5);
  radio.setPALevel(RF24_PA_MIN);
  radio.openWritingPipe(address);
  radio.stopListening();
  const char text2[] = "Hello World";
  radio.write(&text2, sizeof(text2));
}
void loop()
{

}

I turn on the receiver, then turn on the transmitter and the receiver receives. I turn off the transmitter and after a while I turn it on again. The receiver is no longer receive. From now on, no matter how many times I turn the transmitter on and off, the receiver does not receive data. If I turn the receiver off and on, it receives data once when the transmitter is turned on.
If I send twice:

  const char text[] = "Hello World";
  radio.write(&text, sizeof(text));
  const char text2[] = "Hello World";
  radio.write(&text2, sizeof(text2));

the second send is always received by the receiver, but this option does not suit me. Different configuration of the "radio.setRetries (0,0);" function; does not affect.

try changing this part from the transmitter to:
const char text2[32] = "Hello World";

Very quick response. I will check and return an answer as soon as possible.