nRF24 / RF24

OSI Layer 2 driver for nRF24L01 on Arduino & Raspberry Pi/Linux Devices
https://nrf24.github.io/RF24
GNU General Public License v2.0
2.24k stars 1.02k forks source link

nrf24l01+ works fine with RF24 only at 2MBPS #137

Closed boguslawb closed 9 years ago

boguslawb commented 9 years ago

Hi I'm trying to use lower speed then 2MBPS to communicate between two nrf24L01+ modules every 1 second, but only 2MBPS works. The communication require to send 32 bytes between both modules, one is using writeAckPayload() of one struc and then read() method to get the request (another struct) from the other. The other one is using write() then check if available() and read() payload.

What should I check ?

rlogiacco commented 9 years ago

You should check the datasheet because it states the max ack payload length will get shorter when you reduce the data rate. With 32 bytes of data it's already a great success to be able to send it within an ack payload. You can try reducing the retry speed by increasing the first value passed to setAutoRetry function, max value is 15, but that's not guaranteed to work. In practice your ack payload is not received back in time and gets discarded. If you want to use slower data rate you must move away from ack packet payloads.

boguslawb commented 9 years ago

I already have setRetries(15,15), so not much can be done this way. If not by ack then I need to read data and then sent response immediately. I have used two different pipes for reading and writing do I still need to call stopListening before sending back response data ?

if(radio.available()){ radio.read(&data_in,sizeof(data_in)); radio.stopListening(); radio.write(&data_out,sizeof(data_out)); }

would that work fine ? P.S. Is there any forum to discuss the usage of RF24 library ?

rlogiacco commented 9 years ago

@boguslawb I'm not a developer on this library, just a user as you are, and I'm not aware of any specific forums or mailing lists. You might try to start a Google Group for this, though. With regards to your request, if you need to slow down the data rate and you have already tried the setRetries(15,15) option than yes, you need to transmit and receive in two separate steps and the code you were suggesting seems correct to me. The stopListening() function is required to turn the transceiver to transmit mode and you need to have a reading pipe opened on the address you are going to receive data. If you have multiple nodes part of the data_in structure should contain the information required to establish the address for the writing pipe, but if you have only two parties talking then that's not necessary.

I'm writing a walk through for nRF24 modules using this library on my blog https://rlogiacco.wordpress.com/2015/09/21/nrf24-walk-through-introduction/

TMRh20 commented 9 years ago

@boguslawb Try adding the following line to the GettingStarted_CallResponse.ino example sketch after radio.begin(): radio.setDataRate(RF24_250KBPS);

That is an example of how to properly use ACK payloads. If you still have problems @ < 2MBPS then you have some kind of other problem. (not software)

@rlogiacco

You seem to have a pretty good understanding of the retries and ack-payloads, but may be misinterpreting the datasheet or functionality a bit. In my experience, ack payloads are very reliable at any data rate.

You should check the datasheet because it states the max ack payload length will get shorter when you reduce the data rate.

This is kind of correct and incorrect at the same time, as the max ack payload length is always 32 bytes if the retry periods are adjusted accordingly. You need to allow a minimum of 500us 1500uS ARD when setting your retry periods ( radio.setRetries(2,1); radio.setRetries(6,1);will work at any data rate and is guaranteed to work with functional hardware and proper coding )

If you want to use slower data rate you must move away from ack packet payloads.

Ack payloads work fine at any data rate. Technically, slower data rates are actually more reliable and provide better range.

rlogiacco commented 9 years ago

@TMRh20 I might be misinterpreting the datasheet (English is not my mother language) but my understanding is the ack packet must be received within the retry delay window or, in other words, before the transmitter tries to send again. Now, longer the ack packet payload, longer the packet stays on air, longer the delay we should set in the transmitter.

The part I'm referring to is section 7.4.2 stating

The ARD defines the time from the end of a transmitted packet to when a retransmit starts on the PTX.
ARD is set in SETUP_RETR register in steps of 250µs. A retransmit is made if no ACK packet is received by
the PTX.
There is a restriction on the length of ARD when using ACK packets with payload. The ARD time must
never be shorter than the sum of the startup time and the time on-air for the ACK packet:
• For 2Mbps data rate and 5 byte address; 15 byte is maximum ACK packet payload length for
ARD=250µs (reset value).
• For 1Mbps data rate and 5 byte address; 5 byte is maximum ACK packet payload length for
ARD=250µs (reset value).
ARD=500µs is long enough for any ACK payload length in 1 or 2Mbps mode.
• For 250kbps data rate and 5byte address the following values apply:

Followed by a table with one row stating 1250µs =< 24 bytes...

I wouldn't personally expect very long ack payloads to work reliably at very low data rate, but I would be very happy if I misunderstood it!

