Communication between 2 NRF24L01 Radio Modules.

I have recently learned how to use the NRF24LO1 Radio Module and have successfully made communication between them. My next goal for the project is for both of them to be sending out data and listening for any incoming data, then sending out data again. Once one receives data it will light up a LED, but should continue to send out data. Once it does not receive data it should turn off the LED.

I haven't found any code on the internet that code do that or something similar and I have tried combining some different codes I have found on the internet but have not quite been brave enough to try to write some on my own.

I have written some simple Arduino code in the past but I someone could help me write code for this project I would appreciate it.

Thank you.

Have you read Robin2’s excellent nRF24L01 tutorial?

Once one receives data it will light up a LED,

The available() function tells you that data is ready, in the serial buffer, to be read. Turn the LED on.

Once it does not receive data it should turn off the LED.

When you receive data turn the LED on and start a timer. As long as you are receiving data refresh the timer. When data is not received, the timer will not be refreshed. After a set time of not receiving, the timer will time out. Turn off the LED.

Non-blocking timing tutorials:
Several things at a time.
Beginner's guide to millis().
Blink without delay().

droidboy:
My next goal for the project is for both of them to be sending out data and listening for any incoming data,

This may not be quite as straightforward as you think. A wireless module can only listen or talk - it can’t do both at the same time. Unless you plan your system carefully you run the risk that both modules are talking or both are listening which would mean that the whole system would get stuck.

If your project allows you to define one of the Arduinos as master and then use the ackPayload technique in the second example in my tutorial you can have two-way communication without any complications.

…R

I have read through Robin's tutorial. It definitely helped me better understand the NRF24 radio module.

I would prefer there not to be masters and slaves but until I get something working, if that is easiest than I can designate one as Master and the other Slave.

Would I be able to modify the ackPayload code to work for me in this project?

droidboy:
Would I be able to modify the ackPayload code to work for me in this project?

Get the example from my Tutorial working without any changes to the code and after that you can adapt it as you wish.

What is your objection to designating one of the Arduinos as master?

...R

I got the two way communication code working.

I was not wanting to have a master slave communication because I was hoping to have multiple of these units.

Right now I am just trying to make two, a master and slave but eventually I might make more and a master can't communicate to another master and slave can't communicate to another slave, right?

How would I modify the code?

droidboy:
I was not wanting to have a master slave communication because I was hoping to have multiple of these units.

My Tutorial includes an example of a master and two slaves that could be extended to a much larger number of slaves.

and a master can't communicate to another master and slave can't communicate to another slave, right?

That's not correct. An nRF24 can talk to any other nRF24 if it uses the appropriate address and if the other nRF24 is listening on that address. The titles "master" and "slave" are entirely arbitrary and the roles can be changed at any time.

The complication is how to ensure that nRF24 A is listening when nRF24 B wants to send it a message. And if there is an nRF24 C which happens to transmit at the same time as nRF24 B then both messages will be garbled. You will need to consider your program logic very carefully.

The examples in my Tutorial are intended to avoid this sort of complication so that beginners can get started with a good prospect of success.

...R

So I attempted to add some elements to your Rx ack payload code from one of my other project’s code but I don’t think I added it correctly. Here is the code that I added elements from.

void setup() {
Serial.begin(9600);
 pinMode(11, OUTPUT); // put your setup code here, to run once:
 pinMode(8, OUTPUT);
 pinMode(5, OUTPUT);
 }

void loop() {
  // put your main code here, to run repeatedly:
 if(Serial.available()>0)
   {     
      char data= Serial.read(); // reading the data received from the bluetooth module
      switch(data)
      {
        case 'a': digitalWrite(13, HIGH);break; // when a is pressed on the app on your smart phone
        case 'd': digitalWrite(13, LOW);break; // when d is pressed on the app on your smart phone
        case 'b': digitalWrite(8, HIGH);break;
        case 'c': digitalWrite(8, LOW);break;
        case 'e': digitalWrite(5, HIGH);break;
        case 'f': digitalWrite(5, LOW);break;
        default : break;
      }
      Serial.println(data);
   }
   delay(50) ;
}

This is your code with what I added to it.

// SimpleRxAckPayload- the slave or the receiver

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

#define CE_PIN   9
#define CSN_PIN 10

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

RF24 radio(CE_PIN, CSN_PIN);

char dataReceived[10]; // this must match dataToSend in the TX
int ackData[2] = {109, -4000}; // the two values to be sent to the master
bool newData = false;

//==============

void setup() {

    Serial.begin(9600);

     pinMode(2, OUTPUT);

    Serial.println("SimpleRxAckPayload Starting");
    radio.begin();
    radio.setDataRate( RF24_250KBPS );
    radio.openReadingPipe(1, thisSlaveAddress);

    radio.enableAckPayload();
    
    radio.startListening();

    radio.writeAckPayload(1, &ackData, sizeof(ackData)); // pre-load data
}

//==========

void loop() {
    getData();
    showData();
}

//============

void getData() {
    if ( radio.available() ) {
        radio.read( &dataReceived, sizeof(dataReceived) );
        updateReplyData();
        newData = true;
    }
}

//================

