Go Down

Topic: nRF24L01+ and RF24 lib ack failure (Read 4 times) previous topic - next topic

PeterH

I've got a bunch of Arduinos connected together using the RF24 library (http://maniacbug.github.com/RF24/index.html) and nRF24L01+ transceivers.

It's basically working, but I have a strange problem:

Between some pairs of Arduinos, when I send a message the message arrives, but the radio.write() method returns a false (failure) status code. I think this means that the outgoing message was received, but the sender did not receive an ack from the receiver.

The problem is quite widespread; usually, write() succeeds but returns false. Occasionally, when I start up two Arduinos I don't see this problem; the write() returns true (success) every time for hours on end. And then for no apparent reason, it will start returning false.

When problem is occurring, I will occasionally (perhaps 1 in 100 messages) see a successful ack.

I don't think it is a hardware problem - the problem affects all my Arduinos and they are all capable of sending and receiving.

I don't think it is a signal strength problem - I see the problem when the radios are two feet apart or twenty feet apart.

I see the problem with just two Arduinos running - I don't think it is a collision/overlap problem.

I have a suspicion it may be due to internal behaviour of the RF24 library. Sometimes I have an Arduino that is acting as an intermediary between two other Arduinos, and it will consistently fail to send messages that are initiated locally but it will successfully send a message that is being forwarded (i.e. radio.read() immediately followed by radio.write()) and then subsequent write()s will fail.

I have briefly turned on debug within the RF24 library, got a welter of information that I didn't understand and quickly turned it off again.

Here are two small sketches that demonstrate the problem:
Sender code:
Code: [Select]

#include <SPI.h>
#include <OneWire.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"

//
// Hardware configuration
//

RF24 radio(9, 10);
#define RADIO_GROUND 8

const uint64_t receiverAddress = 0x0000000000000001LL;

unsigned long lastMessageMillis;
#define MESSAGE_INTERVAL_MILLIS 10000

unsigned int message = 0;

void setup(void)
{
  //
  // Print preamble
  //

  Serial.begin(9600);
  printf_begin(); // enable stdout to Arduino host serial stream
  printf("\n\rSimpleSender\n\r");

  //
  // Setup and configure radio
  //
  setupRadio();

  lastMessageMillis = 0;
}

void setupRadio()
{
  pinMode(RADIO_GROUND, OUTPUT);
  digitalWrite(RADIO_GROUND, LOW);
  delay(500);
 
  radio.begin();
  radio.setPALevel(RF24_PA_HIGH);
  radio.setRetries(15, 15); // set the number of retries and interval between retries to the maximum
}

void loop(void)
{
  if((millis() - lastMessageMillis) > MESSAGE_INTERVAL_MILLIS)
  {
    lastMessageMillis += MESSAGE_INTERVAL_MILLIS;
    //radio.stopListening();
    radio.openWritingPipe(receiverAddress);
 
    if( radio.write(&message, sizeof(message)) )
    {
      printf("Sent %d\r\n", message);
    }
    else
    {
      printf("Send %d failed\n\r", message);
      // radio.printDetails();
    }
    //radio.startListening();

    message++;
  }
}

Sender output:
Quote

SimpleSender
Send 0 failed
Send 1 failed
Send 2 failed
...

Receiver code:
Code: [Select]

#include <SPI.h>
#include <OneWire.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"

//
// Hardware configuration
//

RF24 radio(9, 10);
#define RADIO_GROUND 8

const uint64_t receiverAddress = 0x0000000000000001LL;

void setup(void)
{
  //
  // Print preamble
  //

  Serial.begin(9600);
  printf_begin(); // enable stdout to Arduino host serial stream
  printf("\n\rSimpleReceiver\n\r");

  setupRadio();
}

void setupRadio()
{
  pinMode(RADIO_GROUND, OUTPUT);
  digitalWrite(RADIO_GROUND, LOW);
  delay(500);

  radio.begin();
  radio.setRetries(15, 15); // set the number of retries and interval between retries to the maximum

  radio.openReadingPipe(1, receiverAddress);
  radio.startListening();
}

