Arduino + nRF24L01

Hi.

I have two of these cards nRF24L01, each connected to an Arduino Duelminove ..

I need help in programming boards, I wanted to work as a receiver and transmitter..
I've been seeing here, but did not realize there much .. Arduino Playground - Nrf24L01

Now already show a photo of the robot.. ImageShack - Best place for all of your image hosting and image sharing needs

Thanks

  • the site http://blog.diyembedded.com/ has a general description and quite a few tutorials on how to use the chip. See links on the right side to various pdf's.

Also, the mirf-lib comes with a few simple examples which should you get going. They are pretty extensively commented. Download and unpack the lib. Note that you need also the special SPI-lib from the same location. The Mirf-lib does not work with the SPI-lib which comes with Arduino 22.

Important in the usage of nRF24L01 is that (in Mirf-lib language) the RADDR and TADDR strings are matching, that the payload size is identical on both sides, and also that the channel the units are operating is identical. Speaking of channels: you might want to use another than the default channel, as this one is close to the WLAN channel 1 which is usually jammed with traffic.

Note that you will not get more than a few meters of transmission distance with these units - they are primarily used in wireless presenters, mouses and keyboards.... - no way to control a robot 100 Meters away with that technology.

I've been researching and these must be the right code for programming.?

Uploaded with ImageShack.us

Flavio - that is just part of the story, namely only the listing of the different code groups available. That will get you nowhere. You need to look

  • at the different registers, in order to understand what needs to be set for your specific application
  • at the state diagram of that module (actually quite complicated) in order to do it in the right sequence
  • and finally at the specific commands to read and write registers and to lower or raise signal lines.

or, in other words: get the datasheet of the nRF24L01 and read a lot. Expect to have to do a lot of experiments before you reach your goal, as usually datasheets are not written very well. It's a lot of work. That's why usually people use libraries written by others which simply "do the job". Have a look at the Mirf-library (Arduino Playground - Nrf24L01), it probably does everything you want to do. Note that you have to install the special SPI-lib which is linked on that page.

