RF24 (TMRh20) - addressing?

Hello together, (and sorry for my poor english)

I have a project with some nanos + nrf24 and using RF24- library from TMRh20... It is working great...

But next stepp should be to make a little network... one master-node and 5 chields. But I have problems with correct pipe names...

So every node should name the pipes in the same way:

byte addresses[][6] = {"1Pipe","2Pipe","3Pipe","4Pipe","5Pipe","6Pipe"};

is it right?

And now master should open alle writing pipes and all reading pipes in that way:

radio.openWritingPipe(addresses[1]);
radio.openWritingPipe(addresses[2]);
radio.openWritingPipe(addresses[3]);
radio.openWritingPipe(addresses[4]);
radio.openWritingPipe(addresses[5]);
radio.openWritingPipe(addresses[6]);
radio.openReadingPipe(1,addresses[0]);
radio.openReadingPipe(1,addresses[1]);
radio.openReadingPipe(1,addresses[2]);
radio.openReadingPipe(1,addresses[3]);
radio.openReadingPipe(1,addresses[4]);
radio.openReadingPipe(1,addresses[5]);

correct?

and now each chield should open one writing pipe an one reading pipe- but each node hast to use a different one ...

Node1:

radio.openWritingPipe(addresses[0]);
radio.openReadingPipe(0,addresses[1]);

Node2:

radio.openWritingPipe(addresses[1]);
radio.openReadingPipe(1,addresses[2]);

Node3:

radio.openWritingPipe(addresses[2]);
radio.openReadingPipe(2,addresses[3]);

Node4:

radio.openWritingPipe(addresses[3]);
radio.openReadingPipe(3,addresses[4]);

Node5:

radio.openWritingPipe(addresses[4]);
radio.openReadingPipe(4,addresses[5]);

correct??? - in that way only message from node 1 will be received from master... but I can not find the failure....

MaHa76:
And now master should open alle writing pipes

No. There is only one writing pipe.

MaHa76:
and now each chield should open one writing pipe an one reading pipe-

No. You could use

radio.openWritingPipe(addresses[0]);
radio.openReadingPipe(1,addresses[0]);

radio.openWritingPipe(addresses[1]);
radio.openReadingPipe(1,addresses[1]);

radio.openWritingPipe(addresses[2]);
radio.openReadingPipe(1,addresses[2]);
...

So the master receives from each of the six possible slaves and all slaves have a persona address that can be used ba the master.

Please read the datasheet. nRF24L01P_Product_Specification_1_0.pdf

Thank you very much!!!!

I have read the documentation, also the classes from TMRh20... but my english is not so well- so it takes a lot of time to understand- not only to read...

So your hint is great- I will start another try out tomorrow...

  1. question: when I would like to start a tree- topology... how should I address the chields of the chields?

I would not design a tree in that way.

Each node would get a personal address, 1 upstream and n downstream addresses
managed by software (could be stored to eeprom).

Packets need a network header, some routing will be needed, etc.

Even in your setup I would let all slaves send to one address, removing the limit of 6 slave nodes)

I use different addresses for different types of information not as a personal channels between two nodes.

OK... at the moment I do not understand how to do in real...

So, maybe short explaination of my project...

I have some Lamps (all equiped with LEDs) in each room... I have 5 rooms in my flat, getting datas from master node- so that first stepp should work with that adressing- I choose a "master- lamp" for each room, communicating directly to master. So in every room are up to 4 "chield"-lamps and / or sensors (motion, ir-remote)- so it would work fine with 5 chields for each master- lamp...

So my first idea was that it should be best solved with tree- topology...

