NRF24L01 can't manage to send information

Hello everyone,
I am trying to make this module work to send information from one Arduino Uno to an Arduino Mega. I am using the library available in this link.

When running the pingpair_test example code on both Arduinos, I get the following response:
In the sender Arduino, I get:


RF24/tests/pingpair_test/

ROLE: Sender

+READY press any key to start


Configuration	 = 

SPI Speedz	= 10 Mhz
STATUS		= 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1	= 0xe8e8f0f0e1 0xc2c2c2c2c2
RX_ADDR_P2-5	= 0xc3 0xc4 0xc5 0xe1
TX_ADDR		= 0xe8e8f0f0e1
RX_PW_P0-6	= 0x20 0x20 0x20 0x20 0x20 0x20
EN_AA		= 0x3f
EN_RXADDR	= 0x23
RF_CH		= 0x5a
RF_SETUP	= 0x07
CONFIG		= 0x0e
DYNPD/FEATURE	= 0x3f 0x06
Data Rate	= 1 MBPS
Model		= nRF24L01+
CRC Length	= 16 bits
PA Power	= PA_MAX
ARC		= 0


Now sending length 4...No responses received.  Are interrupts connected??

Send:Failed 

+OK FAIL

In the receiver, I get:


RF24/tests/pingpair_test/

ROLE: Receiver

+READY press any key to start


Configuration	 = 

SPI Speedz	= 10 Mhz
STATUS		= 0x7f RX_DR=1 TX_DS=1 MAX_RT=1 RX_P_NO=7 TX_FULL=1
RX_ADDR_P0-1	= 0xffffffffff 0xffffffffff
RX_ADDR_P2-5	= 0xff 0xff 0xff 0xff
TX_ADDR		= 0xffffffffff
RX_PW_P0-6	= 0xff 0xff 0xff 0xff 0xff 0xff
EN_AA		= 0xff
EN_RXADDR	= 0xff
RF_CH		= 0xff
RF_SETUP	= 0xff
CONFIG		= 0xff
DYNPD/FEATURE	= 0xff 0xff
Data Rate	= 1 MBPS
Model		= nRF24L01+
CRC Length	= 16 bits
PA Power	= PA_MAX
ARC		= 15


+OK 

On both modules I have connected the IRQ pin to the pin D2. What should I do?

Looks like either you have the receiver wired wrong or its faulty.

Note all the 0xffffffffff in the receiver configuration where as the transmitter configuration looks OK.

I am using the reciever with an Arduino Mega.

I have connected:
GND --> GND
VCC --> 3.3V
CE --> 9
CSN --> 53
SCK --> 52
MOSI --> 51
MISO --> 50
IRQ --> 2

Hi @arturo_olvrs,

Definitely place a electrolytic capacitor of at least 10µF as close as possible to the nrf24l01 from the 3.3v to the gnd on the receiver and the transmitter. These modules are known to be very finicky and I have had lots of issues myself with them. Maybe try moving your wiring to different pins if you are using a breadboard.

Did you check the actual connections with a multimeter ?

Have you tried the transmitter module in the same location as the (possibly faulty) receiver ?

@arturo_olvrs code:

/*
 Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 version 2 as published by the Free Software Foundation.
 */

/**
 * Full test on single RF pair
 *
 * This sketches uses as many RF24 methods as possible in a single test.
 *
 * To operate:
 *  Upload this sketch on two nodes, each with IRQ -> pin 2
 *  One node needs pin 7 -> GND, the other NC.  That's the receiving node
 *  Monitor the sending node's serial output
 *  Look for "+OK PASS" or "+OK FAIL"
 */

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

//
// Hardware configuration
//

// Set up nRF24L01 radio on SPI bus plus pins 8 & 9

RF24 radio(7, 8);

// sets the role of this unit in hardware.  Connect to GND to be the 'pong' receiver
// Leave open to be the 'ping' transmitter
const short role_pin = 5;

//
// Topology
//

// Single radio pipe address for the 2 nodes to communicate.
const uint64_t pipe = 0xE8E8F0F0E1LL;

//
// Role management
//
// Set up role.  This sketch uses the same software for all the nodes in this
// system.  Doing so greatly simplifies testing.  The hardware itself specifies
// which node it is.
//
// This is done through the role_pin
//

// The various roles supported by this sketch
typedef enum {
    role_sender = 1,
    role_receiver
} role_e;

// The debug-friendly names of those roles
const char* role_friendly_name[] = {"invalid", "Sender", "Receiver"};

// The role of the current running sketch
role_e role;

