NRF24L01 transmitter delay (out of sync after a while) - traffic light use case

Hi there,

Newbie learning a lot from this forum!

I'm experimenting with two Arduino Uno's equiped with NRF24L01. I'm trying to run a traffic light setup where the main (transmitting) Arduino has a traffic light and controls another Uno's traffic light. In the end I need three receiving traffic lights, so the code is set up for that.

To be flexible in adapting the traffic lights timing, I used the millis-function.

With my receiver powered on, it nicely syncs when powering the transmitter. After a while (<1min) there is already a noticable delay on the receiving side which is ramping up. Rebooting the transmitter solves the issue, so I'm quite sure it's related to an issue on my transmitting side. However, since I'm looping through the lights one by one I don't understand how the receivers end up with the delay while the local one on the transmitter isn't. I would expect all lights to be delayed, but still in sync.

Any thoughts where it might be going wrong?

TX

// master light

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); // CE, CSN         
const byte receiver2[6] = "10102";     //address of light2
const byte receiver3[6] = "10103";     //address of light3
const byte receiver4[6] = "10104";     //address of light4

// ******************** //
// LIGHT SETTINGS BEGIN //
// ******************** //

// light1 settings
long red1Time = 2000;   // light 1 time settings
long orange1Time = 2000;
long green1Time = 2000;
long light1Time = 0;    // green light starting offset

// light2 settings
long red2Time = 2000;   // light 2 time settings
long orange2Time = 2000;
long green2Time = 2000;
long light2Time = 2000; // green light2 starting offset

// light3 settings
long red3Time = 2000;   // light 3 time settings
long orange3Time = 2000;
long green3Time = 2000;
long light3Time = 4000;    // green light3 starting offset

// light4 settings
long red4Time = 2000;   // light 4 time settings
long orange4Time = 2000;
long green4Time = 2000;
long light4Time = 0;    // green light4 starting offset

// ****************** //
// LIGHT SETTINGS END //
// ****************** //

// light1 on master arduino
int light1[4] = {0,0,0,0}; // red, orange, green, closing
const int PIN_RED_1 = A5;
const int PIN_ORANGE_1 = A4;
const int PIN_GREEN_1 = A3;

// light2, light3, light4 on slave arduinos
int light2[4] = {0,0,0,0}; // red, orange, green, closing
int light3[4] = {0,0,0,0}; // red, orange, green, closing
int light4[4] = {0,0,0,0}; // red, orange, green, closing

unsigned long startTime1=millis();
unsigned long startTime2=millis();
unsigned long startTime3=millis();
unsigned long startTime4=millis();
unsigned long now;

void setup() {
  radio.begin();                  //Starting the Wireless communication
  radio.setPALevel(RF24_PA_MIN);  //Set at minimum distance
  radio.stopListening();          //This sets the module as transmitter
  
  pinMode(PIN_RED_1,OUTPUT);
  pinMode(PIN_ORANGE_1,OUTPUT);
  pinMode(PIN_GREEN_1,OUTPUT);

  // start light1 at green
  light1[3] = 1;
  digitalWrite(PIN_GREEN_1,light1[3]);
  
  // start light2 at green
  light2[3] = 1;
  radio.openWritingPipe(receiver2);
  radio.write(&light2, sizeof(light2));
  
  // start light3 at green
  light3[3] = 1;
  radio.openWritingPipe(receiver3);
  radio.write(&light3, sizeof(light3));
  
  // start light4 at green
  light4[3] = 1;
  radio.openWritingPipe(receiver4);
  radio.write(&light4, sizeof(light4));
}

void loop() {
  now = millis();
  if( now - startTime1 > light1Time)
    light(1);
  if( now - startTime2 > light2Time)
    light(2);
  if( now - startTime3 > light3Time)
    light(3);
  if( now - startTime4 > light4Time)
    light(4);
}

