Go Down

Topic: RF24 Library: Driver for nRF24L01(+) 2.4GHz Wireless Transceiver (Read 236217 times) previous topic - next topic

ellen

#45
Nov 11, 2011, 02:23 am Last Edit: Nov 11, 2011, 02:54 am by ellen Reason: 1
great work the library maniacbug  :P

ps. i am wondering what could be the reason why it takes 5 milliseconds to send 32 bytes (each packet) at 2mbps with your library  :smiley-eek:
(i did set radio.setRetries(0,0); else it was even more if the receiver is off or out of range, 45ms)

unsigned long time = millis();
radio.write(send_payload,32); //5 ms.
Serial.println(millis()-time,DEC);

while it takes 0-1ms with the mirf library

unsigned long time = millis();
Mirf.send((byte *)&time); //0ms.
Serial.println(millis()-time,DEC);

ps. is it also possible to read out the pipe address so that a reveiver can set up an receiving pipe with that address? (needed for unknown/unique adresses) just like how tcpip works for example
because now it seems i can only use upto 6 devices/addresses :~

and/or is it possible to send/read raw packets?
seems it can only receive when the (pipe)address is known, i try to disable shockburst but then i have no clue how to receive the data
there is no clear example in the nrf24l01+ product specification pdf.

hope someone can give me an answer, thanks!

Ellen.

maniacbug


great work the library maniacbug  :P


Thanks!


ps. i am wondering what could be the reason why it takes 5 milliseconds to send 32 bytes (each packet) at 2mbps with your library  :smiley-eek:
(i did set radio.setRetries(0,0); else it was even more if the receiver is off or out of range, 45ms)

while it takes 0-1ms with the mirf library


No idea.  Worth running some tests to find out.


ps. is it also possible to read out the pipe address so that a reveiver can set up an receiving pipe with that address? (needed for unknown/unique adresses) just like how tcpip works for example


What you would want to do is disable Auto-Acknowledge, and have all your transmitters use the same pipe.  Of course you'd have to implement a carrier-detect system where a transmitted made sure the line was clear before transmitting.  Like Ethernet does.


because now it seems i can only use upto 6 devices/addresses :~


Yup.  That's the simplest case.  It would be interesting to extend it for multiple units on the same pipe.  I just haven't needed that.  For multiple nodes, I use a multi-hop system, my RF24Network network layer.  In my use, rarely are >6 nodes within speaking distance from each other.


and/or is it possible to send/read raw packets?
seems it can only receive when the (pipe)address is known


No, I don't think the chip is  set up to do that.


, i try to disable shockburst but then i have no clue how to receive the data
there is no clear example in the nrf24l01+ product specification pdf.


You can turn off shockburst, and you'll still receive data.  You just won't get or send any ACK's.

ellen

Thx! i had already set radio.setAutoAck(false) :)

also i found out what caused the delay in RF24.cpp

whatHappened(tx_ok,tx_fail,ack_payload_available); //causes 2ms delay in TX

write_register(CONFIG, ( read_register(CONFIG) | _BV(PWR_UP) ) & ~_BV(PRIM_RX) );
delay(2); //another 2ms delay in TX

ce(HIGH);
delayMicroseconds(15); //another 15us delay in TX
delay(2); //another 2ms delay in TX

for sending multiple packets with radio.write 5-6ms delay is way to much to get a decent speed
to send send data at full speed (250kbit/1mbit/2mbit) succesfully with only 0-1ms delay i had to change it into this:

Code: [Select]