Thanks for all your work and I'm glad about your improvements on this library!

rlogiacco commented 9 years ago

BTW, I'm referring to the datasheet available on the Nordic website as the one usually referenced, hosted by Sparkfun, is a pre release datasheet which does actually report 500uS work at any data rate

TMRh20 commented 9 years ago

The part I'm referring to is section 7.4.2...

Haha, thanks for the correction @rlogiacco . That would make radio.setRetries(5,1) the bare minimum for all data rates and payload sizes... I think.

rlogiacco commented 9 years ago

I will give this setup a try in a few hours and let you know if it works and reliable... but I remain doubtful :wink:

rlogiacco commented 9 years ago

Ok, I gave this a try and, to anticipate the results, the original poster is correct in his statement :disappointed:

I've used the wiring described in my blog posts, using two nano. I've slightly changed the code used for my blog post and available on github https://github.com/rlogiacco/nRF24-Walk-Through changing only the necessary setup parameters: the data rate, the retries and the payload size.

Here are the results:

Data rate Payload size Retries Outcome
2MBPS 2 2,15 OK
2MBPS 20 2,15 OK
2MBPS 20 15,15 OK
1MBPS 20 15,15 FAIL
1MBPS 2 15,15 FAIL
256KBPS 20 15,15 FAIL
256KBPS 2 15,15 FAIL

I then moved to the GettingStarted_CallResponse.ino example and changed the radio initialization only, because I'm using pins 9 and 10, but I wasn't able to make it work without any other modification... Weird.

The code I wrote is based on your pingpair_ack.ino example and it works at 2MBPS.

I've everything set up, so if you want me to do any other test, feel free to ask.

TMRh20 commented 9 years ago

Well, the main problem with testing using code based on pingpair_ack.ino is that the sketch itself is fundamentally flawed. If you read back through the history of issues, ack payloads have been tested and discussed at length.

The 'flaw' is simply that the ack payload should be written to the TX fifo as soon as the radio enters listening mode, otherwise the radio has no ack-payload to send, since this is handled internally by the nrf24l01+ chip.

With the GettingStarted_CallResponse.ino example, you need to also change the 'radio number' in the user config section.

My Results:

Data Rate Payload Size Retries Outcome
2MBPS 32 15, 15 OK
1MBPS 32 15, 15 OK
250K 32 15, 15 OK

If you are having problems getting the main examples (gettingstarted and gettingstarted_callResponse) then you most definitely have other problems.

TMRh20 commented 9 years ago

Just to confirm the datasheet info again as well, the above tests all succeed with a retry value as low as radio.setRetries(5,1);

rlogiacco commented 9 years ago

That's great! And apologies for not having noticed the config part... I was in a hurry :blush:

I can confirm your results and now changing my code reordering the radio config part: is it possible my results depend on that? I cannot spot any other substantial difference as I was setting the ack payload right after switching to listen mode as you suggested....

receiver code is https://github.com/rlogiacco/nRF24-Walk-Through/blob/master/hub/arduino/hub.ino transmitter code is https://github.com/rlogiacco/nRF24-Walk-Through/blob/master/sensor/sensor.ino

in both I've set retries to 5,15, datarate to 1MBPS and payload size to 20 bytes

TMRh20 commented 9 years ago

I'm not sure. Here is my test code: https://gist.github.com/TMRh20/6ff2e7e30a3c93204644

Increasing the no. of retries to 15 from 1 ( radio.setRetries(5,15); ) in this example will increase reliability, but is not technically needed.

rlogiacco commented 9 years ago

@TMRh20 I had an additional startListening() call which was somehow preventing the correct operation: thanks a lot for enlightening me on this pitfall! I'll be sure to have this into my series, hopefully this will help reduce your support requests!

I don't know if you want to further investigate or document somewhere that having two calls to startListening() was preventing slower data rates to deliver ack payloads, which still sounds weird to me...

The specific change is in commit https://github.com/rlogiacco/nRF24-Walk-Through/commit/03c3fcee49eef72d206161554e0ec71d641aac0d

TMRh20 commented 9 years ago

I don't know if you want to further investigate or document somewhere that having two calls to startListening() was preventing slower data rates to deliver ack payloads, which still sounds weird to me...

There are essentially a few rules to using ack payloads that will ensure everything works:

  1. Always write an ack payload immediately after calling radio.startListening(); . Since direct SPI @ 8mhz is always faster than the radio, this ensures that an ack-pld is always waiting for any incoming data. In your prev example this rule was not followed, so the MCU was attempting to write the ack-payloads after receiving data.
  2. Whenever an incoming payload is read, an ack-pld is written. This ensures that incoming vs outgoing is always 1-to-1 so there are never any extra or missing ack payloads. (no need to flush)
  3. Ack payloads are dynamic payloads, so the two features should be enabled.

