Stuck on project with RF24L01

Hello programmers,

I’m having some problems with a project.
The setup for the project is that I have 2 arduino’s with RF24 chip.
both of them have a HC-SR04 sensor (ultrasonic) connected and one Led.

The idea of my program is that at startup my master arduino Led turns on a LED.
To show that this arduino is active and measuring.
If I then manipulate the ultrasonic sensor the led goes out and it has to send something to the other arduino.

This arduino then receives something and turns his led on and activates his sensor.
If I do the same on this sensor the process needs to repeat itself.

The sensor is working. I see that the led turns up on startup and goes off when I put my hand over the sensor.
But I’m not sending or receiving anyting…
Can someone give me some advice?

Regards,
Steven

Code Arduino 1:

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


RF24 radio(10, 9);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network

const uint16_t this_node = 00;   // Address of this node in Octal format ( 04,031, etc)
const uint16_t node01 = 01;      // Address of the other node in Octal format
//const uint16_t node012 = 012;
//const uint16_t node022 = 022;
const int trigPin = 7;
const int echoPin = 6;
const int ledPin = 3;
long duration;
int Master;


void setup() {
  SPI.begin();
  Serial.begin(57600);
  radio.begin();
    network.begin(90, this_node);  //(channel, node address)
    radio.setDataRate(RF24_2MBPS);
    pinMode(ledPin, OUTPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  Master = 1;
  }

void loop() {
  network.update();
  if (Master == 0) {
    Serial.println("Looking for message");
    while ( network.available() ) {     // Is there any incoming data?
      Serial.println("received message");
      RF24NetworkHeader header;
      unsigned long incoming;
      network.read(header, &incoming, sizeof(incoming));
      Master = 1;
    }
  }


  if (Master == 1) {
    digitalWrite(ledPin, HIGH);
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    duration = pulseIn(echoPin, HIGH);

    if (duration < 2500) {
      digitalWrite(ledPin, LOW);
      Master = 0;
      Serial.println("Send message");
      unsigned long Outgoing = 10;
      RF24NetworkHeader header2(node01);     // (Address where the data is going)
      bool ok = network.write(header2, &Outgoing, sizeof(Outgoing)); // Send the data
      }

  }
}

Code of the other arduino:

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


RF24 radio(10, 9);               // nRF24L01 (CE,CSN)
RF24Network network(radio);      // Include the radio in the network

const uint16_t this_node = 01;   // Address of this node in Octal format ( 04,031, etc)
const uint16_t node01 = 00;      // Address of the other node in Octal format
//const uint16_t node012 = 012;
//const uint16_t node022 = 022;
const int trigPin = 7;
const int echoPin = 6;
const int ledPin = 3;
long duration;
int Master;


void setup() {
  SPI.begin();
  Serial.begin(57600);
  radio.begin();
  network.begin(90, this_node);  //(channel, node address)
  radio.setDataRate(RF24_2MBPS);
  pinMode(ledPin, OUTPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  Master = 0;
  }

void loop() {
 network.update();
  if (Master == 0) {
    Serial.println("Looking for message");
    while ( network.available() ) {     // Is there any incoming data?
      Master = 1;
      Serial.println("received message");
      RF24NetworkHeader header;
      unsigned long incoming;
      network.read(header, &incoming, sizeof(incoming));
          }
  }


  if (Master == 1) {
    digitalWrite(ledPin, HIGH);
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    duration = pulseIn(echoPin, HIGH);

    if (duration < 2500) {
      digitalWrite(ledPin, LOW);
      Master = 0;
      Serial.println("Send message");
      unsigned long Outgoing = 1;
      RF24NetworkHeader header2(node01);     // (Address where the data is going)
      bool ok = network.write(header2, &Outgoing, sizeof(Outgoing)); // Send the data
      }

  }
}

Do you really need the network? How far apart are the nRF24s?

Have a look at this Simple nRF24L01+ Tutorial.

Wireless problems can be very difficult to debug so get the wireless part working on its own before you start adding any other features.

The examples are as simple as I could make them and they have worked for other Forum members. If you get stuck it will be easier to help with code that I am familiar with. Start by getting the first example to work

...R

Thx for the response.
I got the first example to work.

What do you mean with ‘network’?
Is ‘radio’ better? I see 2 types of programs, one with

radio.begin

and the other one is

network.begin

what is the difference?

In the final project the arduino’s are going to be about 10 meters from each other.

The Network library adds additional functionality on top of the basic RF24 library.

The idea underlying the Network library is to enable messages to be relayed from C to B to A which would be useful if A and C were too far apart to communicate directly.

If, in your case, both C and B can each communicate directly with A then there is no need for extra complexity of the Network library.

...R

Is this also possible when i upgrade the project to 1 master and 6 slave modules.
They all need to communicate with the master (in 2 directions). but not with each other.

Is this possible with the regular radio methode, or does it need to involve the network functions then?

Tosse:
Is this also possible when i upgrade the project to 1 master and 6 slave modules.

It should be possible with 60 slaves, or 160.

But what you really need to tell us is what size of message needs to be sent and how often the messages need to be sent. The quantity of data may present a limitation. However the Network system would be even slower.

...R

The message is very small, it would just be a trigger to activate some commands on the slave nodes.
Is this also possible? Or should this always be a 'message'?

The idea is that the master arduino should trigger a (random) slave arduino and then wait for its response.

What do you think is the difference between a "trigger" and a "message"? The application seems perfect for @Robin2's "Two-way transmission using the ackPayload concept" example.

Is the ackpayload concept not just the confirmation that the message has been received?
In my case the arduino needs to turn on a led and wait for a input before sending its message back to the master arduino.

Then you want @Robin2's "Two-way transmission by swapping roles" example. Be the master waits long enough for the reply from a given slave before sending the command/message to the next slave. You don't want 2 slaves replying at the same time and stepping on each other.

Tosse:
Is the ackpayload concept not just the confirmation that the message has been received?

No.

The ordinary process (as in my first example) provides an acknowledgement that a message is received. The ackPayload provides a convenient means for the slave to send data back to the master.

In my case the arduino needs to turn on a led and wait for a input before sending its message back to the master arduino.

It may still be possible to use the simple ackPayload system for that if you recognize that the replies are always one step behind.

...R

I got the program to work with using the example from Robin. (thx)
But for the moment it isn’t always doing what I want it to do.

It needs to act like this:
At startup:
MasterModule: Led turns high and start measuring with ultrasonic sensor (all goes well)
When sensor triggered: Send message to all arduino slaves. (message is random number from 1-6)

Arduino Slave captures the message and see if the number corresponds with there setting. (I gave them a unique number from 1-6)

This specific arduino turns on led and starts his sensor.
When sensor triggered turn down led en send message back to mastermodule.

This kinda works, but sometimes i see that 2 or more slave modules react on a message from the master…
Can someone check this code for me and give me some tips?

MasterModule

// MasterModule LightGame

#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'};
const byte masterAddress[5] = {'T', 'X', 'a', 'a', 'a'};

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

long dataToSend = 1;
int dataReceived[2]; 
bool newData = false;

const int trigPin = 7;
const int echoPin = 6;
const int ledPin = 3;
long duration;

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

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);  
  Serial.begin(9600);
  Serial.println("MasterModule LightGame");

  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.openWritingPipe(slaveAddress);
  radio.openReadingPipe(1, masterAddress);
  radio.setRetries(3, 5); // delay, count
  
  newData = true;
 }

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

