Connecting Two Arduinos with nRF24L01

Hi everybody! I'm working on a project which involves the use of two Arduino UNO boards.
It's a sort of chrono sensor. On both i installed an UltraSonic HC-04 Module and i have to connect it with the nRF24L01 Upgraded Version (the green one).
I'm still working on the two codes, here's the one of the "Start Sensor":

#include "RTClib.h"
#include <Wire.h>
RTC_DS1307 RTC;
int trigPin = 2;
int echoPin = 3;
int ledVerde = 12;
int ledRosso = 13;
int ct;
int s;
int m;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();
  if (! RTC.isrunning()) {
    Serial.println("RTC is NOT running");
  }
  DateTime now = RTC.now();
  DateTime compiled = DateTime(__DATE__, __TIME__);
  if (now.unixtime() < compiled.unixtime()) {
    Serial.println("RTC is older than compile time! UPDATING");
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  Serial.println("Cronometro pronto.");
  pinMode(trigPin, OUTPUT); 
  pinMode(echoPin, INPUT); 
  pinMode(ledVerde, OUTPUT);
  pinMode(ledRosso, OUTPUT);
}

void loop() {
  digitalWrite(ledRosso, HIGH);
  digitalWrite(ledVerde, LOW);
  int duration;
  int distance;
  digitalWrite(trigPin, HIGH);
  delay(1);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  if (distance <= 100 && distance >= 0) {
  digitalWrite(ledVerde, HIGH);
  while (digitalRead(ledVerde) == HIGH) {
  timer();
  }
 }
}

void timer() {
  DateTime now = RTC.now();

  Serial.print("Tempo: ");
  Serial.print(now.year(), DEC);
  Serial.print("/");
  Serial.print(now.month(), DEC);
  Serial.print("/");
  Serial.print(now.day(), DEC);
  Serial.print(" ");
  Serial.print(now.hour(), DEC);
  Serial.print(":");
  Serial.print(now.minute(), DEC);
  Serial.print(":");
  Serial.print(now.second(), DEC);
  Serial.println();

  delay(1000);
 }

And here's the one of the "Arrive Sensor":

#include <LiquidCrystal.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
int trigPin = 6;
int echoPin = 7;
int ct;
int s;
int m;

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
RF24 radio(7, 8);
const byte addresses[] [6] = {"00001"};

void setup() {
  lcd.begin(16, 2);
  radio.begin();
  radio.openWritingPipe(addresses[1]);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(trigPin, OUTPUT); 
  pinMode(echoPin, INPUT);
}

void loop() {
  int duration;
  int distance;
  digitalWrite(LED_BUILTIN, LOW);
  digitalWrite(trigPin, HIGH);
  delay(1);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  if (distance <= 100 && distance >= 0) {
  digitalWrite(LED_BUILTIN, LOW);
  while (digitalRead(LED_BUILTIN) == LOW) {
  !timer();
  }
  radio.write(timer, sizeof(timer));
  delay(1000);
 }
}

void timer() {
  ct = ct + 1;
  lcd.print(m);
  lcd.print(":");
  lcd.print(s);
  lcd.print(".");
  lcd.print(ct);
  delay(95.65);
  lcd.clear();
  if (ct == 10) {
    ct = 0;
    s = s + 1;
  }
  if (s == 60) {
    s = 0;
    m = m + 1;
  }
 }

Now, the problem.
Both have to work as a transmitter and as a receiver.
The first one has to transmit the void "timer()" to start on the second module when the bike pass in front of the "Start Sensor", where it should appear on an lcd screen.
When the bike pass in front of the "Arrive Sensor", it has to send a signal to the "Start Sensor" to stop the void "timer()".

I can't figure out how to send the signals and how to stop the void "timer()"!
Could you help me out?
Thanks in advance, best regards

Have a look at this Simple nRF24L01+ Tutorial. The system in the second example (using the ackPayload feature) is a very convenient way to have 2-way communication.

Wireless problems can be very difficult to debug so start by getting your wireless communication working before adding any other features.

...R

The first one has to transmit the void "timer()"

You can't transmit a function. There are NO voids in your code (only in your terminology). There are FUNCTIONS.

Try again, to describe what you want to transmit.

PaulS:
You can't transmit a function. There are NO voids in your code (only in your terminology). There are FUNCTIONS.

Try again, to describe what you want to transmit.

The Arduino board at the arrive zone has to tell to the Arduino board at the start zone to shut off the Green Led and to stop the timer.

I tried by giving this code to the transmitter:

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

#define CE_PIN   8
#define CSN_PIN 9

int trigPin = 6;
int echoPin = 7;

RF24 radio(CE_PIN, CSN_PIN);