@MaHa76, I get the impression that you want one master to communicate with several slaves and then each slave to communicate with several sub-slaves (best word I can think of.

For example M talks to A, B and C. And A then talks to A1, A2 an A3 and B talks to B1, B2 and B3 etc.

And I am assuming that there is no need for M to talk to A2 (for example).

Is this a correct description? - If not please explain how it should be.

If that was my project I would give every device a separate ID. I would get the Master to poll each of A, B and C in turn. And I would use very similar code in each of A, B and C, to talk to each of their sub-slaves.

The pair of programs in this link are a simpified version of a system I use for controlling model trains. I think it could easily be adapted to meet your requirement.

...R

yes- 100% correct... :smiley:

I will have a deeper look at your project- thanks for that link.

hm.... that was not helpfull for my understanding of correct addressing...

It is no problem to set up good communication between to nodes.... but more than this is not working....

MaHa76:
hm.... that was not helpfull for my understanding of correct addressing...

Can you explain what the problem is with my suggested code - maybe I can help?

I am using a version of that to communicate with 3 devices and lots more are possible.

...R

I have tryed to use the parts for communication in my sketch.... but it works always with one chield... or 2 chields between each other (what I do not wanted...)

Maybe I should restart from beginning.... (?)

I do not understand the naming of pipes and when to open wich reading pipe and wich writing pipe... I have read documentation from NRF24 and also classes created from TRMh20... but in all cases only communication between 2 nodes is described... I would need an example for a real star-network...

It is rather unfortunate that many example programs use the name "pipe" for the variable that holds the ID of the device .

There is one writing pipe and 6 reading pipes. This means an nRF24 could receive messages from 6 other devices at the same time, but it can only send a message to one device at a time

The system I have used only uses one pipe, not matter how many slaves there are. In the example Tx code there is a line

radio.openWritingPipe(slaveID);

which prepares to send a message to a particular slave. You can have an array of different slave addresses and call each one in turn.

In the Rx code the line

radio.openReadingPipe(1,deviceID);

causes the slave to listen on pipe 1 for messages addressed to deviceID - which is the number assigned to that slave. Each slave should have a different number.

Does this help?

If not please try to explain what you don't understand.

...R

MaHa76:
I would need an example for a real star-network...

If you miss such an example, you should write one. :wink:

OK, thanks for that additional hint... So on weekend I will start to make reduced sketches- only showing addressing, sending and receiving from "dummy"-datas... I will try to work with your example...

and when it works- yes for sure, I will give it to all as an example for a star- network inkl. sketch for 6 nodes. :slight_smile:

Hello together,

based on TMRh20'slibrary I have create 3 sketches to start with network- using 1 Master and min. 5 Nodes...

So, first stepp, I have now 1 master and 2 chields... Both chields are receiving datas from Master without any problems. But master is allways receiving datas from 1 node- I have tryed a lot and read documentations but can not find any solution....

maybe you could help me....

master:

#include <SPI.h>
#include "RF24.h"
#include "FastLED.h"
#include <DS3232RTC.h>
#include <Time.h>
#include <Wire.h>

RF24 radio(9,10);
byte addresses[][6] = {"1Pipe","2Pipe","3Pipe","4Pipe","5Pipe","6Pipe",};

long Status[6] = {10,11,12,13,14,15};  // definiere das Verhalten der Lampen
long Sensor[6];  // Fadingzeit, Farbe (CSV), Helligkeit (CSV), Sättigung (CSV), Haltezeit, Adresse Lampe, Pipe

int IRStatus;
int IRRaum; // 01 = Raum 1, 02 = Raum 2, 03 = Raum 3, 04 = Raum 4, 05 = Raum 5, 06 = alle Räume
int Auto = 1; // wenn Auto = 0, dann gelten die manuellen Vorgaben, Wenn Auto = 1, dann gelten die Programmvorgaben
          // wenn Auto = 2, starte Pogramm???
// Ordne automatische Programme zu

int i;

#define DATA_PIN 4
#define NUM_LEDS 3
CRGB leds[NUM_LEDS];

void setup() 
{
  Serial.begin(57600);
  Serial.println("Test Zentrale");
  
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
  
    leds[0] = CRGB::Cyan;
    FastLED.show();
    delay(200);
    leds[1] = CRGB::Cyan;
    FastLED.show();
    delay(200);
    leds[2] = CRGB::Cyan;
    FastLED.show();
    delay(200);
    leds[0] = CRGB::Orange;
    FastLED.show();
    delay(200);
    leds[1] = CRGB::Orange;
    FastLED.show();
    delay(200);
    leds[2] = CRGB::Orange;
    FastLED.show(); 
    delay(200);    
    leds[0] = CRGB::Black;
    FastLED.show();
    delay(200);
    leds[1] = CRGB::Black;
    FastLED.show();
    delay(200);
    leds[2] = CRGB::Black;
    FastLED.show(); 
    
    setSyncProvider(RTC.get);   // the function to get the time from the RTC
    if(timeStatus() != timeSet) 
        Serial.println("Unable to sync with the RTC");
    else
        Serial.println("RTC has set the system time"); 
  
  radio.begin();

    radio.openWritingPipe(addresses[1]);
    radio.openReadingPipe(1,addresses[3]);
    
  radio.startListening();
}

void loop() 
{
        radio.read( Sensor, sizeof(Sensor) ); 
        unsigned long time = micros();
        Serial.println("empfange ");
        Serial.print(" PIR:      " );
        Serial.println(Sensor[0]);
        Serial.print(" IR- Code: " );
        Serial.println(Sensor[1]);
        Serial.print(" IR- Raum " );
        Serial.println(Sensor[2]);
        Serial.print(" Raum ID " );
        Serial.println(Sensor[3]);
        Serial.print(" ? " );
        Serial.println(Sensor[4]);
        Serial.print(" ? " );
        Serial.println(Sensor[5]);                   
        Serial.println("  ");                      
        Serial.println("  ");
      
     if (i < 6)
     {i++;}
     else
     {i = 1;}
     
      radio.stopListening(); 
      radio.write( Status, sizeof(Status) );  
      radio.startListening(); 
        Serial.print("Sende Vorgaben an Lampe  "); 
        Serial.println();     
        Serial.print("Fadingzeit:    ");
        Serial.println(Status[0]);                      
        Serial.print("Farbe (CSV):   ");
        Serial.println(Status[1]);                            
        Serial.print("Helligkeit:    ");
        Serial.println(Status[2]);                        
        Serial.print("Saettigung   ");
        Serial.println(Status[3]);                    
        Serial.print("Programm: ");
        Serial.println(Status[4]);                       
        Serial.print("Auto? ");
        Serial.println(Status[5]);                      
        Serial.println("  ");                      
        Serial.println("  ");
   
}

Node 1:

#include <SPI.h>
#include "RF24.h"
#include "FastLED.h"
#include "IRremote.h"

RF24 radio(9,10);

byte addresses[][6] = {"1Pipe","2Pipe","3Pipe","4Pipe","5Pipe","6Pipe"};

long Sensor[6];
long Status[6];
long Trigger[6];
int IRStatus;
int IRRaum; // 01 = Raum 1, 02 = Raum 2, 03 = Raum 3, 04 = Raum 4, 05 = Raum 5, 06 = alle Räume
int RaumID = 2;

int receiver = 3;
IRrecv irrecv(receiver);      
decode_results results; 

int PIR;
int sensorPin = 4;

#define DATA_PIN 2
#define NUM_LEDS 3
CRGB leds[NUM_LEDS];

void setup() 
{
  Serial.begin(57600);
  Serial.print("Test Lampe  ");
  Serial.println(RaumID);
  
  pinMode(sensorPin, INPUT);
  irrecv.enableIRIn();
  
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);

  
  radio.begin();

    radio.openWritingPipe(addresses[RaumID]);
    radio.openReadingPipe(1,addresses[1]);
    
  radio.startListening();
}