// function switches light to next color
void light(int number){
  int run=0;  // to check if light already changed in function
  
  if( number == 1 ){  // light1
    if( light1[1] == 1 && run==0){       // check red light, if so, switch to green
      light1[1] = 0;
      light1[3] = 1;
      light1Time = green1Time;
      digitalWrite(PIN_RED_1,light1[1]);
      digitalWrite(PIN_GREEN_1,light1[3]);
      run=1;
    }
    if( light1[2] == 1 && run==0){       // check orange light, if so, switch to red
      light1[2] = 0;
      light1[1] = 1;
      light1Time = red1Time;
      digitalWrite(PIN_RED_1,light1[1]);
      digitalWrite(PIN_ORANGE_1,light1[2]);
      run=1;
    }
    if( light1[3] == 1 && run==0){       // check green light, if so, switch to orange
      light1[3] = 0;
      light1[2] = 1;
      light1Time = orange1Time;
      digitalWrite(PIN_ORANGE_1,light1[2]);
      digitalWrite(PIN_GREEN_1,light1[3]);
      run=1;
    }
    startTime1 = millis();
  }
 
  if( number == 2 ){  // light2
    radio.openWritingPipe(receiver2);
    if( light2[1] == 1 && run==0){       // check red light, if so, switch to green
      light2[1] = 0;
      light2[3] = 1;
      light2Time = green2Time;
      radio.write(&light2, sizeof(light2));
      run=1;
    }
    if( light2[2] == 1 && run==0){       // check orange light, if so, switch to red
      light2[2] = 0;
      light2[1] = 1;
      light2Time = red2Time;
      radio.write(&light2, sizeof(light2));
      run=1;
    }
    if( light2[3] == 1 && run==0){       // check green light, if so, switch to orange
      light2[3] = 0;
      light2[2] = 1;
      light2Time = orange2Time;
      radio.write(&light2, sizeof(light2));
      run=1;
    }
    startTime2 = millis();
  }

  if( number == 3 ){  // light3
    radio.openWritingPipe(receiver3);
    if( light3[1] == 1 && run==0){       // check red light, if so, switch to green
      light3[1] = 0;
      light3[3] = 1;
      light3Time = green3Time;
      radio.write(&light3, sizeof(light3));
      run=1;
    }
    if( light3[2] == 1 && run==0){       // check orange light, if so, switch to red
      light3[2] = 0;
      light3[1] = 1;
      light3Time = red3Time;
      radio.write(&light3, sizeof(light3));
      run=1;
    }
    if( light3[3] == 1 && run==0){       // check green light, if so, switch to orange
      light3[3] = 0;
      light3[2] = 1;
      light3Time = orange3Time;
      radio.write(&light3, sizeof(light3));
      run=1;
    }
    startTime3 = millis();
  }

  if( number == 4 ){  // light4
    radio.openWritingPipe(receiver4);
    if( light4[1] == 1 && run==0){       // check red light, if so, switch to green
      light4[1] = 0;
      light4[3] = 1;
      light4Time = green4Time;
      radio.write(&light4, sizeof(light4));
      run=1;
    }
    if( light4[2] == 1 && run==0){       // check orange light, if so, switch to red
      light4[2] = 0;
      light4[1] = 1;
      light4Time = red4Time;
      radio.write(&light4, sizeof(light4));
      run=1;
    }
    if( light4[3] == 1 && run==0){       // check green light, if so, switch to orange
      light4[3] = 0;
      light4[2] = 1;
      light4Time = orange4Time;
      radio.write(&light4, sizeof(light4));
      run=1;
    }
    startTime4 = millis();
  }
}

RX

// slave light

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); // CE, CSN

// ********************** //
// SET LIGHT NUMBER BEGIN //
// ********************** //

const byte receiver[6] = "10104"; // 10102 light2; 10103 light3; 10104 light4

// ******************** //
// SET LIGHT NUMBER END //
// ******************** //

int light[4];

const int PIN_RED = A5;
const int PIN_ORANGE = A4;
const int PIN_GREEN = A3;

void setup() {
  radio.begin();
  radio.openReadingPipe(0, receiver);  //Setting the address at which we will receive the data
  radio.setPALevel(RF24_PA_MIN);       //Set at minimum distance
  radio.startListening();              //This sets the module as receiver

  pinMode(PIN_RED,OUTPUT);
  pinMode(PIN_ORANGE,OUTPUT);
  pinMode(PIN_GREEN,OUTPUT);
  }
void loop()
{
  if (radio.available())                //Looking for the data.
  {
    radio.read(&light, sizeof(light));  //Reading the data
  }
  digitalWrite(PIN_RED,light[1]);
  digitalWrite(PIN_ORANGE,light[2]);
  digitalWrite(PIN_GREEN,light[3]);
}

You could put all the information into a single packet that is received by all controlled nodes,
there would be no problem with synchronization.

Look up Optimized high speed nRF24L01+ driver class documentation: RF24 Class Reference
and Optimized high speed nRF24L01+ driver class documentation: RF24 Class Reference.

The int arrays that you are transmitting are used as boolean, that's very inefficient.