const byte address[6] = "00001";

void setup() {
  pinMode(trigPin, OUTPUT); 
  pinMode(echoPin, INPUT);
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
}

void loop() {
  int duration;
  int distance;
  digitalWrite(trigPin, HIGH);
  delay(1);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  if (distance <= 100 && distance >= 0) {
  const char text[] = "STOP";
  radio.write(&text, sizeof(text));
  delay(1000);
  }
 }

And this to the receiver:

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

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int trigPin = 6;
int echoPin = 7;
int ledVerde = 38;
int ledRosso = 39;
int m;
int s;
int dc;

#define CE_PIN   8
#define CSN_PIN 9

RF24 radio(CE_PIN, CSN_PIN);

const byte address[6] = "00001";

void setup() {
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("Tempo: ");
  lcd.setCursor(0,1);
  lcd.print("Nessun tempo");
  pinMode(trigPin, OUTPUT); 
  pinMode(echoPin, INPUT); 
  pinMode(ledVerde, OUTPUT);
  pinMode(ledRosso, OUTPUT);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
}

void loop() {
  int duration;
  int distance;
  digitalWrite(ledRosso, HIGH);
  digitalWrite(ledVerde, LOW);
  digitalWrite(trigPin, HIGH);
  delay(1);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  if (distance <= 100 && distance >= 0) {
    digitalWrite(ledVerde, HIGH);
    while (digitalRead(ledVerde == HIGH)) {
    tempo();
    }
  }
   if (radio.available()) {
   char text[32] = "";
   radio.read(&text, sizeof(text));
   Serial.println(text);
   }
  }

void tempo() {

  lcd.print("Tempo: ");
  lcd.setCursor(0,1);
  dc = dc + 1;
  lcd.print(m);
  lcd.print(":");
  lcd.print(s);
  lcd.print(".");
  lcd.print(dc);
  delay(105);
  lcd.clear();

  if (dc == 9) {
  dc = 0;
  s = s + 1;
  }
  
  if (s == 59) {
  s = 0;
  m = m + 1;
  }
}

How can i make the receiver board to shut off the green led when it receives the text from the transmitter board?

Noshirt:
How can i make the receiver board to shut off the green led when it receives the text from the transmitter board?

What data are you sending to the receiver board? And is it receiving it correctly?

...R

Robin2:
What data are you sending to the receiver board? And is it receiving it correctly?

...R

I'm sending it the char "s", as you can see here:

const char text[] = "s";
radio.write(&text, sizeof(text));

And then, here's what it should do the receiver:

if (radio.available()) {
  char text[32] = "";
  radio.read(&text, sizeof(text));
  Serial.println(text);
  delay(10000);
  }
  if (Serial.available()) {
  ser = Serial.read();
  if (ser == "s") {
  delay(50);
  digitalWrite(ledVerde, LOW);
  }
  }

What i'm doing wrong??

Noshirt:
And then, here's what it should do the receiver:

Don't worry yet about what it should do. Just make sure that the 's' is being received.

Note that in C/C++ a single character uses single quotes whereas you are using double quotes "s"

And you can't expect to receive 32 characters

radio.read(&text, sizeof(text));

if you only send 2

Make sure that the array where data is received exactly matches the array that is sending data - as in my examples.

...R

Robin2:
Don't worry yet about what it should do. Just make sure that the 's' is being received.

Note that in C/C++ a single character uses single quotes whereas you are using double quotes "s"

And you can't expect to receive 32 characters

radio.read(&text, sizeof(text));

if you only send 2

Make sure that the array where data is received exactly matches the array that is sending data - as in my examples.

...R

You're right, in fact i didn't know how to tell him to send an 's' instead of an "s" because it would give me an error!
Now i tried with a different code, but didn't upload it yet.
What do you think about it?
TX:

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

int trigPin = 2;
int echoPin = 3;
int ledVerde = 4;
int SentMessage[1] = {000};

RF24 radio(8, 9);

const uint64_t pipe = 0xE6E6E6E6E6E6;

void setup() {
  pinMode(trigPin, OUTPUT); 
  pinMode(echoPin, INPUT);
  pinMode(ledVerde, OUTPUT);
  digitalWrite(ledVerde, LOW);
  radio.begin();
  radio.openWritingPipe(pipe);
}

void loop() {
  int duration;
  int distance;
  digitalWrite(trigPin, HIGH);
  delay(1);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  if (distance <= 100 && distance >= 0) {
    digitalWrite(ledVerde, HIGH);
    SentMessage[0] = 111;
    radio.write(SentMessage, 1);
  }
 }