void loop() 
{
  
    leds[0] = CRGB::Black;
    FastLED.show();
    leds[1] = CRGB::Black;
    FastLED.show();
    leds[2] = CRGB::Black;
    FastLED.show();  
    
 PIR = digitalRead(sensorPin);
    if (PIR == HIGH)
         {  
                leds[1] = CRGB::Green;
 FastLED.show();
                Serial.println("Bewegung erkannt.");
         }
    else
         {
                leds[1] = CRGB::Red;
 FastLED.show(); 
                Serial.println("keine Bewegung.");   
         }
        
if (irrecv.decode(&results))
  {
    translateIR();
    irrecv.resume();
  }  
  
  Sensor[0] = PIR;
  Sensor[1] = IRStatus;
  Sensor[2] = IRRaum;
  Sensor[3] = RaumID;
    
    radio.stopListening();     
        Serial.println("Sende...");
        Serial.print("  Bewegung erkannt: ");
        Serial.println(Sensor[0]);
        Serial.print("  IR- Code ");
        Serial.println(Sensor[1]);
        Serial.print("  IR- Raum ");
        Serial.println(Sensor[2]);
        Serial.print("  Raum ID ");
        Serial.println(Sensor[3]);
        Serial.print("  offen ");
        Serial.println(Sensor[4]);
        Serial.print("  offen ");  
        Serial.println(Sensor[5]);
        Serial.println(" ");  
        Serial.println(" "); 

    if (!radio.write( Sensor, sizeof(Sensor) ))
    {
       Serial.println("fehlgeschlagen");  
                leds[0] = CRGB::Red;
 FastLED.show();
     }
        
    radio.startListening();                                    // Now, continue listening
    
    unsigned long started_waiting_at = micros();               // Set up a timeout period, get the current microseconds
    boolean timeout = false;                                   // Set up a variable to indicate if a response was received or not
    
    while ( ! radio.available() ){                             // While nothing is received
      if (micros() - started_waiting_at > 20 ){            // If waited longer than 200ms, indicate timeout and exit while loop
          timeout = true;
          break;
      }      
    }
    
    delay(5);
        
    if ( timeout ){                                             // Describe the results
        Serial.println("Fehlgeschlagen- Antwortzeit abgelaufen...");  
                leds[1] = CRGB::Red;
 FastLED.show();
    }
    else
    { 
        IRStatus = 0;
        radio.read( Status, sizeof(Status) );
        
        Serial.println("empfange Vorgaben:   ");
        Serial.print("Fadingzeit: ");
        Serial.println(Status[0]);
        Serial.print("  Farbe (CSV): ");
        Serial.println(Status[1]);
        Serial.print("  Helligkeit (CSV: )");
        Serial.println(Status[2]);
        Serial.print("  Saettigung (CSV): ");
        Serial.println(Status[3]);
        Serial.print("  offen ");
        Serial.println(Status[4]);
        Serial.print("  offen   ");  
        Serial.println(Status[5]);
        Serial.println(" ");  
        Serial.println(" ");  
                leds[0] = CRGB::Green;
 FastLED.show();
    }

    delay(10);
}