void loop() {
  
  while (newData == true) {
    digitalWrite(ledPin, HIGH);
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    duration = pulseIn(echoPin, HIGH);

    if (duration < 2500) {
      digitalWrite(ledPin, LOW);
      newData = false;
      send();
      }
  }
  getData();

}

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

void send() {

  radio.stopListening();
  dataToSend= random(1, 6);
  Serial.println(dataToSend);
  bool rslt;
  rslt = radio.write( &dataToSend, sizeof(dataToSend) );
  radio.startListening();
}

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

void getData() {

  if ( radio.available() ) {
    newData = true;
  }
}

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

SlaveModule

// SlaveModule LightGame

#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'};
const byte masterAddress[5] = {'T','X','a','a','a'};

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

long dataReceived; // must match dataToSend in master
long slaveModule = 1; //number of SlaveModule (1 to 6)
int replyData = 5; // just some data to send back to MasterModule
bool newData = false;

const int trigPin = 7;
const int echoPin = 6;
const int ledPin = 3;
long duration;


void setup() {
    pinMode(ledPin, OUTPUT);
    pinMode(trigPin, OUTPUT);
    pinMode(echoPin, INPUT);
    Serial.begin(9600);
    Serial.println("SlaveModule LightGame");

    radio.begin();
    radio.setDataRate( RF24_250KBPS );
    radio.openWritingPipe(masterAddress); // NB these are swapped compared to the master
    radio.openReadingPipe(1, slaveAddress);
    radio.setRetries(3,5); // delay, count
    radio.startListening();

    newData = false;

}

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

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

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

