Closed boguslawb closed 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.
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 ?
@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/
@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.
@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!
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
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.
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:
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.
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.
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);
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
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.
@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
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:
note: The radio.flushTX() command is available if you do need to flush the outgoing buffer.
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:
Ack payloads are dynamic payloads. You are using dyn plds by force on pipes 0 & 1. Check radio.printDetails()
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!
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...
@TMRh20: if that's the best we can collectively do, we will all go back to making our own wagon wheels. :-)
@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
@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.
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
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.
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 ?
I think it must be some issue with hardcode communication speed when using softSPI mode, because even at 1MBPS it doesn't work.
@boguslawb SoftSPI has been tested and is working at all datarates. Please check your code, config and test with the known examples.
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
Maybe it matters that I'm using Linux Voyager (which is a variant of Ubuntu).
@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.
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
Sorry, my mistake. I have no clue why it works at 2MBPS only :-(
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
why is rf_setup different in both cases ? 250KBPS - RF_SETUP = 0x27 2MBPS - RF_SETUP = 0x0f
?
@boguslawb Have you tried using the default sketches and then changing speed on both of them (only speed)?
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.
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.
Sure,I know.
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 ?
@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).
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.
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 ?