RX:

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

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int trigPin = 6;
int echoPin = 7;
int ledVerde = 38;
int ledRosso = 39;
int m;
int s;
int dc;
int ReceivedMessage[1] = {000};

RF24 radio(8, 9);

const uint64_t pipe = 0xE6E6E6E6E6E6;

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.clear();
  lcd.print("Tempo: ");
  lcd.setCursor(0,1);
  lcd.print("Nessun tempo");
  pinMode(trigPin, OUTPUT); 
  pinMode(echoPin, INPUT); 
  pinMode(ledVerde, OUTPUT);
  pinMode(ledRosso, OUTPUT);
  radio.begin();
  radio.openReadingPipe(1, pipe);
  radio.startListening();
}

void loop() {
  while (radio.available()) {
  radio.read(ReceivedMessage, 1);
  if (ReceivedMessage[0] == 111) {
    digitalWrite(ledVerde, LOW);
    delay(10);
  }
  }
  int duration;
  int distance;
  digitalWrite(ledRosso, HIGH);
  digitalWrite(ledVerde, LOW);
  digitalWrite(trigPin, HIGH);
  delay(1);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  if (distance <= 100 && distance >= 0) {
    digitalWrite(ledVerde, HIGH);
    while (digitalRead(ledVerde == HIGH)) {
    tempo();
    }
  }
}

void tempo() {

  lcd.print("Tempo: ");
  lcd.setCursor(0,1);
  dc = dc + 1;
  lcd.print(m);
  lcd.print(":");
  lcd.print(s);
  lcd.print(".");
  lcd.print(dc);
  delay(100);
  lcd.clear();

  if (dc == 9) {
  dc = 0;
  s = s + 1;
  }
  
  if (s == 60) {
  s = 0;
  m = m + 1;
  }
}

Noshirt:
but didn't upload it yet.
What do you think about it?

Ask me after you have tried it and have told me how it works.

The Arduino system makes experimenting and learning-by-doing very easy

...R

Robin2:
Ask me after you have tried it and have told me how it works.

The Arduino system makes experimenting and learning-by-doing very easy

...R

It does nothing...

Noshirt:
It does nothing...

Do you mean you have no Serial.print() statements in the code so you can monitor what it is doing? If that is the case then you need to add some.

OR do you mean that you have some print statements and not even one of them is being printed?

If you are still at the stage of trying to get the radios to work why is there LCD stuff in your program?

Have you tried my examples?

...R

Robin2:
Do you mean you have no Serial.print() statements in the code so you can monitor what it is doing? If that is the case then you need to add some.

OR do you mean that you have some print statements and not even one of them is being printed?

If you are still at the stage of trying to get the radios to work why is there LCD stuff in your program?

Have you tried my examples?

...R

I think i found the solution.

That's the TX:

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

#define CE_PIN 9
#define CSN_PIN 53

...

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

RF24 radio(CE_PIN, CSN_PIN);

char dataReceived[10];
bool newData = false;

...