void translateIR()
{
  switch(results.value)
{}
}

Node 2 is the same as Node 1, only "RaumID" is a different one...

I have put some example-values in sketch from master, cause real sketch is realing long- master is receiving Datas from Nodes (lamps with PIR and IR-remote) and is calculating Values for brightness, colour and so on , depending on time, date and weather and so on....

You do not check for a received packet before reading and processing it (in master loop).

I have done before- with out succsess- so, now I have tryed to minimize the sketch....

based on your hint, I have included checking radio availability... but master has still problems to receive... only sometime one node is available....

#include <SPI.h>
#include "RF24.h"
#include "FastLED.h"
#include <DS3232RTC.h>
#include <Time.h>
#include <Wire.h>

RF24 radio(9,10);
byte addresses[][6] = {"1Pipe","2Pipe","3Pipe","4Pipe","5Pipe","6Pipe",};

long Status[6] = {10,11,12,13,14,15};  // definiere das Verhalten der Lampen
long Sensor[6];  // Fadingzeit, Farbe (CSV), Helligkeit (CSV), Sättigung (CSV), Haltezeit, Adresse Lampe, Pipe

int IRStatus;
int IRRaum; // 01 = Raum 1, 02 = Raum 2, 03 = Raum 3, 04 = Raum 4, 05 = Raum 5, 06 = alle Räume
int Auto = 1; // wenn Auto = 0, dann gelten die manuellen Vorgaben, Wenn Auto = 1, dann gelten die Programmvorgaben
          // wenn Auto = 2, starte Pogramm???
// Ordne automatische Programme zu