void loop(void)
{
  // if there is data ready
  uint8_t pipe;
  unsigned int message;
 
  if ( radio.available(&pipe) )
  {
    if( radio.read(&message, sizeof(message)) )
    {
        printf("RECEIVED %d\r\n", message);
    }
    else
    {
      printf("Radio read failed\n\r");
//      radio.printDetails();
    }
  }
}

Receiver output:
Quote

SimpleReceiver
RECEIVED 0
RECEIVED 1
RECEIVED 2
RECEIVED 3
...


Hardware connections are:

1 GND connected to nano pin D8
2 VCC connected to nano pin 3V3
3 CE connected to nano pin D9
4 CSN connected to nano pin D10
5 SCK connected to nano pin D13 =SCK
6 MOSI connected to nano pin D11 =MOSI
7 MISO connected to nano pin D12 =MISO
8 IRQ not connected

Any idea what I'm doing wrong?
I only provide help via the forum - please do not contact me for private consultancy.

maniacbug

#1
Jan 27, 2012, 04:08 am Last Edit: Jan 27, 2012, 04:14 am by maniacbug Reason: 1

I have a suspicion it may be due to internal behaviour of the RF24 library.


Well, that may very well be! :)  Radio timing can be complex, or it may be a straight-up bug.  Thanks for the example code, I'll try it out.

What rev of the library do you have?  If you downloaded it from the "download" link, it's in the name of the zip file.  If you cloned it from git, do "git log -1".

First thing I would try is a different pipe.  Try to balance the 1's and 0's in the pipe.  The examples from Nordic have pipes like that, e.g. A8A8E1F0C6, etc.

EDIT: Could you also try it with the radio ground tied permanently to the Nano's ground?

maniacbug

Ok, as soon as I made this change, it started working fine.

Code: [Select]

const uint64_t receiverAddress = 0xABCDABCD71LL;

PeterH

Wow, that was a pretty inspired guess!

Yes, when I use that address it seems to be 100% reliable. I'm intrigued to know what difference that made, perhaps it upset the radio's framing algorithm? Anyway it seems to have solved the problem which is all that matters.

Thanks for the help.

I don't suppose it matters now, but in case you're interested the version of RF24 I'm running comes from maniacbug-RF24-d437163.zip.
I only provide help via the forum - please do not contact me for private consultancy.

maniacbug


Wow, that was a pretty inspired guess!

Yes, when I use that address it seems to be 100% reliable. I'm intrigued to know what difference that made, perhaps it upset the radio's framing algorithm? Anyway it seems to have solved the problem which is all that matters.

Thanks for the help.


Cool, glad it's working.  I was always wondering if that was superstition or really needed, but I never bothered to test it.  Until now!


I don't suppose it matters now, but in case you're interested the version of RF24 I'm running comes from maniacbug-RF24-d437163.zip.


Cool.  The Dec 19th version has some speed improvements, but the Nov 2nd version you have should be stable.

danielcugler

Hi guys,

I am so happy to have found this thread. I was experiencing the same problem and changing the pipe address in my sketch made all acks work fine!  :)

However, I would like to set up the pipe address randomly.

My question is: How can I create pipe addresses randomly in a way that could avoid such ack problems?

Do you guys know another way of solving this problem?

Thank you!

PeterH


However, I would like to set up the pipe address randomly.


That seems like an unlikely thing to want to do. What is your underlying objective? I had a possibly similar requirement which was to enable each RF24 device to find an address which was unique within the set of devices near it. In my case I did that by setting up a self-organising tree of devices, where each device tried to identify the devices around it and find which one had the best route to the root of the tree, and arrange for that parent to allocate it a unique address. The idea was that this functions as a loose mesh network that would each device to act as a range extender for the root node. My approach using the ack payloads as a return channel to avoid each device from having to keep pipes open for other devices trying to connect to it.
I only provide help via the forum - please do not contact me for private consultancy.