void setup() {
Serial.begin(9600);
  Serial.println("SimpleRx Starting");
  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.openReadingPipe(1, thisSlaveAddress);
  radio.startListening();

...

void loop() {
  if (radio.available()) {
   radio.read(&dataReceived, sizeof(dataReceived));
   newData = true;
  }
  if (newData == true) {
        Serial.print("Data received ");
        Serial.println(dataReceived);
        digitalWrite(ledVerde, LOW);
        newData = false;
    }

...

And that's the RX:

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

#define CE_PIN 9
#define CSN_PIN 10

...

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

RF24 radio(CE_PIN, CSN_PIN);

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

void setup() {

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

...

void loop() {
digitalWrite(ledVerde, HIGH);
    while (digitalRead (ledVerde == HIGH)) {
    bool rslt;
    rslt = radio.write(&dataToSend, sizeof(dataToSend) );

    Serial.print("Data Sent ");
    Serial.print(dataToSend);
    if (rslt) {
    Serial.println("  Acknowledge received");
  } else {
        Serial.println("  Tx failed");

It sends the message "Message 0" but it doesn't turn off the led as i say in "digitalWrite(ledVerde, LOW);"

You have your Rx and Tx mixed up.

You need to post complete programs - and please do so in your next Reply rather than updating the previous Reply as that makes the Thread easier to follow.

Don't try to mix up the code for receiving data with the code for acting on the received data. Put the different pieces of code in separate functions and then you can test them separately.

...R

Solved!

I did it like this:

TX:

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

#define CE_PIN 9
#define CSN_PIN 10

int trigPin = 3;
int echoPin = 4;
int ledVerde = 5;
char dataToSend[10] = "Message 0";
char txNum = '0';

RF24 radio(CE_PIN, CSN_PIN);

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

void setup() {
  Serial.begin(9600);
  Serial.println("SimpleTx Starting");
  pinMode(trigPin, OUTPUT); 
  pinMode(echoPin, INPUT);
  pinMode(ledVerde, OUTPUT);
  digitalWrite(ledVerde, LOW);
  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.setRetries(3,5); // delay, count
  radio.openWritingPipe(slaveAddress);
}

void loop() {
  int duration;
  int distance;
  digitalWrite(ledVerde, LOW);
  digitalWrite(trigPin, HIGH);
  delay(1);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  if (distance <= 100 && distance >= 0) {
    digitalWrite(ledVerde, HIGH);
    while (digitalRead (ledVerde == HIGH)) {
    send();
 }
}
}

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;
}

RX:

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

#define CE_PIN 9
#define CSN_PIN 53

LiquidCrystal lcd(12, 11, 5, 4, 3, 10);

int trigPin = 6;
int echoPin = 7;
int ledVerde = 38;
int ledRosso = 39;
int m;
int s;
int dc;
const byte thisSlaveAddress[5] = {'R','x','A','A','A'};

RF24 radio(CE_PIN, CSN_PIN);

char dataReceived[10];
bool newData = false;

void setup() {
  lcd.begin(16, 2);
  digitalWrite(ledVerde, LOW);
  pinMode(trigPin, OUTPUT); 
  pinMode(echoPin, INPUT); 
  pinMode(ledVerde, OUTPUT);
  pinMode(ledRosso, OUTPUT);
  pinMode(53, OUTPUT);
  Serial.begin(9600);
  Serial.println("SimpleRx Starting");
  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.openReadingPipe(1, thisSlaveAddress);
  radio.startListening();
}

void loop() {
  int duration;
  int distance;
  digitalWrite(ledRosso, HIGH);
  digitalWrite(trigPin, HIGH);
  delay(1);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = (duration/2) / 29.1;
  if (distance <= 100 && distance >= 0) {
    digitalWrite(ledVerde, HIGH);
    while (digitalRead(ledVerde) == HIGH) {
    tempo();
    getData();
    showData();
  }
}
}

void tempo() {

  
  lcd.setCursor(0,1);
  dc = dc + 1;
  lcd.print(m);
  lcd.print(":");
  lcd.print(s);
  lcd.print(".");
  lcd.print(dc);
  delay(100);
  

  if (dc == 9) {
  dc = 0;
  s = s + 1;
  }
  
  if (s == 60) {
  s = 0;
  m = m + 1;
  }
}

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(ledVerde, LOW);
        newData = false;
    }
}

It works perfectly! Now the green led on the receiver shut off when it receive the signal and the time stays still on the LCD! :slight_smile:

Noshirt:
It works perfectly! Now the green led on the receiver shut off when it receive the signal and the time stays still on the LCD! :slight_smile:

Glad you have it working.

It would be a little more obvious how it works if you did it like this (just snippets)

// extract from loop()
    tempo();
    getData();
    updateLed();  // new
    showData();
void updateLed() {
   if (newData == true) {
     digitalWrite(ledVerde, LOW); // line moved from showData()
   }
}

Also, I would not encase the code for checking the radio in a WHILE. Rather than this

  if (distance <= 100 && distance >= 0) {
    digitalWrite(ledVerde, HIGH);
    while (digitalRead(ledVerde) == HIGH) {
      tempo();
      getData();
      showData();
    }
  }

try

  if (distance <= 100 && distance >= 0) {
    digitalWrite(ledVerde, HIGH);
  }
  tempo();
  getData();
  updateLed();
  showData();

...R

Robin2:
Also, I would not encase the code for checking the radio in a WHILE. Rather than this

  if (distance <= 100 && distance >= 0) {

digitalWrite(ledVerde, HIGH);
    while (digitalRead(ledVerde) == HIGH) {
      tempo();
      getData();
      showData();
    }
  }



try


if (distance <= 100 && distance >= 0) {
    digitalWrite(ledVerde, HIGH);
  }
  tempo();
  getData();
  updateLed();
  showData();




...R

I tried like this, but it just makes the timer start from when the Arduino turns on, instead of when the green led turns on... thank you so much anyway :slight_smile:

Noshirt:
I tried like this, but it just makes the timer start from when the Arduino turns on, instead of when the green led turns on... thank you so much anyway :slight_smile:

That does not invalidate the concept I was trying to suggest.

You may need to make a special condition for startup.

...R

Robin2:
You may need to make a special condition for startup.

...R

Like................?

Noshirt:
Like................?

You need to post the complete program in which you used my code suggestion.

...R