void send() {
    while (newData == true) {
    radio.stopListening();
    
    digitalWrite(ledPin, HIGH);
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    duration = pulseIn(echoPin, HIGH);

    if (duration < 2500) {
      digitalWrite(ledPin, LOW);
            bool rslt;
            rslt = radio.write( &replyData, sizeof(replyData) );
            radio.startListening();
            newData = false;
    }
}
}
//================

void getData() {

    if ( radio.available() ) {
        radio.read( &dataReceived, sizeof(dataReceived) );
        if (dataReceived == slaveModule){
          Serial.println(dataReceived);
          newData = true;
        }
    }
}

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

Tosse:
It needs to act like this:
At startup:
MasterModule: Led turns high and start measuring with ultrasonic sensor (all goes well)
When sensor triggered: Send message to all arduino slaves. (message is random number from 1-6)

Arduino Slave captures the message and see if the number corresponds with there setting. (I gave them a unique number from 1-6)

This specific arduino turns on led and starts his sensor.
When sensor triggered turn down led en send message back to mastermodule.

If you are sending the same message to several slaves all listening on the same address then you MUST turn off auto-acknowledgement for all (or all but 1) of the slaves. If they all send an acknowledgement the signal will be garbled and the master may assume that the message failed.

You can get around that by giving each slave a separate address and have the master send a message to a single slave.

Separately, am I correct to assume that when the master sends a message for a specific slave there is no risk of any of the other slaves responding?

...R

I'll try the different adress mode that you suggest.

Can you explain to me what this line means exactly?

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

Which adress should I use for the other slaves?

Tosse:
Can you explain to me what this line means exactly?

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

Which adress should I use for the other slaves?

An address is just a 5 byte number. I find it easiest to use characters to represent the numbers - but you don't have to.

For my model train control system I just change one of the characters for the different addresses - for example

RxAAA
RxAAB
RxAAC
etc

...R

Robin2:
An address is just a 5 byte number. I find it easiest to use characters to represent the numbers - but you don't have to.

For my model train control system I just change one of the characters for the different addresses - for example

RxAAA
RxAAB
RxAAC
etc

...R

Oke I'll try that, thx for all the help...

