Topics > Robotics

Arduino + nRF24L01

<< < (2/3) > >>

cpixip:
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.


--- Code: ---
#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);
  }
}

--- End code ---


The sensor now runs the following matching piece of code:


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

--- End code ---


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 ;) ).

Flavio21:
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 ..

cpixip:
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...

maniacbug:

--- Quote from: cpixip on Apr 25, 2011, 09:17 pm ---


* 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.)


--- End quote ---


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.

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.?

200ft Not bad, not expecting much ..

Navigation

[0] Message Index

[#] Next page

[*] Previous page

Go to full version