note: The radio.flushTX() command is available if you do need to flush the outgoing buffer.

rlogiacco commented 9 years ago

Ack payloads are dynamic payloads, so the two features should be enabled.

The code on the above mentioned Github repo works with fixed payload size... and it's reliable as well... So, unless one of the functions following the setPayloadSize() function call is overriding my setting, that statement doesn't sound correct to me. I would say, from my tests, the ack payload must be equal or smaller than the payload size set... which was the reason why I set the payloadsize to 2: only one is transmitted, but 2 are in the ack payload.

note: The radio.flushTX() command is available if you do need to flush the outgoing buffer.

That's good and valuable info, I believe it's going to be faster than my actual stopListening-startListening calls.

Thanks a million for your insights, I hope you don't mind my replies :wink:

TMRh20 commented 9 years ago

Ack payloads are dynamic payloads. You are using dyn plds by force on pipes 0 & 1. Check radio.printDetails()

rlogiacco commented 9 years ago

So, if I understand it correctly, I set the payload size, but by activating ack packet payloads I am turning pipes 0 and 1 into dynamic payload size implicitly, no matter what statement comes first (in my case I first set the ack packet payloads and then payload size). is it like that?

Obviously printDetails reports

DYNPD/FEATURE    = 0x03 0x06

perfectly matching with what you said and even the datasheet reports your a very similar same statement:

If ACK packet payload is activated, ACK packets have dynamic payload lengths and 
the Dynamic Payload Length feature should be enabled for pipe 0 on the PTX and PRX.

It only states pipe 0 though, which makes sense for ack packets, not sure if it does make sense for pipe 1...

Wow, I wasn't aware of all this, very good to know!

TMRh20 commented 9 years ago

It only states pipe 0 though, which makes sense for ack packets, not sure if it does make sense for pipe 1

Hehehe, this is precisely why I try to avoid technical support inquiries, trying to detail the changes or benefits of this library, or discussing the technical details of RF24 modules at all. As you seem to be finding, if you really want to know whats going on, you need to read the datasheet and study the code/docs, and do some testing. That's what I did...

Jeppedy commented 9 years ago

@TMRh20: if that's the best we can collectively do, we will all go back to making our own wagon wheels. :-)

TMRh20 commented 9 years ago

@Jeppedy Touche buddy.

Collectively is different than just me though lol. The idea of a detailed walk through for nRF24 modules is a step in the right direction though, especially if I don't have to write it! This was more of what I was getting at, and why I'm adding my $0.02. :p

TMRh20 commented 9 years ago

@rlogiacco & @Jeppedy The answer is more of a philosophical one than a technical one I think. Since this is meant as essentially a 'raw' driver, it is questionable as to whether the driver should manage the pipes and addresses at all, or leave things in the hands of the user. The problem is that is far too difficult to expect all users to get into all of the details of pipe addressing and management, so the driver just kind of 'does some things' in the background to make your life easier.

The part is the concept of preserving old code, since the library was originally written by maniacbug, and I've attempted to keep things as closely aligned as possible, without restricting development, and preserving things that don't need to be changed. A flawed concept? Maybe.

In the end, the question of whether it makes sense for pipe 1 or not is really a technical question, but a philosophical one.

Are you using pipe1? The examples do, so it does. Do the examples need to? Probably not. Should they be changed to use only pipe0? You tell me? It is simply a matter of preference, so the answer is yes&no.

rlogiacco commented 9 years ago

I get your point @TMRh20 and if it would have been my decision I would have gone down the same route. The really important thing is to communicate those decisions and you actually did in the class docs, but you know very well Arduinoers don't read docs, they tweak examples :smile: And I'm not considering myself different to be honest, but I'm trying to improve :wink:

I completely agree with most you said, that's the reason for my blog series: I was sick of explaining in the forums, over and over, the max 6 nodes limit was just stupid, but apparently most users don't get it. I really hope to manage to correct those misunderstandings and help people use these modules at their best. I hope that series will somehow repay your effort to explain all this to me.

Now better for me to write a bit: if you will be so kind to keep an eye to the blog and correct anything you might find incorrect or confusing I will be really grateful.

Thanks a million, Roberto

boguslawb commented 9 years ago

Please do not close this issue yet. I have to re-check first the available ing pair example then my own code. I'm using 32 byte sized ACK and only using pipes 0 and 1,so the problem must be with the functions calls sequence.

boguslawb commented 9 years ago

