Time Synchronisation using RF24

We’re trying to synchronize several (2+) nodes. All Arduinos are equipped with a led that should flash at the same time without a hardcoded broadcast. We’re sending a packet into a sensoring network and by retrieving another packet we can compute the RTT of this packet and thereafter delay a certain time to pick up the right time of flashing the led of the sensor thay is new in our network.
However, when we’re trying to send a packet using the RF24 no other node will pick up the signal of the new incoming node.

We’re using the code beneath for all nodes:

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




// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
// (MV:) Adapted to work with the configuration of the shield. Original: RF24 radio(9,10);

RF24 radio(3, 9);
SimpleTimer timer;
int led_pin = 8;
int waitTime = 1500;
long t1, t2, t3, t4;

// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t adress = 0xF0D0D0F0D1LL;
boolean imsyncing = false;
int ledState = LOW;
long toSend[2];
long previousMillis = 0;
boolean pending = false;

void setup(void)
{

  // set up the led pin
  pinMode(led_pin, OUTPUT);
  randomSeed(analogRead(0));
  timer.setInterval(random(3000,10000), syncMethod);

  Serial.begin(57600);
  printf_begin();

  //
  // Setup and configure rf radio
  //

  radio.begin();
  radio.setRetries(15,0);
  radio.setChannel(63);
  radio.setPALevel(RF24_PA_MAX);
  // optionally, reduce the payload size.  seems to
  // improve reliability
  radio.enableDynamicPayloads();
  //
  // Open pipes to other nodes for communication
  //
  radio.openWritingPipe(adress);
  
  //
  // Start listening \n
  //
  radio.startListening();
  printf("now listening \n\r");
  //
  // Dump the configuration of the rf unit for debugging
  //
  radio.printDetails();
}


void loop(void)
{
  timer.run();
  
  if (radio.available() && !imsyncing){     
    radio.read( &t1, sizeof(long) );
    delay(20);
    printf("\n time packet 1 is received: %ld", t1);  
    long t2= millis();
    printf("\ntime packet 2: %ld", t2);  
    
    toSend[0]= t2;
    pending = true;
    
  }

  long currentMillis = millis();
    if(currentMillis - previousMillis > waitTime){
      previousMillis = currentMillis;
      if(ledState == LOW){
        ledState = HIGH;
        if(pending){
            radio.stopListening();
            printf("stopped listening \n\r");
            toSend[1]= millis();
            printf("\ntime packet 3: %ld", toSend[1]);  
            bool ok = radio.write(&toSend, (sizeof(long)*2));
            }
            if (ok){
              printf("\n time packets 2 and 3 have been succesfully sent..\n");       
            }
            else {
              printf("\n time packets 2 and 3 have not been sent..\n\r");
            }
            pending = false;
            radio.startListening();
            printf("now listening \n\r");
         }
      } else {
        ledState = LOW;
      }
      digitalWrite(led_pin, ledState);     
  }
}


void syncMethod()
{
printf("\n\rStart of sync methode");


  // Take the time, and send it.  This will block until complete

    // First, stop listening so we can talk.
    imsyncing=true;
    t1 = millis();
    printf("\ntime packet 1: %ld \n", t1);  
    radio.stopListening();
    printf("stopped listening \n\r");
    bool ok = radio.write(&t1, sizeof(long));

    if (ok){
      printf("time packet 1 sent to the other node..\n");        
      // Listening to an answer includint time packets 2 and 3.
      radio.startListening(); 
      printf("now listening \n\r"); 
      //Wachten op antwoord
      long started_waiting_at = millis();
      bool timeout = false;
      while ( ! radio.available() && ! timeout ){
        if (millis() - started_waiting_at > 2000 ){
          timeout = true;
        }
      }
    
    if(timeout){
      printf("\n time packets 2 and 3 haven't been received2");
    } else {
      printf("\n time pakcets 2 and 3 received");
      long answer[2];
      radio.read( &answer, (sizeof(long)*2) );
      delay(20);       
      t4 = millis();
      t2 = answer[0];
      t3 = answer[1];
      printf("\n t1: %ld -- t2: %ld -- t3: %ld -- t4: %ld", t1, t2, t3, t4); 
      int RTT = (t4-t1) - (t3-t2);
      digitalWrite(led_pin, HIGH);
      previousMillis = millis() - (RTT/2); 
      printf("\n previous millis: %ld", previousMillis);     
    }

    }
    else {
      printf("time packet one wasn't sent\n\r");   
      radio.startListening();
      printf("now listening \n\r");

    }
    

    
    
  imsyncing = false;
   
   printf("End of sync method\n\r");
}

PS we’re rookies

The nRF24L01+ transceivers provide half duplex communication between pairs of nodes. You can't use it directly to implement a broadcast or multicast. You could potentially get the same sort of effect by having each node poll a time source which returns a timestamp, and then halve the RTT of that poll to estimate how long ago that timestamp was current and set the local clock from that. Given that the clocks would only drift slowly once they were synchronised, this polling would not need to be very frequent. Any node which has established its own clock by polling a time source could itself act as a time source for other nodes, but the more 'hops' there are between the original time source and a given node the less accurate its clock will be. This means a flat hierarchy would work better than a deep one.