void showData() {
    if (newData == true) {
        Serial.print("Data received ");
        Serial.println(dataReceived);
        Serial.print(" ackPayload sent ");
        Serial.print(ackData[0]);
        Serial.print(", ");
        Serial.println(ackData[1]);
        digitalWrite(5, HIGH);break;
        newData = false;

         if (newData == false) {
        digitalWrite(5, LOW);break;
        newData = true;
    }
}

//================

void updateReplyData() {
    ackData[0] -= 1;
    ackData[1] -= 1;
    if (ackData[0] < 100) {
        ackData[0] = 109;
    }
    if (ackData[1] < -4009) {
        ackData[1] = -4000;
    }
    radio.writeAckPayload(1, &ackData, sizeof(ackData)); // load the payload for the next time
}

Here is the area where I added the most code. It is the void Showdata.

void showData() {
    if (newData == true) {
        Serial.print("Data received ");
        Serial.println(dataReceived);
        Serial.print(" ackPayload sent ");
        Serial.print(ackData[0]);
        Serial.print(", ");
        Serial.println(ackData[1]);
        digitalWrite(5, HIGH);break;
        newData = false;

         if (newData == false) {
        digitalWrite(5, LOW);break;
        newData = true;
    }
}

There is also an error message flashing that says

exit status 1
‘updateReplyData’ was not declared in this scope

You’ve got a mismatched { } pair in function showData()

Use CTRL-T to auto format your code in the IDE.

Your use of the “break” statement outside of a switch case in the same function is erroneous.

How do I fix this?

droidboy:
How do I fix this?

Study the code carefully line by line and check that every { has its own matching }

...R

So I have been adding code to your Rx Ack payload code.

// SimpleRx - the slave or the receiver

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

#define CE_PIN   9
#define CSN_PIN 10

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

RF24 radio(CE_PIN, CSN_PIN);

char dataReceived[10]; // this must match dataToSend in the TX
bool newData = false;

//===========

void setup() {

  Serial.begin(9600);
  pinMode(13, OUTPUT);

  Serial.println("SimpleRx Starting");
  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.openReadingPipe(1, thisSlaveAddress);
  radio.startListening();
}

//=============

void loop() {
  getData();
  showData();

}

//==============

void getData() {
  if ( radio.available() ) {
    radio.read( &dataReceived, sizeof(dataReceived) );
    newData = true;
  }
}

void showData() {
  if (newData == true) {
    Serial.print("Data received ");
    Serial.println(dataReceived);
    newData = false;
  }
   { if (newData == true) {
      digitalWrite(13, HIGH);break;
      newData = false;
    }
  }
}

This is the section where I added the most code.

void showData() {
  if (newData == true) {
    Serial.print("Data received ");
    Serial.println(dataReceived);
    newData = false;
  }
   { if (newData == true) {
      digitalWrite(13, HIGH);break;
      newData = false;
    }
  }
}

There is an error message flashing saying
exit status 1
break statement not within loop or switch

I don’t know if I added the code in the right area.

Can you help me figure out why this error message is flashing?

Why have you got a break; statement? - remove it and the error will go away.

Apart from that your code is not correct. This

    newData = false;
  }
   { if (newData == true) {

can't work because the IF will never work because newData will always be false. You don't need that second IF clause at all.

...R

I removed the second IF clause and break statement, then added parts of the IF to the original IF.

The Error messages went away but it still is not powering the pin.

This is the section of code that I changed

void showData() {
  if (newData == true) {
    Serial.print("Data received ");
    Serial.println(dataReceived);
    digitalWrite(2, HIGH);
    newData = false;
  }

Posting partial changes is not helpful. Nobody wants to go back and find your original post with original code, possibly apply some/all of the changes suggested in the replies and maybe arrive at something that resembles the code you are trying to use/debug. Just post the complete sketch so it is not a piecemeal collection.

Sorry, I only thought it would be necessary to post the part of the code that I modified.

// SimpleRx - the slave or the receiver

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

#define CE_PIN   9
#define CSN_PIN 10

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

RF24 radio(CE_PIN, CSN_PIN);

char dataReceived[10]; // this must match dataToSend in the TX
bool newData = false;

//===========

void setup() {

  Serial.begin(9600);
  pinMode(2, OUTPUT);

  Serial.println("SimpleRx Starting");
  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.openReadingPipe(1, thisSlaveAddress);
  radio.startListening();
}

//=============

void loop() {
  getData();
  showData();

}

//==============

void getData() {
  if ( radio.available() ) {
    radio.read( &dataReceived, sizeof(dataReceived) );
    newData = true;
  }
}

void showData() {
  if (newData == true) {
    Serial.print("Data received ");
    Serial.println(dataReceived);
    digitalWrite(2, HIGH);
    newData = false;
  }
}

droidboy:
Sorry, I only thought it would be necessary to post the part of the code that I modified.

Please post sample of the output that the program sends to the Serial Monitor.

Also please post the TX program. Wireless programs must always be viewed as pairs.

...R

This is the Tx code, I have not modified it. What do you mean by A sample of output that the program sends to the Serial Monitor?

// SimpleTx - the master or the transmitter

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


#define CE_PIN   9
#define CSN_PIN 10

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


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

char dataToSend[10] = "Message 0";
char txNum = '0';


unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 1000; // send once per second


void setup() {

    Serial.begin(9600);

    Serial.println("SimpleTx Starting");

    radio.begin();
    radio.setDataRate( RF24_250KBPS );
    radio.setRetries(3,5); // delay, count
    radio.openWritingPipe(slaveAddress);
}

//====================

void loop() {
    currentMillis = millis();
    if (currentMillis - prevMillis >= txIntervalMillis) {
        send();
        prevMillis = millis();
    }
}

//====================

void send() {

    bool rslt;
    rslt = radio.write( &dataToSend, sizeof(dataToSend) );
        // 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 ");
    Serial.print(dataToSend);
    if (rslt) {
        Serial.println("  Acknowledge received");
        updateMessage();
    }
    else {
        Serial.println("  Tx failed");
    }
}

//================

void updateMessage() {
        // so you can see that new data is being sent
    txNum += 1;
    if (txNum > '9') {
        txNum = '0';
    }
    dataToSend[8] = txNum;
}