// Interrupt handler, check the radio because we got an IRQ
void check_radio(void);

//
// Payload
//

const int min_payload_size = 4;
const int max_payload_size = 32;
int payload_size_increments_by = 2;
int next_payload_size = min_payload_size;

char receive_payload[max_payload_size + 1]; // +1 to allow room for a terminating NULL char

//
// Test state
//

bool done; //*< Are we done with the test? */
bool passed; //*< Have we passed the test? */
bool notified; //*< Have we notified the user we're done? */
const int num_needed = 10; //*< How many success/failures until we're done? */
int receives_remaining = num_needed; //*< How many ack packets until we declare victory? */
int failures_remaining = num_needed; //*< How many more failed sends until we declare failure? */
const int interval = 100; //*< ms to wait between sends */

char configuration = '1'; //*< Configuration key, one char sent in by the test framework to tell us how to configure, this is the default */

uint8_t pipe_number = 1; // Which pipe to send on.

void one_ok(void)
{
    // Have we received enough yet?
    if (!--receives_remaining) {
        done = true;
        passed = true;
    }
}

void one_failed(void)
{
    // Have we failed enough yet?
    if (!--failures_remaining) {
        done = true;
        passed = false;
    }
}

//
// Setup
//

void setup(void)
{
    //
    // Role
    //

    // set up the role pin
    pinMode(role_pin, INPUT);
    digitalWrite(role_pin, HIGH);
    delay(20); // Just to get a solid reading on the role pin

    // read the address pin, establish our role
    if (digitalRead(role_pin)) {
        role = role_sender;
    } else {
        role = role_receiver;
    }

    //
    // Print preamble
    //

    Serial.begin(115200);
    printf_begin();
    printf("\n\rRF24/tests/pingpair_test/\n\r");
    printf("ROLE: %s\n\r", role_friendly_name[role]);

    //
    // Read configuration from serial
    //
    // It would be a much better test if this program could accept configuration
    // from the serial port.  Then it would be possible to run the same test under
    // lots of different circumstances.
    //
    // The idea is that we will print "+READY" at this point.  The python script
    // will wait for it, and then send down a configuration script that we
    // execute here and then run with.
    //
    // The test controller will need to configure the receiver first, then go run
    // the test on the sender.
    //

    printf("+READY press any key to start\n\r\n\r");

    while (!Serial.available()) {
    }
    configuration = Serial.read();
    printf("Configuration\t = %c\n\r", configuration);

    //
    // Setup and configure rf radio
    //

    radio.begin();

    // We will be using the Ack Payload feature, so please enable it
    radio.enableAckPayload();
    radio.enableDynamicPayloads();  // needed for using ACK payloads

    // Config 2 is special radio config
    if (configuration == '2'){
        radio.setCRCLength(RF24_CRC_8);
        radio.setDataRate(RF24_250KBPS);
        radio.setChannel(10);
    }else{
        //Otherwise, default radio config

        // Optional: Increase CRC length for improved reliability
        radio.setCRCLength(RF24_CRC_16);

        // Optional: Decrease data rate for improved reliability
        radio.setDataRate(RF24_1MBPS);

        // Optional: Pick a high channel
        radio.setChannel(90);
    }

    // Config 3 is static payloads only
    if (configuration == '3'){
        next_payload_size = 16;
        payload_size_increments_by = 0;
        radio.setPayloadSize(next_payload_size);
    }else{
        // enable dynamic payloads
        radio.enableDynamicPayloads();
    }

    // Config 4 tests out a higher pipe ##
    if (configuration == '4' && role == role_sender){
        // Set top 4 bytes of the address in pipe 1
        radio.openReadingPipe(1, pipe & 0xFFFFFFFF00ULL);

        // indicate the pipe to use
        pipe_number = 5;
    }else if (role == role_sender){
        radio.openReadingPipe(5, 0);
    }

    //
    // Open pipes to other nodes for communication
    //

    // This simple sketch opens a single pipe for these two nodes to communicate
    // back and forth.  One listens on it, the other talks to it.

    if (role == role_sender){
        radio.openWritingPipe(pipe);
    }else{
        radio.openReadingPipe(pipe_number, pipe);
    }

    //
    // Start listening
    //

    if (role == role_receiver){
        radio.startListening();
    }

    //
    // Dump the configuration of the rf unit for debugging
    //

    radio.printDetails();

    //
    // Attach interrupt handler to interrupt #0 (using pin 2)
    // on BOTH the sender and receiver
    //

    attachInterrupt(0, check_radio, FALLING);
    delay(50);
    if (role == role_receiver){
        printf("\n\r+OK ");
    }
}