void RF24::write( const void* buf, uint8_t len )
{
  //bool result = false; <-- excluded because i had to exclude whatHappened

  // Begin the write
  startWrite(buf,len);

  // ------------
  // At this point we could return from a non-blocking write, and then call
  // the rest after an interrupt

  // Instead, we are going to block here until we get TX_DS (transmission completed and ack'd)
  // or MAX_RT (maximum retries, transmission failed).  Also, we'll timeout in case the radio
  // is flaky and we get neither.

  // IN the end, the send should be blocking.  It comes back in 60ms worst case, or much faster
  // if I tighted up the retry logic.  (Default settings will be 1500us.
  // Monitor the send
  uint8_t observe_tx;
  uint8_t status;
  uint32_t sent_at = millis();
  const uint32_t timeout = 500; //ms to wait for timeout
  do
  {
    status = read_register(OBSERVE_TX,&observe_tx,1);
    IF_SERIAL_DEBUG(Serial.print(observe_tx,HEX));
  }
  while( ! ( status & ( _BV(TX_DS) | _BV(MAX_RT) ) ) && ( millis() - sent_at < timeout ) );

  // The part above is what you could recreate with your own interrupt handler,
  // and then call this when you got an interrupt
  // ------------

  // Call this when you get an interrupt
  // The status tells us three things
  // * The send was successful (TX_DS)
  // * The send failed, too many retries (MAX_RT)
  // * There is an ack packet waiting (RX_DR)
  //bool tx_ok, tx_fail; <-- excluded because i had to exclude whatHappened
  //whatHappened(tx_ok,tx_fail,ack_payload_available); //causes 2ms delay in TX :(
 
  //printf("%u%u%u\n\r",tx_ok,tx_fail,ack_payload_available);

  //result = tx_ok; <-- excluded because i had to exclude whatHappened
  IF_SERIAL_DEBUG(Serial.print(result?"...OK.":"...Failed"));

  // Handle the ack packet
  if ( ack_payload_available )
  {
    ack_payload_length = getDynamicPayloadSize();
    IF_SERIAL_DEBUG(Serial.print("[AckPacket]/"));
    IF_SERIAL_DEBUG(Serial.println(ack_payload_length,DEC));
  }

  // Yay, we are done.

  // Power down
  powerDown();

  // Flush buffers (Is this a relic of past experimentation, and not needed anymore??)
  //flush_tx(); <-- gave (timing?) problems sending packets

  //return result; <-- excluded because i had to exclude whatHappened
}


Code: [Select]

void RF24::startWrite( const void* buf, uint8_t len )
{
  ce(LOW); //<--added
 
  // Transmitter power-up
  write_register(CONFIG, ( read_register(CONFIG) | _BV(PWR_UP) ) & ~_BV(PRIM_RX) );
  //delay(2); <--excluded

  // Send the payload
  write_payload( buf, len );

  // Allons!
  ce(HIGH);
  //delayMicroseconds(15);  <--excluded
  //delay(2);  <--excluded
  //ce(LOW); <--excluded
}


maniacbug

#48
Nov 17, 2011, 09:59 pm Last Edit: Nov 17, 2011, 10:01 pm by maniacbug Reason: 1
Ok, I see the overall problem.  This library is tuned to send packets occasionally with high reliability and low power consumption, not to send a non-stop stream of high-speed data.  Your modifications root out some of those optimizations, in favor of higher throughput.  

You also should skip the  power down/power up cycle.  Where you are just jamming data as fast as you can, you want the transmitter powered up the entire time.

The delay(2)'s are too high, although 280us delay is needed after power-up.  The CE(high)/15us delay/CE(low) is useful to conserve power in the case where transmissions are infrequent.  Obviously in your case, that's not needed because you're always jamming packets through.

Are you sure 'whatHappened' causes a 2ms delay?  Anyway if you don't call it, you won't know whether your packet went through.  Ah but then again, you don't care, because you have ACK's off.

ellen

well i am realizing it is maybe better to write my own library since yours is optimized for sending/reading packets occasionally like you say, anyway your library is still very useful to me together with the product specification how to use the chip :) ;)

fca

Hi and thanks for this great library..
i'm starting a project  that wil be something like this http://arduino.cc/forum/index.php/topic,79855.0.html


i will have a base station and 5 remote units...
maniacbug, can you help me out... (maybe some newbie questions)

do i need to go with the "complex"  mesh network or can i make it a simple client to base  from each remote sensor to the base...