one more question, where the slaveadress is now in my setup() section.
Can I replace this and put the 'radio.openWirtingPipe(slaveaddress1);' just before I write it? (so in the send section?
Then I would work with a randomizer and a case 1 to 6 for changing the adress of the receiver.

Tosse:
one more question, where the slaveadress is now in my setup() section.
Can I replace this and put the 'radio.openWirtingPipe(slaveaddress1);' just before I write it?

Yes. That is illustrated in the multi-tx example in Reply #17 in my Tutorial

...R

I rewrote the code to send it to more ‘slaves’ and that works i think.
But the masterarduino gets stuck and acts like he receives something and then continues his proces.
Even though i unplugged all the other slaves.
What am I doing wrong?

after reset, the first time it works great, but then it goes wrong…

// MasterModule LightGame

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

#define CE_PIN   9
#define CSN_PIN 10

const byte slaveAddress1[5] = {'R', 'x', 'A', 'A', 'A'};
const byte slaveAddress2[5] = {'R', 'x', 'A', 'A', 'B'};
const byte slaveAddress3[5] = {'R', 'x', 'A', 'A', 'C'};
const byte slaveAddress4[5] = {'R', 'x', 'A', 'A', 'D'};
const byte slaveAddress5[5] = {'R', 'x', 'A', 'A', 'E'};
const byte slaveAddress6[5] = {'R', 'x', 'A', 'A', 'F'};
const byte masterAddress[5] = {'T', 'X', 'a', 'a', 'a'};

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

long dataToSend = 1;
int dataReceived[2]; 
bool newData = false;
int whichNode;

const int trigPin = 7;
const int echoPin = 6;
const int ledPin = 3;
long duration;

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

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);  
  Serial.begin(9600);
  Serial.println("MasterModule LightGame");

  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  //radio.openWritingPipe(slaveAddress1);
  radio.openReadingPipe(1, masterAddress);
  radio.setRetries(3, 5); // delay, count
  
  newData = true;
 }

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

void loop() {
  
  while (newData == true) {
    digitalWrite(ledPin, HIGH);
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    duration = pulseIn(echoPin, HIGH);

    if (duration < 1500) {
      //digitalWrite(ledPin, LOW);
      //newData = false;
      delay(500);
      digitalWrite(trigPin, LOW);
      delayMicroseconds(2);
      digitalWrite(trigPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(trigPin, LOW);
      duration = pulseIn(echoPin, HIGH);
      if (duration < 1500) {
      digitalWrite(ledPin, LOW);
      newData = false;
      send();
      }}
  }
  getData();

}

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

void send() {

  radio.stopListening();
  whichNode = random(1,3);
  switch (whichNode){
    case 1:
    radio.openWritingPipe(slaveAddress1);
    Serial.println("Sending to node 1");
    break;
    case 2:
    radio.openWritingPipe(slaveAddress2);
    Serial.println("Sending to node 2");
    break;
    case 3:
    radio.openWritingPipe(slaveAddress3);
    Serial.println("Sending to node 3");break;
    case 4:
    radio.openWritingPipe(slaveAddress4);
    Serial.println("Sending to node 4");
    break;
    case 5:
    radio.openWritingPipe(slaveAddress5);
    Serial.println("Sending to node 5");
    break;
    case 6:
    radio.openWritingPipe(slaveAddress6);
    Serial.println("Sending to node 6");
    break;
  }
  bool rslt;
  rslt = radio.write( &dataToSend, sizeof(dataToSend) );
  radio.startListening();
}

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

void getData() {
  Serial.println("Data Send, waiting for repsonse");
  if ( radio.available() ) {
    newData = true;
  }
}

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

Tosse:
after reset, the first time it works great, but then it goes wrong....

Please describe in more detail what happens when it goes wrong.

I am very suspicious of this

void getData() {
  Serial.println("Data Send, waiting for repsonse");
  if ( radio.available() ) {
    newData = true;
  }
}

My guess is that the print will happen so often that it overflows the Serial Output Buffer and brings things to a stop

Also, in this part

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

you make no check to see if the data was sent successfully.

In general I think you need to reduce the frequency with which data is sent by the master (at least for testing) to once per second without reducing the frequency of listening for a response.

...R

I thing I know where the problem is. Only thing is that I can't fix it.

as I told, the first time the procedure works good.
It waits from a message from the Node before it continues.
with this line?

void getData() {
  
  if ( radio.available() ) {
    Serial.println("Received data from Slave");
    newData = true;
  }
}

But it seems that this radio.available stays true.
So the second run it doesnt wait for an answer it goes directly to the next step. (with newData = true)

Edit:
I fixed the problem. Dont know that this is the correct way, but now it works.
I send data to a slave.
And I resend the same data from slave to master, if this is oke then the transmission was correct.
And I add +1 to the data to send.

thx for all the help. Now I can start with adding some other features...