CaptainJack

Hello all !

Really glad I found this topic! I have a question about the library as well, as well as about your code.

I have tried the GettingStarted example, which comes with the RF24 library. Both my NRF24L01+ modules are working and the ping example works.

Then I uploaded your code to my arduinos, and get no response whatsoever. I used the latter address (0xABCDABCD71LL - btw what does 'LL' mean ? ). Your code doesn't seem to differ from the example, so I don't understand. I added the radio.printDetails for debugging. Results below.

Sender:


Receiver:


(For some reason I can't copy the text from the serial window to anywhere else; can the printf statement make weird characters which prevent copying text?)

So my question is: why do I not get this code to work, while the original example is working?

Thanks in advance,

Jack

PeterH

To copy code from the serial monitor, put the cursor over the text you want to copy and click the left button to set focus on that window, press ctrl+A to select all the text and ctrl+C to copy it all to the clipboard. To post it into a post, click the right mouse button and select 'paste' from the context menu. I recommend pasting the output inside code tags to ensure the forum software doesn't mangle it.

If your sketch doesn't behave the same as the example then there is some difference between them. I suggest comparing the two files to find what the difference is.
I only provide help via the forum - please do not contact me for private consultancy.

CaptainJack

Ah, I see I haven't been too clear about what I did. I did try to ctrl+A, ctrl+C and then ctrl+V. If I try to paste what is shown in the window above I only get:

Code: [Select]


SimpleSender

STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1


and that is either all there is in the clipboard, or for some reason it stops pasting after that point. Mind: after RC_ADDR_PO-1 it pastes a TAB, and then it ends.

I was comparing the sketch you posted above to the GettingStarted sketch which is provided with the library you use. I could not find a functional difference. My guess is the above sketches are working for you, and I was wondering whether you made certain choices in programming that sketch which differ from the examples provided.

Cheers and thanks in advance,

Jack

PeterH

I suggest you try copying from the serial monitor and pasting to notepad to see whether it's the copy which is going wrong, or the  paste.
I only provide help via the forum - please do not contact me for private consultancy.

CaptainJack

Notepad gives the same results as the forum editor.

PeterH

Does all the text highlight when you press ctrl-A? Note that you have to put the focus in the text area by clicking the mouse in it, first. You should also be able to drag-select the text using the mouse. With the text selected, ctrl+c should copy it to the clip-board.
I only provide help via the forum - please do not contact me for private consultancy.

CaptainJack

I have found the culprit I think:

Code: [Select]
void RF24::print_address_register(const char* name, uint8_t reg, uint8_t qty)
{
  char extra_tab = strlen_P(name) < 8 ? '\t' : 0;
  printf_P(PSTR(PRIPSTR"\t%c ="),name,extra_tab);

  while (qty--)
  {
    uint8_t buffer[5];
    read_register(reg++,buffer,sizeof buffer);

    printf_P(PSTR(" 0x"));
    uint8_t* bufptr = buffer + sizeof buffer;
    while( --bufptr >= buffer )
      printf_P(PSTR("%02x"),*bufptr);
  }

  printf_P(PSTR("\r\n"));
}


So if name is more than 8 characters extra_tab gets the value 0. printf will attempt to print this in the line:

Code: [Select]
  printf_P(PSTR(PRIPSTR"\t%c ="),name,extra_tab);

so a zero gets added to the string. This is not visible in the serial monitor window, but will cut of the string in the clipboard. CTRL+A, CTRL+C and CTRL+V will not work in that case.

Cheers,

Jack

Mappy

Hi  Everyone  :)
I have a problem with delay(); if I increase the delay on Sender ,so the receiver cant get any messages.
Such as a code from "PeterH" above

On Sender
unsigned long lastMessageMillis;
#define MESSAGE_INTERVAL_MILLIS  100 ///// If I use more than 100 , the receiver cant get any messages.  :~

thanks for the help.
Map


Go Up