int i;

#define DATA_PIN 4
#define NUM_LEDS 3
CRGB leds[NUM_LEDS];

void setup() 
{
  Serial.begin(57600);
  Serial.println("Test Zentrale");
  
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);
  
    leds[0] = CRGB::Cyan;
    FastLED.show();
    delay(200);
    leds[1] = CRGB::Cyan;
    FastLED.show();
    delay(200);
    leds[2] = CRGB::Cyan;
    FastLED.show();
    delay(200);
    leds[0] = CRGB::Orange;
    FastLED.show();
    delay(200);
    leds[1] = CRGB::Orange;
    FastLED.show();
    delay(200);
    leds[2] = CRGB::Orange;
    FastLED.show(); 
    delay(200);    
    leds[0] = CRGB::Black;
    FastLED.show();
    delay(200);
    leds[1] = CRGB::Black;
    FastLED.show();
    delay(200);
    leds[2] = CRGB::Black;
    FastLED.show(); 
    
    setSyncProvider(RTC.get);   // the function to get the time from the RTC
    if(timeStatus() != timeSet) 
        Serial.println("Unable to sync with the RTC");
    else
        Serial.println("RTC has set the system time"); 
  
  radio.begin();

    radio.openWritingPipe(addresses[1]);
    radio.openReadingPipe(1,addresses[2]);
    
  radio.startListening();
}

void loop() 
{  
     if (i < 6)
     {i++;}
     else
     {i = 1;}
     
      radio.stopListening(); 
        Serial.print("Sende Vorgaben an Lampe  "); 
        Serial.println();     
        Serial.print("Fadingzeit:    ");
        Serial.println(Status[0]);                      
        Serial.print("Farbe (CSV):   ");
        Serial.println(Status[1]);                            
        Serial.print("Helligkeit:    ");
        Serial.println(Status[2]);                        
        Serial.print("Saettigung   ");
        Serial.println(Status[3]);                    
        Serial.print("Programm: ");
        Serial.println(Status[4]);                       
        Serial.print("Auto? ");
        Serial.println(Status[5]);                      
        Serial.println("  ");                      
        Serial.println("  ");
      
    if (!radio.write( Status, sizeof(Status) ))
    {
       Serial.println("fehlgeschlagen");  
                leds[0] = CRGB::Red;
		FastLED.show();
     }
        
   radio.startListening();             
    
    unsigned long started_waiting_at = micros();    
    boolean timeout = false;                              
    
    while ( ! radio.available() ){                          
      if (micros() - started_waiting_at > 200000 ){          
          timeout = true;
          break;
      }      
    }
        
    if ( timeout ){                                             // Describe the results
        Serial.println("Fehlgeschlagen- Antwortzeit abgelaufen...");  
                leds[1] = CRGB::Red;
		FastLED.show();
    }
    else
    { 
        radio.read( Sensor, sizeof(Sensor) ); 
        unsigned long time = micros();
        Serial.println("empfange ");
        Serial.print(" PIR:      " );
        Serial.println(Sensor[0]);
        Serial.print(" IR- Code: " );
        Serial.println(Sensor[1]);
        Serial.print(" IR- Raum " );
        Serial.println(Sensor[2]);
        Serial.print(" Raum ID " );
        Serial.println(Sensor[3]);
        Serial.print(" ? " );
        Serial.println(Sensor[4]);
        Serial.print(" ? " );
        Serial.println(Sensor[5]);                   
        Serial.println("  ");                      
        Serial.println("  ");
    }
 }

I think you should open two receiving pipes in the master.
You are sending the responses to different pipes and now you are relying on pipe 0 being set by the send.
This will only work as long as you only send to addresses[1].

The main problem seems to be, you are sending the request, both stations answer,
but you process only one response, then stopListening throws away the second packet.

Why have you started a new Thread which is pretty much the same as your earlier Thread

Your miss-spelling of "chield" gave you away - it should be "child"

...R

In my opinion I am more than 2 stepps farther than in the other post- so my idea was to avoid confusion... (bad idea?)

(thanks for that hint regarding child...)