If you really want to start from scratch, have a look at the code I published here (Poor Man's 2.4 GHz Scanner - Networking, Protocols, and Devices - Arduino Forum) - it's only covering a part of the transmitting operation of the chip, but it should get you going on the low level stuff. Also look at the tinker.eu-stuff linked on the Mirf-Lib page; mbed has probably also some library which can give you ideas on how to operate this specific chip.

However, I recommend using simply one of the libraries which are proven to be working...

I basically wanted a card to send the signal to two potentiometer ..
Can not you give an example.?

Hi Flavio - it is not exactly clear to me what you really want to achieve.

Anyway, here's an example which should work and/or should get you going.

Note that it is based on the old Mirf-library which was using a special Spi-library. The latest version of the Mirf-lib you can download now from the Arduino playground does use the SPI-lib of the Arduino 22 - but I have not tested that one against the code below.

Now to the example: it's basically a very trivial implementation of transmitting information from one Arduino moving around the environment (the "sensor") to a stationary base station. For simplicity, I opted for the following approach:

  • The data is transmitted from the sensor in the form of simple ASCII strings.
  • Each character of the ASCII is transmitted indiviually (very inefficient, but really simple).
  • The base station just pipes the received data via the serial port to the PC.
  • The PC is running software (for example based on Processing) which reads, error-checks and displays the received data.

Thus, it is a kind of a very simple "wireless serial link" between a sensor (transmitting only) and a base station (receiving only).

Here's the code for the base station. The code simply pushes every character value it receives from the nRF24L01 to the serial port. It's up to the PC-program to error-check and analyze what is received.

#include <Spi.h>
#include <mirf.h>

void setup()
{
  Serial.begin(57600);
  
  Mirf.init();
  
  // name the receiving channel - must match tranmitter setting!
  Mirf.setRADDR((byte *)"TX_01");
  
  // just a single byte is transmitted
  Mirf.payload = 1;

  // we use channel 90 as it is outside of WLAN bands 
  // or channels used by wireless surveillance cameras 
  Mirf.channel = 90;
  
  // now config the device.... 
  Mirf.config();  
  
  // Set 1MHz data rate - this increases the range slightly
  Mirf.configRegister(RF_SETUP,0x06);
}

void loop()
{

  byte c; 

  // is there any data pending? 
  if( Mirf.dataReady() )
  {
     // well, get it
     Mirf.getData(&c);

    // ... and write it out to the PC
     Serial.print(c);
  }
}

The sensor now runs the following matching piece of code:

#include <Spi.h>
#include <mirf.h>

// converts a float into a char 
// and sends it via nRF24L01
void transmit( float v)
{
  byte c; 
  char buf[10];
  
  dtostrf(v,9,3,buf);

  for( int i=0 ; i<8 ; i++ )
  { 
    c = buf[i];
    Mirf.send(&c);
    while( Mirf.isSending() ) ;
  }
}

// sends a string via the nRF24L01
void transmit(const char *string)
{
  byte c; 
  
  for( int i=0 ; string[i]!=0x00 ; i++ )
  { 
    c = string[i];
    Mirf.send(&c);
    while( Mirf.isSending() ) ;
  }
}

// send a CR/LF sequence via the nRF24L01
void transmitlf(void)
{
  byte c;
  
  c = '\r';
  Mirf.send(&c);
    while( Mirf.isSending() ) ;
  
  c = '\n';
  Mirf.send(&c);
    while( Mirf.isSending() ) ;
}

void setup()
{
  
  // init the transceiver
  Mirf.init();
  
  // we transmit only a single byte each time
  Mirf.payload = 1;
  
  // selecting a channel which is not too noisy
  Mirf.channel = 90;
  Mirf.config();
 
  // Set 1MHz data rate
  Mirf.configRegister(RF_SETUP,0x06);
  
  // Set address - this one must match the 
  // address the receiver is using!
  Mirf.setTADDR((byte *)"TX_01");
}

void loop() 
{
  float v01,v02; 
  
  // read in some values
  v01 = analogRead(0);
  v02 = analogRead(1);
  
  // transmit a fixed token
  transmit(" : ");
  
  // transmit the first value
  transmit(v01);
  
  // transmit a separator
  transmit(" : ");
  
  // transmit a second token
  transmit(v02);
  
  // transmit a CR/LF for the PC
  // software to sync to
  transmitlf();
 
  // ... just take your time
  delay(100);
}

That's basically it.

The PC software monitors the serial port of the Arduino which is acting as a base station and waits for a CR/LF-sequence to arrive in the data stream in order to start processing.

Once a full string is received, a simple error-checking strategy is employed in the PC software. The first thing to check is whether the two ":" transmitted from the sensor are present.

Furthermore, as the float values are converted by the sensor into strings with a fixed length, the total length of the transmitted string stays constant. However, some bytes might not be received by the base station.

So if you display only data which does have the two ":" transmitted and does have the correct message length, the link becomes quite stable.

As mentioned, this code does not really use any of the advanced features of the nRF24L01, but it should get you started with communications between two Arduinos.

You might want to go further by trying to implement:

  • Transmitting directly binary data in larger data chunks. The nRF24L01 can transmit up to 32byte in one piece.
  • Fine-tuning the Shockburst mode and other transmission parameters for your needs.
  • Implementing a two-communication link.
  • Utilzing/taking care of the FIFO in the nRF24L01.

As the nRF24L01 does feature error-checking in Shockburst mode, such an improved implementation will release the burden of error-checking from the analyzing software running on the PC. The above described method is simple and fast (or quick and dirty, depending on the way you look at it :wink: ).

Hi

I have two potentiometers, one for front and back and another for left and right. For example, W for forward, S for back, A for Left, D for Right and G for stop.. . And just wanted to send nRF24L01 the signal to another receiver nRF24L01..
Basically this is it .. For now I do not want to get into great adventures ..

This is my first experience with programming, even better'm reading it to see if I understand it better ..

Thanks for the help ..

Hi Flavio - that is basically the opposite of what I have described in my previous example. Sadly, I do not have the time to work out an example for you, but you might consider to implement something along the following points:

  • You can read the potentiometers with Arduino's analogRead.
  • This gives you a 10-bit value for each of your 4 channels.
  • You can store the 10-bit value of each channel in 2 bytes. This gives you a total of 2*4=8 bytes to transmit.
  • The nRF24L01 is able to transmit these 8 bytes in a single transmission, including CRC-check and - utilizing Shockburst - automatic retransmission if the initial transmission fails. In your case, this is a much better approach than the single byte transmission I sketched above (which is much slower and does not utilize the nRF24L01-buildin error-checking).
  • From my experience, even in close range you will get some loss of signal. nRF24L01 data links are not reliable for transmission ranges larger than about 2-3m and if there is no direct line of sight between the transceivers. (That's probably why these units feature the autotransmission ability.)
  • So make sure at the receiving end that in case no transmission is received, or if a corrupted transmission is received, your robot stops.
  • If you can, try to use modules with real antennas, not modules with antennas which are printed or soldered on the circuitboard.
  • Try to reduce the datarate as much as you can (1MHz or even lower) - this will increase the link stability and range a little bit.

Maybe some other board members have some code or information to share...

cpixip:

  • From my experience, even in close range you will get some loss of signal. nRF24L01 data links are not reliable for transmission ranges larger than about 2-3m and if there is no direct line of sight between the transceivers. (That's probably why these units feature the autotransmission ability.)

I've found them to be quite good even at distance. Right now I am running a test of 2 units, separated by at least 200ft, on opposite ends of my house and on different floors. My test sent 5000 10-byte packets spaced at 250ms. 180 packets were completely lost, even exhausting all the retries. All the rest made it through OK.

The simplest way to do so would take the information that comes from potentiometers (analogRead between 0 and 1023) and send it immediately by nRF24L01, right.?

200ft Not bad, not expecting much ..

Flavio21:
The simplest way to do so would take the information that comes from potentiometers (analogRead between 0 and 1023) and send it immediately by nRF24L01, right.?

Yup. Just pack it up into a payload and off you go. Each payload can go up to 32 bytes, so plenty of space for most everything you'd want to send to control a robot, I'd imagine.

Spare yourself the hassle of working out all the registers, and use a library. There is the mirf library on the playground. I also wrote my own at http://maniacbug.github.com/RF24/ . In any case, all of cpixip's advice is sound, though I wouldn't recommend sending each value separately.

hi, i am just started using nRF24L01,
i just want know can Arduino use this device communicated with pic16fXXX?
any one have the example?