if i understand correct the mesh network example if i setup all the sensors as "relays" i can increase the distance from the base to the last sensor because the packet is rerouted between each sensor i.e

if sensor5 is not in range with base but sensor5 is in range with sensor4 and sensor 4 with base the packet will go s5->s4->base , is this correct ?
(maybe one advantage in the mesh network)..

reading you mesh code example, i don't understand how to set the role, is the role hard encoded on the table

Quote
const node_info topology[] =
{
  { 0x0000000000LL, 0x0000000000LL,-1 }, // Base
  { 0xF0F0F0F0E1LL, 0x3A3A3A3AE1LL, 0 }, // Relay
  { 0xF0F0F0F0D2LL, 0x3A3A3A3AD2LL, 1 }, // Leaf
  { 0xF0F0F0F0C3LL, 0x3A3A3A3AC3LL, 1 }, // Leaf
  { 0xF0F0F0F0B4LL, 0x3A3A3A3AB4LL, 1 }, // Leaf
  { 0xF0F0F0F0A5LL, 0x3A3A3A3AA5LL, 0 }, // Leaf, direct to Base

and then the role will be defined  taking the the address i set  by serial console?
i mean if i choose address 0 then this will be the base if i choose address 3 will be leaf ?


I don't understand where on the payload is the data to send...



i just ordered nrf24l01 modules, can i do a mesh network (just for testing) with 2 ?

I will transmit few bytes every 5 minutes, if i reduce the speed to 1mbit will the range, increase ?

But i still waiting for the modules maybe later in real testing i will understand it better..

Regards and thanks for your great work...





maniacbug


Hi and thanks for this great library..


Hi.  Thanks for writing, and good luck with your project!

The first thing to understand is that RF24 is only a driver for the wireless module.  It does not include any networking of any sort.  It's just a way to send messages between radios.

In your case, you may not need anything fancy.  A radio using RF24 can communicate easily with 6 other radios as long as they are all in range of the base.  The starping is the example to try out in this case.

If you really want something a bit more complex, you can check out RF24Network.  This includes a minimal networking feature set to provide static addressing and routing across the network.  It doesn't implement a true 'mesh' topology, but rather a 'tree' topology.

Quote

if sensor5 is not in range with base but sensor5 is in range with sensor4 and sensor 4 with base the packet will go s5->s4->base , is this correct ?


If you use RF24Network, yes you can set the network up to do as you say, but it's all STATIC.  So you set up node 5 to ALWAYS transmit to node 4, and node 4 to always transmit to the base.  In this case, 5 is a leaf and so it can sleep, but 4 should stay awake to catch traffic from 5.

Quote

reading you mesh code example, i don't understand how to set the role, is the role hard encoded on the table

Code: [Select]

const node_info topology[] =
{
  { 0x0000000000LL, 0x0000000000LL,-1 }, // Base
...



What example are you looking at?  And do you have the current code base?

Quote

if i reduce the speed to 1mbit will the range, increase ?


Yes.  In fact, if you have nRF24L01+ units, you can reduce further to 250kbps which will extend it further still.

fca

Hi the code is from the rf24network..
But I believe that i will have all the modules in range of the base.
So the the starexample is a good start..
I will remove the code from the pong on ping units and ping code from the pong...
Will these have issues with sensors sending at the same time ?
I would prefer to have the base pulling from the sensors but then I couldnt put the sensors sleeping...

Thanks

maniacbug

Quote

I will remove the code from the pong on ping units and ping code from the pong...


That's fine.  I prefer them together because it makes it much easier to maintain a single sketch rather than 2 and have to keep track of which sketch is on which board.  Totally personal preference of course.

Quote

Will these have issues with sensors sending at the same time ?


Shouldn't have problems because the radios have built-in retries.  You can also crank up the retries to 15 retries, which should totally overcome any collisions.

Quote

I would prefer to have the base pulling from the sensors but then I couldnt put the sensors sleeping...


Right.  The usual design is to have the sensors send for this very reason.

direk

Hi guys!

I have some problems with RF24... Cannot make it work in any way... I took pingpair example (the newest one), burned it on two differend devices and got results on rs232:

Quote

RF24/examples/pingpair/
ROLE: Pong back
STATUS           = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1     = 0xf0f0f0f0d2 0xf0f0f0f0e1
RX_ADDR_P2-5     = 0x69 0x96 0xa5 0xc3
TX_ADDR          = 0xf0f0f0f0d2
RX_PW_P0-6       = 0x08 0x08 0x20 0x20 0x20 0x20
EN_AA            = 0x3f
EN_RXADDR        = 0x3f
RF_CH            = 0x4c
RF_SETUP         = 0x07
CONFIG           = 0x0f
DYNPD/FEATURE    = 0x00 0x06
Data Rate        = 1MBPS
Model            = nRF24L01+
CRC Length       = 16 bits
PA Power         = PA_HIGH


And the second one:
Quote

RF24/examples/pingpair/
ROLE: Ping out
STATUS           = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1     = 0xf0f0f0f0e1 0xf0f0f0f0d2
RX_ADDR_P2-5     = 0x00 0x00 0xd8 0x2f
TX_ADDR          = 0xf0f0f0f0e1
RX_PW_P0-6       = 0x08 0x08 0x2c 0x34 0x00 0x06
EN_AA            = 0x23
EN_RXADDR        = 0x12
RF_CH            = 0x4c
RF_SETUP         = 0x06
CONFIG           = 0x0f
DYNPD/FEATURE    = 0x00 0x05
Data Rate        = 1MBPS
Model            = nRF24L01+
CRC Length       = 16 bits
PA Power         = PA_HIGH
Now sending 431...failed.
Failed, response timed out.
Now sending 2155...failed.
Failed, response timed out.
Now sending 3861...failed.
Failed, response timed out.
...


As you see the second one is sending, but the first one is not replying and I have no idea why. What kind of tests can I make to find issue?

maniacbug

Can you try removing power from both units and then plug them back in.  Config=0f on both units doesn't seem right.

luxeomni

just a quick question from a project of mine point of view:
In theory could the r24network library could work with something like 0 to 99 nodes ? ( the nodes won't necessary send data at the same time) ?

And a little other question : do you know if someone came up with a pcb design as small as possible with mcu + nrf24l01+ integrated ?

maniacbug


just a quick question from a project of mine point of view:
In theory could the r24network library could work with something like 0 to 99 nodes ? ( the nodes won't necessary send data at the same time) ?


RF24Network is pretty specialized and bare-bones.  Any given node will only listen to 6 other nodes at once, taking advantage of the chip's built in pipes.  If you weren't worried about collisions, you could have many nodes with the same node address.  So the parent node would listen to all of those nodes thinking it was a single node.


And a little other question : do you know if someone came up with a pcb design as small as possible with mcu + nrf24l01+ integrated ?


You could take a look at my sensor node.  This is the small PCB I use, although it's still through-hole so it could be even smaller with SMD parts. 

direk

#58
Dec 04, 2011, 10:38 am Last Edit: Dec 04, 2011, 01:53 pm by direk Reason: 1
I was trying to upload other samples, restart whole devices or only nRF module, etc... without success... I have no idea what is going wrong, If it will be SPI problem I belive that other config values will be zeros or FF's...

PS.
  radio.powerDown();
  radio.printDetails();  -> gives me config 0x0d
  radio.powerUp();
  radio.printDetails();  -> gives me config 0x0f

luxeomni




RF24Network is pretty specialized and bare-bones.  Any given node will only listen to 6 other nodes at once, taking advantage of the chip's built in pipes.  If you weren't worried about collisions, you could have many nodes with the same node address.  So the parent node would listen to all of those nodes thinking it was a single node.

You could take a look at my sensor node.  This is the small PCB I use, although it's still through-hole so it could be even smaller with SMD parts. 


So basically i could have multiple nodes with same adress, but with different IDs? ( not bothering with collisions ).

Go Up