Connecting two arduinos wirelessly through NRF24L01 modules in ROS

Hi all,

I have been trying to send commands through Simulink (publisher) to arduino node (subscriber) but have some problems. I can make communications between my arduinos (one UNO and the other one NANO) wirelessly using two NRF24L01 modules. I can also program to subscribe a node in ROS, then I can send continuous values (PWM) to that node and see that using “rostopic echo …” command. However, I am not able to combine the two! In other words, I would like one of my arduinos (say NANO) be connected to the computer using USB, connect to it using rosserial, publish any subscribed node and get values back from my publisher block in Simulink. So far I have been able to do these! Now I want that published value which is sent to my NANO through rosserial (USB cable) be sent over to the other arduino (UNO) as well (wirelessly through NRF24L01 module). The received message in UNO should be shown in terms of a change in a voltage of pin 2 for example.

Code for the transmitter (NANO) is as follows:

#include <ros.h>
#include <std_msgs/Int8.h>
#include "Arduino.h"
#include <SPI.h>
#include <RF24.h>

ros::NodeHandle  nh;

RF24 radio(7, 8);
byte addresses[][6] = {"1Node", "2Node"};


//int toggle_msg;

void messageCb( const std_msgs::Int8& toggle_msg){
   digitalWrite(2, toggle_msg.data);
}

ros::Subscriber<std_msgs::Int8> sub("Arduino", messageCb);

void setup()
{
 Serial.begin(9600);
 pinMode(2,OUTPUT);
 digitalWrite(2,0);
 delayMicroseconds(10);
 
//  nh.initNode();
//  nh.subscribe(sub);

//  Serial.begin(9600);
 Serial.println("THIS IS THE TRANSMITTER CODE - YOU NEED THE OTHER ARDIUNO TO SEND BACK A RESPONSE");
 // Initiate the radio object
 radio.begin();
 // Set the transmit power to lowest available to prevent power supply related issues
 radio.setPALevel(RF24_PA_MIN);
 // Set the speed of the transmission to the quickest available
 radio.setDataRate(RF24_2MBPS);
 // Use a channel unlikely to be used by Wifi, Microwave ovens etc
 radio.setChannel(124);
 // Open a writing and reading pipe on each radio, with opposite addresses
 radio.openWritingPipe(addresses[1]);
 radio.openReadingPipe(1, addresses[0]);
 // Random number seeding (we're going to be sending a single random number)
 randomSeed(analogRead(A0));
 nh.initNode();
 nh.subscribe(sub);
}



void loop()
{


 // Generate a single random character to transmit
 
 unsigned int data = toggle_msg;
 // Ensure we have stopped listening (even if we're not) or we won't be able to transmit
 radio.stopListening(); 
 // Did we manage to SUCCESSFULLY transmit that (by getting an acknowledgement back from the other Arduino)?
 // Even we didn't we'll continue with the sketch, you never know, the radio fairies may help us
 if (!radio.write( &data, sizeof(unsigned char) )) {
   Serial.println("No acknowledgement of transmission - receiving radio device connected?");    
 }
 // Now listen for a response
 radio.startListening();
 // But we won't listen for long, 200 milliseconds is enough
 unsigned long started_waiting_at = millis();
 // Loop here until we get indication that some data is ready for us to read (or we time out)
 while ( ! radio.available() ) {
   // Oh dear, no response received within our timescale
   if (millis() - started_waiting_at > 200 ) {
     Serial.println("No response received - timeout!");
     return;
   }
 }
 // Now read the data that is waiting for us in the nRF24L01's buffer
 unsigned char dataRx;
 radio.read( &dataRx, sizeof(unsigned char) );
 // Show user what we sent and what we got back
 Serial.print("Sent: ");
 Serial.print(data);
 Serial.print(", received: ");
 Serial.println(dataRx);
 // Try again 1s later
 delay(1000);

   digitalWrite(2, 10);
 delayMicroseconds(10);
 nh.spinOnce();
 delay(1000);

}

Code for the receiver (UNO) is as follows:

#include "Arduino.h"
#include <SPI.h>
#include <RF24.h>

// This is just the way the RF24 library works:
// Hardware configuration: Set up nRF24L01 radio on SPI bus (pins 10, 11, 12, 13) plus pins 7 & 8
RF24 radio(7, 8);

byte addresses[][6] = {"1Node","2Node"};

// -----------------------------------------------------------------------------
// SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP   SETUP
// -----------------------------------------------------------------------------
void setup() {
 Serial.begin(9600);
 Serial.println("THIS IS THE RECEIVER CODE - YOU NEED THE OTHER ARDUINO TO TRANSMIT");

 // Initiate the radio object
 radio.begin();

 // Set the transmit power to lowest available to prevent power supply related issues
 radio.setPALevel(RF24_PA_MIN);

 // Set the speed of the transmission to the quickest available
 radio.setDataRate(RF24_2MBPS);

 // Use a channel unlikely to be used by Wifi, Microwave ovens etc
 radio.setChannel(124);

 // Open a writing and reading pipe on each radio, with opposite addresses
 radio.openWritingPipe(addresses[0]);
 radio.openReadingPipe(1, addresses[1]);

 // Start the radio listening for data
 radio.startListening();
 pinMode(2, OUTPUT);

}

// -----------------------------------------------------------------------------
// We are LISTENING on this device only (although we do transmit a response)
// -----------------------------------------------------------------------------
void loop() {
//  digitalWrite(2, 1);
 // This is what we receive from the other device (the transmitter)
 unsigned char data;

 // Is there any data for us to get?
 if ( radio.available()) {

   // Go and read the data and put it into that variable
   while (radio.available()) {
     radio.read( &data, sizeof(char));
     digitalWrite(2, data);


   }

   // No more data to get so send it back but add 1 first just for kicks
   // First, stop listening so we can talk
   radio.stopListening();
   data++;
   radio.write( &data, sizeof(char) );

   // Now, resume listening so we catch the next packets.
   radio.startListening();

   // Tell the user what we sent back (the random numer + 1)
   Serial.print("Sent response ");
   Serial.println(data);

 }
//  if (! radio.available()) {
//    digitalWrite(2 ,1);
//  }
}

Both codes inspired from HERE

I would appreciate any help!

update your post using code tage see section 7 of how to use the forum

I know a little about using the nRF24 but I know nothing about ROS or Simulink.

Your Tx program seems to read data from the nRF24 even if the Tx failed and even if no response was received.

For what you seem to be doing I suspect that AckPayload feature would be a much simpler way to achieve two-way communication. Have a look at the second example in this Simple nRF24L01+ Tutorial. And if you really do need to swap roles between sending and receiving have a look at the third example.

It will be best to get the wireless part working before adding any other features into the program. Then if an added feature breaks the wireless communication it will be immediately obvious where the problem is.

...R

Thanks