//
// Print buffer
//
// Printing from the interrupt handler is a bad idea, so we print from there
// to this intermediate buffer
//

char prbuf[1000];
char* prbuf_end = prbuf + sizeof(prbuf);
char* prbuf_in = prbuf;
char* prbuf_out = prbuf;

//
// Loop
//

static uint32_t message_count = 0;
static uint32_t last_message_count = 0;

void loop(void){
    //
    // Sender role.  Repeatedly send the current time
    //

    if (role == role_sender && !done){
        // The payload will always be the same, what will change is how much of it we send.
        static char send_payload[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ789012";

        // First, stop listening so we can talk.
        radio.stopListening();

        // Send it.  This will block until complete
        printf("\n\rNow sending length %i...", next_payload_size);
        radio.startWrite(send_payload, next_payload_size, 0);

        // Update size for next time.
        next_payload_size += payload_size_increments_by;
        if (next_payload_size > max_payload_size){
            next_payload_size = min_payload_size;
        }

        // Try again soon
        delay(interval);

        // Timeout if we have not received anything back ever
        if (!last_message_count && millis() > interval * 100){
            printf("No responses received.  Are interrupts connected??\n\r");
            done = true;
        }
    }

    //
    // Receiver role: Does nothing!  All the work is in IRQ
    //

    //
    // Spew print buffer
    //

    size_t write_length = prbuf_in - prbuf_out;
    if (write_length){
        Serial.write(reinterpret_cast<uint8_t*>(prbuf_out), write_length);
        prbuf_out += write_length;
    }

    //
    // Stop the test if we're done and report results
    //
    if (done && !notified){
        notified = true;

        printf("\n\r+OK ");
        if (passed){
            printf("PASS\n\r\n\r");
        }else{
            printf("FAIL\n\r\n\r");
        }
    }
}

void check_radio(void)
{
    // What happened?
    bool tx, fail, rx;
    radio.whatHappened(tx, fail, rx);

    // Have we successfully transmitted?
    if (tx){
        if (role == role_sender){
            prbuf_in += sprintf(prbuf_in, "Send:OK ");
        }

        if (role == role_receiver){
            prbuf_in += sprintf(prbuf_in, "Ack Payload:Sent\n\r");
        }
    }

    // Have we failed to transmit?
    if (fail){
        if (role == role_sender){
            prbuf_in += sprintf(prbuf_in, "Send:Failed ");

            // log status of this line
            one_failed();
        }

        if (role == role_receiver){
            prbuf_in += sprintf(prbuf_in, "Ack Payload:Failed\n\r");
        }
    }

    // Not powering down since radio is in standby mode
    //if (( tx || fail ) && ( role == role_sender )){ radio.powerDown(); }

    // Did we receive a message?
    if (rx){
        // If we're the sender, we've received an ack payload
        if (role == role_sender){
            radio.read(&message_count, sizeof(message_count));
            prbuf_in += sprintf(prbuf_in, "Ack:%lu ", message_count);

            // is this ack what we were expecting?  to account
            // for failures, we simply want to make sure we get a
            // DIFFERENT ack every time.
            if ((message_count != last_message_count) || (configuration == '3' && message_count == 16)){
                prbuf_in += sprintf(prbuf_in, "OK ");
                one_ok();
            }else{
                prbuf_in += sprintf(prbuf_in, "FAILED ");
                one_failed();
            }
            last_message_count = message_count;
        }

        // If we're the receiver, we've received a time message
        if (role == role_receiver){
            // Get this payload and dump it
            size_t len = max_payload_size;
            memset(receive_payload, 0, max_payload_size);

            if (configuration == '3'){
                len = next_payload_size;
            }else{
                len = radio.getDynamicPayloadSize();
            }

            radio.read(receive_payload, len);

            // Put a zero at the end for easy printing
            receive_payload[len] = 0;

            // Spew it
            prbuf_in += sprintf(prbuf_in, "Recv size=%i val=%s len=%u\n\r", len, receive_payload, strlen(receive_payload));

            // Add an ack packet for the next time around.
            // Here we will report back how many bytes we got this time.
            radio.writeAckPayload(pipe_number, &len, sizeof(len));

            ++message_count;
        }
    }
}

I have now tried connecting the possibly faulty reciever to an Arduino Uno using the same connection as I had previously done with the other Arduino Uno.

The message I get now on the reciever is:


RF24/tests/pingpair_test/

ROLE: Receiver

+READY press any key to start


Configuration	 = 

SPI Speedz	= 10 Mhz
STATUS		= 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1	= 0xe7e7e7e7e7 0xe8e8f0f0e1
RX_ADDR_P2-5	= 0xc3 0xc4 0xc5 0xc6
TX_ADDR		= 0xe7e7e7e7e7
RX_PW_P0-6	= 0x20 0x20 0x20 0x20 0x20 0x20
EN_AA		= 0x3f
EN_RXADDR	= 0x02
RF_CH		= 0x5a
RF_SETUP	= 0x07
CONFIG		= 0x0f
DYNPD/FEATURE	= 0x3f 0x06
Data Rate	= 1 MBPS
Model		= nRF24L01+
CRC Length	= 16 bits
PA Power	= PA_MAX
ARC		= 0


+OK 

The message I get on the transmitter is:


RF24/tests/pingpair_test/

ROLE: Sender

+READY press any key to start


Configuration	 = 

SPI Speedz	= 10 Mhz
STATUS		= 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1	= 0xe8e8f0f0e1 0xc2c2c2c2c2
RX_ADDR_P2-5	= 0xc3 0xc4 0xc5 0xe1
TX_ADDR		= 0xe8e8f0f0e1
RX_PW_P0-6	= 0x20 0x20 0x20 0x20 0x20 0x20
EN_AA		= 0x3f
EN_RXADDR	= 0x23
RF_CH		= 0x5a
RF_SETUP	= 0x07
CONFIG		= 0x0e
DYNPD/FEATURE	= 0x3f 0x06
Data Rate	= 1 MBPS
Model		= nRF24L01+
CRC Length	= 16 bits
PA Power	= PA_MAX
ARC		= 0


Now sending length 4...

Now sending length 6...

Now sending length 8...

Now sending length 10...

Now sending length 12...

Now sending length 14...

Now sending length 16...

Now sending length 18...

Now sending length 20...

Now sending length 22...

Now sending length 24...

Now sending length 26...

Now sending length 28...

Now sending length 30...

Now sending length 32...

Now sending length 4...

Now sending length 6...

Now sending length 8...

Now sending length 10...

Now sending length 12...

Now sending length 14...

Now sending length 16...

Now sending length 18...

Now sending length 20...

Now sending length 22...

Now sending length 24...

Now sending length 26...

Now sending length 28...

Now sending length 30...

Now sending length 32...

Now sending length 4...

Now sending length 6...

Now sending length 8...

Now sending length 10...

Now sending length 12...

Now sending length 14...

Now sending length 16...

Now sending length 18...

Now sending length 20...

Now sending length 22...

Now sending length 24...

Now sending length 26...

Now sending length 28...

Now sending length 30...

Now sending length 32...

Now sending length 4...

Now sending length 6...

Now sending length 8...

Now sending length 10...

Now sending length 12...

Now sending length 14...

Now sending length 16...

Now sending length 18...

Now sending length 20...

Now sending length 22...

Now sending length 24...

Now sending length 26...

Now sending length 28...

Now sending length 30...

Now sending length 32...

Now sending length 4...

Now sending length 6...

Now sending length 8...

Now sending length 10...

Now sending length 12...

Now sending length 14...

Now sending length 16...No responses received.  Are interrupts connected??


+OK FAIL

What should I do? As I said, IRQ is connected to D2.

Looks like you may have 'fixed' some dodgy wiring by moving things around.

Now you need to connect each of the NRF24s to a decent 3.3V power supply, the 3.3V supply on the Mega and UNO is not really designed to run transmitters.

I have just connected it to an external voltage supplier and I still get the same error...

Then follow this tutorial, in detail;

I have worked with a lot of nrf's and have faced numerous problems at times.
Simple NRf tutorial is like the master key for starting to solve the problem from root.

Your case looks a little complicated maybe because you are not able to get things done properly. Follow this tutorial and start from checking the connections and wiring.

Here are some advices from my experience:

  1. Utilise the builtin library functions for checking if Nrf is connected properly .(i.e. isChipConnected() ).
  2. Try to keep some distance between both nrf's .
  3. Keep connection wires short in length .
  4. Use Ack packet functionality to keep check on connection.
  5. Use a good power source (Uno and mega's built-in would do in some cases)
  6. Avoid silly mistakes in program( eg. different codes copied from internet give different response packets which newbies find hard to solve)
  7. Check for burnt modules .(check for heating and power consumption)
  8. First establish connection using basic code before moving to complex data transfer or tasks.
    Try the above and tell if that resolves.
1 Like

I still have the same problem. It does not send me any error message. I connect them correctly, and I have bought a voltage adapter so that I do not burn the modules. In addition, it comes with a capacitor inside. Therefore, I doubt that the problem is there.

The message that I was trying to send was received, but only once. What can the problem be? Does this module produce a lot of errors? Is there any modules or different ways of wireless communication that does not produce so many errors?

Make sure the transmitter and receiver address are the same (at PIPE0)

RX_ADDR_P0-1 = 0xe7e7e7e7e7 0xe8e8f0f0e1
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xe7e7e7e7e7

RX_ADDR_P0-1 = 0xe8e8f0f0e1 0xc2c2c2c2c2
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xe1
TX_ADDR = 0xe8e8f0f0e1

I am opening radio.openReadingPipe(1,0xE8E8F0F0E1LL) in the receiver node and radio.openWritingPipe(0xE8E8F0F0E1LL) in the sender node.

As I said, I received the message once.

When you receive a message, just to test, clear the RX_DR bit in the STATUS register and flush the RX FIFO. You have to look at the library on how to do that though. The NRF24 stops receiving if the RX_DR bit is not cleared or the RX_FIFO is full...

This is the code I am uploading to both Arduinos, each Arduino connected to one computer. This is the example code of the library with some modifications, as the one made to flush the RX FIFO.

This tries to send the information but I keep receiving the FAIL error. What should I do?

/*
 Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 version 2 as published by the Free Software Foundation.
 */

/**
 * Full test on single RF pair
 *
 * This sketches uses as many RF24 methods as possible in a single test.
 *
 * To operate:
 *  Upload this sketch on two nodes, each with IRQ -> pin 2
 *  One node needs pin 7 -> GND, the other NC.  That's the receiving node
 *  Monitor the sending node's serial output
 *  Look for "+OK PASS" or "+OK FAIL"
 */

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

//
// Hardware configuration
//

// Set up nRF24L01 radio on SPI bus plus pins 8 & 9

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

// sets the role of this unit in hardware.  Connect to GND to be the 'pong' receiver
// Leave open to be the 'ping' transmitter
const short role_pin = 5;

//
// Topology
//

// Single radio pipe address for the 2 nodes to communicate.
const uint64_t pipe = 0xE8E8F0F0E1LL; ///0xCCCECCCECC

//
// Role management
//
// Set up role.  This sketch uses the same software for all the nodes in this
// system.  Doing so greatly simplifies testing.  The hardware itself specifies
// which node it is.
//
// This is done through the role_pin
//

// The various roles supported by this sketch
typedef enum {
    role_sender = 1,
    role_receiver
} role_e;

// The debug-friendly names of those roles
const char* role_friendly_name[] = {"invalid", "Sender", "Receiver"};

// The role of the current running sketch
role_e role;

// Interrupt handler, check the radio because we got an IRQ
void check_radio(void);

//
// Payload
//

const int min_payload_size = 4;
const int max_payload_size = 32;
int payload_size_increments_by = 2;
int next_payload_size = min_payload_size;

char receive_payload[max_payload_size + 1]; // +1 to allow room for a terminating NULL char

//
// Test state
//

bool done; //*< Are we done with the test? */
bool passed; //*< Have we passed the test? */
bool notified; //*< Have we notified the user we're done? */
const int num_needed = 10; //*< How many success/failures until we're done? */
int receives_remaining = num_needed; //*< How many ack packets until we declare victory? */
int failures_remaining = num_needed; //*< How many more failed sends until we declare failure? */
const int interval = 100; //*< ms to wait between sends */

char configuration = '1'; //*< Configuration key, one char sent in by the test framework to tell us how to configure, this is the default */

uint8_t pipe_number = 1; // Which pipe to send on. ///////////////////////////////////////

void one_ok(void)
{
    // Have we received enough yet?
    if (!--receives_remaining) {
        done = true;
        passed = true;
    }
}

void one_failed(void)
{
    // Have we failed enough yet?
    if (!--failures_remaining) {
        done = true;
        passed = false;
    }
}

//
// Setup
//

void setup(void)
{
    //
    // Role
    //

    // set up the role pin
    pinMode(role_pin, INPUT);
    digitalWrite(role_pin, HIGH);
    delay(20); // Just to get a solid reading on the role pin

    // read the address pin, establish our role
    if (digitalRead(role_pin)) {
        role = role_sender;
    } else {
        role = role_receiver;
    }

    //
    // Print preamble
    //

    Serial.begin(115200);
    printf_begin();
    printf("\n\rRF24/tests/pingpair_test/\n\r");
    printf("ROLE: %s\n\r", role_friendly_name[role]);

    //
    // Read configuration from serial
    //
    // It would be a much better test if this program could accept configuration
    // from the serial port.  Then it would be possible to run the same test under
    // lots of different circumstances.
    //
    // The idea is that we will print "+READY" at this point.  The python script
    // will wait for it, and then send down a configuration script that we
    // execute here and then run with.
    //
    // The test controller will need to configure the receiver first, then go run
    // the test on the sender.
    //

    printf("+READY press any key to start\n\r\n\r");

    while (!Serial.available()) {
    }
    configuration = Serial.read();
    printf("Configuration\t = %c\n\r", configuration);

    //
    // Setup and configure rf radio
    //

    if (!radio.begin()) {
       Serial.println(F("radio hardware not responding!"));
       while (1) {} // hold program in infinite loop to prevent subsequent errors
    }
    
    if (!radio.isChipConnected()) {
           Serial.println(F("Chip not connected."));
           while (1) {} // hold program in infinite loop to prevent subsequent errors
        }
    

    // We will be using the Ack Payload feature, so please enable it
    radio.enableAckPayload();
    radio.enableDynamicPayloads();  // needed for using ACK payloads

    // Config 2 is special radio config
    if (configuration == '2'){
        radio.setCRCLength(RF24_CRC_8);
        radio.setDataRate(RF24_250KBPS);
        radio.setChannel(10);
    }else{
        //Otherwise, default radio config

        // Optional: Increase CRC length for improved reliability
        radio.setCRCLength(RF24_CRC_16);

        // Optional: Decrease data rate for improved reliability
        radio.setDataRate(RF24_1MBPS);

        // Optional: Pick a high channel
        radio.setChannel(90);
    }

    // Config 3 is static payloads only
    if (configuration == '3'){
        next_payload_size = 16;
        payload_size_increments_by = 0;
        radio.setPayloadSize(next_payload_size);
    }else{
        // enable dynamic payloads
        radio.enableDynamicPayloads();
    }

    // Config 4 tests out a higher pipe ##
    if (configuration == '4' && role == role_sender){
        // Set top 4 bytes of the address in pipe 1
        radio.openReadingPipe(1, 0xFFFFFFFF00ULL);

        // indicate the pipe to use
        pipe_number = 5;
    }else if (role == role_sender){
        radio.openReadingPipe(5, 0xFFFFFFFF00ULL);
    }

    //
    // Open pipes to other nodes for communication
    //

    // This simple sketch opens a single pipe for these two nodes to communicate
    // back and forth.  One listens on it, the other talks to it.

    if (role == role_sender){
        radio.openWritingPipe(pipe);
    }else{
        radio.openReadingPipe(pipe_number, pipe);
    }

    //
    // Start listening
    //

    if (role == role_receiver){
        radio.startListening();
    }

    //
    // Dump the configuration of the rf unit for debugging
    //

    radio.printDetails();

    //
    // Attach interrupt handler to interrupt #0 (using pin 2)
    // on BOTH the sender and receiver
    //

    attachInterrupt(0, check_radio, FALLING);
    delay(50);
    if (role == role_receiver){
        printf("\n\r+OK ");
    }
}

//
// Print buffer
//
// Printing from the interrupt handler is a bad idea, so we print from there
// to this intermediate buffer
//

char prbuf[1000];
char* prbuf_end = prbuf + sizeof(prbuf);
char* prbuf_in = prbuf;
char* prbuf_out = prbuf;

//
// Loop
//

static uint32_t message_count = 0;
static uint32_t last_message_count = 0;

void loop(void){
    //
    // Sender role.  Repeatedly send the current time
    //

    if (role == role_sender && !done){
        // The payload will always be the same, what will change is how much of it we send.
        static char send_payload[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ789012";

        // First, stop listening so we can talk.
        radio.stopListening();

        // Send it.  This will block until complete
        printf("\n\rNow sending length %i...", next_payload_size);
        radio.startWrite(send_payload, next_payload_size, 0);

        // Update size for next time.
        next_payload_size += payload_size_increments_by;
        if (next_payload_size > max_payload_size){
            next_payload_size = min_payload_size;
        }

        // Try again soon
        delay(interval);

        // Timeout if we have not received anything back ever
        if (!last_message_count && millis() > interval * 100){
            printf("No responses received.  Are interrupts connected??\n\r");
            done = true;
        }
    }

    //
    // Receiver role: Does nothing!  All the work is in IRQ
    //
    if (role == role_sender && !done){
      radio.flush_rx();
    }
    //
    // Spew print buffer
    //

    size_t write_length = prbuf_in - prbuf_out;
    if (write_length){
        Serial.write(reinterpret_cast<uint8_t*>(prbuf_out), write_length);
        prbuf_out += write_length;
    }

    //
    // Stop the test if we're done and report results
    //
    if (done && !notified){
        notified = true;

        printf("\n\r+OK ");
        if (passed){
            printf("PASS\n\r\n\r");
        }else{
            printf("FAIL\n\r\n\r");
        }
    }
}

void check_radio(void)
{
    // What happened?
    bool tx, fail, rx;
    radio.whatHappened(tx, fail, rx);

    // Have we successfully transmitted?
    if (tx){
        if (role == role_sender){
            prbuf_in += sprintf(prbuf_in, "Send:OK ");
        }

        if (role == role_receiver){
            prbuf_in += sprintf(prbuf_in, "Ack Payload:Sent\n\r");
        }
    }

    // Have we failed to transmit?
    if (fail){
        if (role == role_sender){
            prbuf_in += sprintf(prbuf_in, "Send:Failed ");

            // log status of this line
            one_failed();
        }

        if (role == role_receiver){
            prbuf_in += sprintf(prbuf_in, "Ack Payload:Failed\n\r");
        }
    }

    // Not powering down since radio is in standby mode
    //if (( tx || fail ) && ( role == role_sender )){ radio.powerDown(); }

    // Did we receive a message?
    if (rx){
        // If we're the sender, we've received an ack payload
        if (role == role_sender){
            radio.read(&message_count, sizeof(message_count));
            prbuf_in += sprintf(prbuf_in, "Ack:%lu ", message_count);

            // is this ack what we were expecting?  to account
            // for failures, we simply want to make sure we get a
            // DIFFERENT ack every time.
            if ((message_count != last_message_count) || (configuration == '3' && message_count == 16)){
                prbuf_in += sprintf(prbuf_in, "OK ");
                one_ok();
            }else{
                prbuf_in += sprintf(prbuf_in, "FAILED ");
                one_failed();
            }
            last_message_count = message_count;
        }

        // If we're the receiver, we've received a time message
        if (role == role_receiver){
            // Get this payload and dump it
            size_t len = max_payload_size;
            memset(receive_payload, 0, max_payload_size);

            if (configuration == '3'){
                len = next_payload_size;
            }else{
                len = radio.getDynamicPayloadSize();
            }

            radio.read(receive_payload, len);

            // Put a zero at the end for easy printing
            receive_payload[len] = 0;

            // Spew it
            prbuf_in += sprintf(prbuf_in, "Recv size=%i val=%s len=%u\n\r", len, receive_payload, strlen(receive_payload));

            // Add an ack packet for the next time around.
            // Here we will report back how many bytes we got this time.
            radio.writeAckPayload(pipe_number, &len, sizeof(len));

            ++message_count;
        }
    }
}

Keep the test program simple for now.

Configure the NRF without all the extra features such as DYNAMIC PAYLOADS or ACK with PAYLOADS. These will complicate things if you are just testing

// We will be using the Ack Payload feature, so please enable it
radio.enableAckPayload();
radio.enableDynamicPayloads(); // needed for using ACK payloads

Preferably,

  • static payload of 32 bytes
  • no ACK with PAYLOAD
  • enable auto ACK

start with that simple configuration first first

I have now tried this code, and I still do not manage to send information.

/*
 * See documentation at https://nRF24.github.io/RF24
 * See License information at root directory of this library
 * Author: Brendan Doherty (2bndy5)
 */

/**
 * A simple example of sending data from 1 nRF24L01 transceiver to another.
 *
 * This example was written to be used on 2 devices acting as "nodes".
 * Use the Serial Monitor to change each node's behavior.
 */
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"

// instantiate an object for the nRF24L01 transceiver
RF24 radio(8, 9); // using pin 7 for the CE pin, and pin 8 for the CSN pin

// sets the role of this unit in hardware.  Connect to GND to be the 'pong' receiver
// Leave open to be the 'ping' transmitter
const short role_pin = 5;

// Single radio pipe address for the 2 nodes to communicate.
const uint64_t pipe = 0xE8E8F0F0E1LL; ///0xCCCECCCECC
uint8_t pipe_number = 1;

// For this example, we'll be using a payload containing
// a single float number that will be incremented
// on every successful transmission
float payload = 0.0;

// The various roles supported by this sketch
typedef enum {
    role_sender = 1,
    role_receiver
} role_e;

// The debug-friendly names of those roles
const char* role_friendly_name[] = {"invalid", "Sender", "Receiver"};

// The role of the current running sketch
role_e role;

void setup() {

  // set up the role pin
  pinMode(role_pin, INPUT);
  digitalWrite(role_pin, HIGH);
  delay(20); // Just to get a solid reading on the role pin
  // read the address pin, establish our role
  if (digitalRead(role_pin)) {
      role = role_sender;
  } else {
      role = role_receiver;
  }

  
  Serial.begin(115200);
  printf_begin();
  while (!Serial) {
    // some boards need to wait to ensure access to serial over USB
  }

  // print example's introductory prompt
  Serial.println(F("RF24/examples/GettingStarted"));

  // initialize the transceiver on the SPI bus
  if (!radio.begin()) {
    Serial.println(F("radio hardware is not responding!!"));
    while (1) {} // hold in infinite loop
  }

  //Check if the module connects to SPI
  if (!radio.isChipConnected()) {
     Serial.println(F("Chip not connected."));
     while (1) {} // hold program in infinite loop to prevent subsequent errors
  }

  printf("ROLE: %s\n\r", role_friendly_name[role]);


  printf("+READY press any key to start\n\r\n\r");

  while (!Serial.available()) {}

  //What does each module do.
  if (role == role_sender){
        radio.openWritingPipe(pipe);
    }else{
        radio.openReadingPipe(pipe_number, pipe);
    }

  
  // Start listening
  if (role == role_receiver){
      radio.startListening();
  }

  //
  // Dump the configuration of the rf unit for debugging
  //
  radio.printDetails();

  /*
  if (role == role_receiver){
      printf("\n\r+OK ");
  }*/
}

void loop() {

  if (role == role_sender) {
    // This device is a TX node
    

    unsigned long start_timer = micros();                    // start the timer
    bool report = radio.write(&payload, sizeof(float));      // transmit & save the report
    unsigned long end_timer = micros();                      // end the timer

    if (report) {
      Serial.print(F("Transmission successful! "));          // payload was delivered
      Serial.print(F("Time to transmit = "));
      Serial.print(end_timer - start_timer);                 // print the timer result
      Serial.print(F(" us. Sent: "));
      Serial.println(payload);                               // print payload sent
      payload += 0.01;                                       // increment float payload
    } else {
      Serial.println(F("Transmission failed or timed out")); // payload was not delivered
    }

    // to make this example readable in the serial monitor
    delay(1000);  // slow transmissions down by 1 second

  } else {
    // This device is a RX node
    radio.flush_rx();
    uint8_t pipe;
    if (radio.available(&pipe)) {             // is there a payload? get the pipe number that recieved it
      uint8_t bytes = radio.getPayloadSize(); // get the size of the payload
      radio.read(&payload, bytes);            // fetch payload from FIFO
      Serial.print(F("Received "));
      Serial.print(bytes);                    // print the size of the payload
      Serial.print(F(" bytes on pipe "));
      Serial.print(pipe);                     // print the pipe number
      Serial.print(F(": "));
      Serial.println(payload);                // print the payload's value
    }
  } // role

} // loop

The receiver module does not print anything, and the emisor module prints the following message:

ROLE: Sender

+READY press any key to start


SPI Speedz	= 10 Mhz
STATUS		= 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1	= 0xe8e8f0f0e1 0xc2c2c2c2c2
RX_ADDR_P2-5	= 0xc3 0xc4 0xc5 0xc6
TX_ADDR		= 0xe8e8f0f0e1
RX_PW_P0-6	= 0x20 0x20 0x20 0x20 0x20 0x20
EN_AA		= 0x3f
EN_RXADDR	= 0x03
RF_CH		= 0x4c
RF_SETUP	= 0x07
CONFIG		= 0x0e
DYNPD/FEATURE	= 0x00 0x00
Data Rate	= 1 MBPS
Model		= nRF24L01+
CRC Length	= 16 bits
PA Power	= PA_MAX
ARC		= 15
Transmission failed or timed out
Transmission failed or timed out
Transmission failed or timed out

After observing the program, I have realized that the problem is that radio.write() returns false. According to the library, it returns false if:

/*
`false` if the payload was sent but was not acknowledged with an ACK
packet. This condition can only be reported if the auto-ack feature
is on.
*/

I do not understand what "but was not acknowledged with an ACK
packet." means. What should I do?

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.