Ok.I was able to isolate problem. it is related to SoftSPI and DigitalIO. When I checked with hardware SPI on various CE and CSN pins it worked at any data rate. When I use my shield which has also SD card reader workaround and which defined SoftSPI in RF24_config.h with const uint8_t SOFT_SPI_MISO_PIN = 8; const uint8_t SOFT_SPI_MOSI_PIN = 7; const uint8_t SOFT_SPI_SCK_PIN = 9;

and RF24 Ce and CSN pins set to 5 and 6 - it works only at 2MBPS.

Can you help me with this issue ?

boguslawb commented 9 years ago

I think it must be some issue with hardcode communication speed when using softSPI mode, because even at 1MBPS it doesn't work.

TMRh20 commented 9 years ago

@boguslawb SoftSPI has been tested and is working at all datarates. Please check your code, config and test with the known examples.

boguslawb commented 9 years ago

That's what I did, maybe I messed something with your example, because I had to divide it into two sketches. Here is my test code based on your examples: https://github.com/boguslawb/heatcontrol_V1/blob/master/tests/role_ping_back/role_ping_back.ino https://github.com/boguslawb/heatcontrol_V1/blob/master/tests/role_ping_out/role_ping_out.ino

boguslawb commented 9 years ago

Maybe it matters that I'm using Linux Voyager (which is a variant of Ubuntu).

TMRh20 commented 9 years ago

@boguslawb I think I may have noticed an issue with softspi not configuring auto-ack properly but haven't been able to recreate it since the one time it happened to me. In your radio.printDetails() output, do you see the auto-ack setting showing as 3f ? I'm not sure what to suggest honestly.

@rlogiacco

I was sick of explaining in the forums, over and over, the max 6 nodes limit was just stupid, but apparently most users don't get it.

As I have stated, unless you specifically manage the timing as in a token-ring network, or simply transmit very slowly, the concept of utilizing more than 6 nodes in direct communication with a single master node is technically flawed, and auto-acks will report incorrectly.

This is manufacturer specified and inherent to the design of the radios. There is no way around this.

boguslawb commented 9 years ago

Here is what I got in the Arduino Duemillanove + my shield at 250KBPS >>>>>>>> pong back role <<<<<<<<<< STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0 RX_ADDR_P0-1 = 0x65646f4e32 0x65646f4e31 RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6 TX_ADDR = 0x65646f4e32 RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00 EN_AA = 0x3f EN_RXADDR = 0x02 RF_CH = 0x4c RF_SETUP = 0x27 CONFIG = 0x0f DYNPD/FEATURE = 0x3f 0x06 Data Rate = 250KBPS Model = nRF24L01+ CRC Length = 16 bits PA Power = PA_MAX

boguslawb commented 9 years ago

Sorry, my mistake. I have no clue why it works at 2MBPS only :-(

boguslawb commented 9 years ago

STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0 RX_ADDR_P0-1 = 0x65646f4e32 0x65646f4e31 RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6 TX_ADDR = 0x65646f4e32 RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00 EN_AA = 0x3f EN_RXADDR = 0x02 RF_CH = 0x4c RF_SETUP = 0x0f CONFIG = 0x0f DYNPD/FEATURE = 0x3f 0x06 Data Rate = 2MBPS Model = nRF24L01+ CRC Length = 16 bits PA Power = PA_MAX

boguslawb commented 9 years ago

why is rf_setup different in both cases ? 250KBPS - RF_SETUP = 0x27 2MBPS - RF_SETUP = 0x0f

?

Avamander commented 9 years ago

@boguslawb Have you tried using the default sketches and then changing speed on both of them (only speed)?

boguslawb commented 9 years ago

I tried modified sketches because I have only one computer. I can change speed on one device with lcs screen and buttons. I will try to do the same using serial on the second one if time permit.

Avamander commented 9 years ago

Wait, did you change the communication speed on only one of the nodes? If yes, then you have to use the same speed on both nodes that you wish to use.

boguslawb commented 9 years ago

Sure,I know.

deckboy35 commented 4 years ago

Hi, case closed but unfortunately having exact same issues with datarates. All of my NRF24l01 work only on 2MBPS . I tried them getting started example , have stable connection only on 2MBPS. Is there any known way how to use them on 250KBPS ?

2bndy5 commented 4 years ago

@deckboy35 please open a new issue, and describe your experience with more detail. This issue is related to using ACK payloads attached to the automatically responding ACK packets. The getting started example does not use ACK payloads (nor dynamic payload lengths).

politropov commented 3 years ago

Hi, case closed but unfortunately having exact same issues with datarates. All of my NRF24l01 work only on 2MBPS . I tried them getting started example , have stable connection only on 2MBPS. Is there any known way how to use them on 250KBPS ?

Try to look on your NRF24l01 chip close, if there is no sign + (NRF24l01+) so this is old version and it works just on 1 and 2 MBPS.