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.21k stars 1.02k forks source link

Updated library compatibility issue? #786

Closed Mmessiter closed 2 years ago

Mmessiter commented 3 years ago

I recently (rather late!) downloaded the most recent RF24 library and updated my radio control project. The transmitter worked perfectly and immediately without any code changes. But when I updated the receiver code, it only partially worked with lots of extra lost packets. So I reverted the receiver to the older library which fixed it immediately. I am puzzled! Today I ran some tests with the new library in the receiver code: I increased the packet count between channel hops massively. This reduced error rate by a similar proportion. So it’s clearly changing channel that’s the cause. But why and how to fix it is a mystery. If anyone has a clue I’d really appreciate it!

Malcolm Messiter

2bndy5 commented 3 years ago

Have you made sure the examples work on your setup? I would suggest running scanner example and gettingstarted.ino.

To try to diagnose your particular application, it would be easier to see the code (if you permit it). We haven't changed anything to how the channel is changed. I have to assume it is something to do with timing because you mention your application does channel hopping.

A few other details that you left out:

  1. what platform are running this library on?
  2. what boards are you running this library on?
Mmessiter commented 3 years ago

Thank you! All help very much appreciated!

I use a Teensy 4.0 in the receivers and a Teensy 4.1 in the transmitters.

My code is so far about 6000 lines - I’m happy to share the project as it’s only for fun. I fly model helicopters with it. There’s a brief video on YouTube. https://youtu.be/xAlO0PTQo08

Here’s just the function that changes channel at the receiver end:

void HopToNextFrequency(){ 
                 Radio.stopListening();
                 Radio.setChannel(NextChannel);
                 Radio.startListening();
                 #ifdef DEBUG
                   ShowHopDurationEtc();     
                 #endif     
}

This code works fine on the old version of the library.

During one interesting test, I found that if I remove both the stopListening and startListening calls, with the old library in use, then the error rate increases exactly as if I were using the new library. A clue perhaps?!

Thanks for your help!

2bndy5 commented 3 years ago

I think I came accross that video recently from a MBed thread about comparing ebyte clones and RFM7x clones...

During one interesting test, I found that if I remove both the stopListening and startListening calls, with the old library in use, then the error rate increases exactly as if I were using the new library. A clue perhaps?!

This is a good lead; worth looking into.

Can you provide the exact versions of the RF24 lib that you're talking about. I assume you're comparing v1.4.1 (latest) to some older version.

Mmessiter commented 3 years ago

I will double check library versions and respond in an hour or so. It’s breakfast time here!😃 The newer version was current only two days ago. The older one was current in April I think which is when I moved over to PlatformIO.
… the radio has exceed all my expectations and is really great. Many fellow modelers want to make one! So I’ll share code, STL files, Gerber files… everything.
Thanks!

2bndy5 commented 3 years ago

quick question: Are you following PIO registry releases? or the github releases? The dates have been different since v1.3.11

Mmessiter commented 3 years ago

The older version is dated April 14th this year. I’ve much to learn! I don’t know yet where to see the version number! I found the newer one a couple of days ago more or less by chance. I didn’t see any ‘release’. I will try to learn! Sorry I’m really just an old oboe player learning all this from the beginning!

2bndy5 commented 3 years ago

v1.4.0 introduced an object oriented SPI bus feature. v1.4.1 rolled back that feature concerning SoftSPI implementation. Teensy boards seem to not need the new SPI bus feature... I have a better idea of where to investigate.

Mmessiter commented 3 years ago

Sounds like we’re well on the way to an answer. Hooray! I too will make further tests… incidentally, one reason I want to move to the new library is it’s ability to detect nRF24L01 Chip presence. I want to use two or three in the receiver for better rf reception security, so detecting how many are actually connected is needed!

2bndy5 commented 3 years ago

I made a commit to the rp2xxx branch that rolls back the SPI bus feature for Teensy boards. You can try it out in PIO by running

pio lib install https://github.com/nRF24/RF24.git#rp2xxx

If your project's source code has a local copy of the RF24 library, then you can add this unreleased branch to your platformio.ini file under the lib_deps option (be sure to remove any pre-existing RF24 lib dependency)

[env:teensy40]
platform = teensy
board = teensy40
lib_deps =
  https://github.com/nRF24/RF24.git#rp2xxx

I would greatly appreciate your feedback since I couldn't find anyone to test v1.4.0 on Teensy boards. I can already confirm that the branch will compile because the teensy boards are the only ones that we test compile for in our PIO CI workflow.

Mmessiter commented 3 years ago

That’s fantastic thank you!! I will certainly try this out and report back - today. It may take me a couple of hours because life sometimes get in the way… Thank you - most especially for coping with my ignorance. I will probably learn eventually as I’m rather keen.

2bndy5 commented 3 years ago

Take your time, I'm going to sleep soon.

Mmessiter commented 3 years ago

I was quicker than expected! I have done as you suggest. It successfully compiled using that link which you supplied above. I have tested the result. The error rate is much as before. So this did not fix it. The problem is probably in my code and I will try to find it!

2bndy5 commented 3 years ago

is your code uploaded to a github repo that I can browse?

Mmessiter commented 3 years ago

One moment …. I will send a link …

Mmessiter commented 3 years ago

Ok here is the lot on Dropbox https://www.dropbox.com/sh/pcb2ctkfuetkqr9/AAAzHIdh7cLelY9uk2oV2K0Wa?dl=0

Mmessiter commented 3 years ago

I must learn more about GitHub!

Mmessiter commented 3 years ago

Also … those files on Dropbox will allow anyone to make up this radio. But that might be rather tricky without documentation so I will write a doc file and add it. Eg a 5” Nextion screen is needed, as well as their editor. And several other specific components are needed….

TMRh20 commented 3 years ago

I was thinking that we made some changes to the timing of startListening and stopListening a while back but I’d need the version numbers of the libs u are using to know if that might be the issue.

On Aug 23, 2021, at 5:34 AM, Mmessiter @.***> wrote:

 Also … those files on Dropbox will allow anyone to make up this radio. But that might be rather tricky without documentation so I will write a doc file and add it. Eg a 5” Nextion screen is needed, as well as their editor. And several other specific components are needed….

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android.

2bndy5 commented 3 years ago

code on dropbox uses v1.4.1 on the tx side, and v1.1.5 on the rx side

2bndy5 commented 3 years ago

@TMRh20 are you referring to this release (v1.2.0)

v1.3.8 has some info about startListening() and stopListening()

TMRh20 commented 3 years ago

@2bndy5 Yeah, I was going to suggest printing and adjusting the txDelay variable to a larger delay to see if that affects things. What do you think?

2bndy5 commented 3 years ago

Its worth a try. The channel hopping concerns me a bit. Especially when printing to Serial. In my experience printing out data over Serial can cause significant slow downs. However , the code seems to use ifdef DEBUG /*print stuff*/ #endif

2bndy5 commented 3 years ago

I don't see the code using ACK payloads in the ACK packets (which is fine - just thought I'd mention it).

Mmessiter commented 3 years ago

I can test the results of ideas pretty quickly. I’m also ready to edit my code if that might help. I did try adding short delays here and there. But I was shooting in the dark. I missed of course. I’ll get the document file ready and add it. Then others can build one, test, fly, develop more maybe. It’s great fun. Very few modelers build their radio. You’ll see my PID code in there for quads etc. That part is ‘A work in progress’. Not yet safe in the air! I did fly a quad but it was not very stable so far. Much code still to write.

… I do use ACK payloads for telemetry. Sorry my code might be a bit obscure!

2bndy5 commented 3 years ago

I want to move to the new library is it’s ability to detect nRF24L01 Chip presence.

This can be done from Radio.begin() return value and from Radio.isChipConnected() after setup() is complete.

I want to use two or three in the receiver for better rf reception security, so detecting how many are actually connected is needed!

I assume from the video, you're using PA/LNA modules (perhaps from ebyte?), this inherently requires special attention to make sure the radio's necessary & extraordinary power needs are met. Adding more radios to listen to alternating channels would definitely help (if channel hopping is truely required).

TMRh20 commented 3 years ago

@Mmessiter Then maybe try something like Serial.print(radio.txDelay); to get the operating value of the delay, then adjust it a bit higher or lower to see if that makes a difference in your channel hopping. radio.txDelay = X

Mmessiter commented 2 years ago

Gosh thank you for all this. Much to try and to learn. Yes I’m using EBYTE ML01DP5 mostly. … capacitors I hope handle current surge demands. Seems ok so far. I wanted more than one receiver because of possible loss of signal due to polarization and aerial at bad angle in model. Two at 90 degrees might cover it. If one hears nothing the other might still work!

Mmessiter commented 2 years ago

By the way, how is Radio.txDelay used?

Mmessiter commented 2 years ago

According to our Uk law, channel hopping is needed when transmit power exceeds 10 mW. With hopping, 100mW is allowed.

2bndy5 commented 2 years ago

See the docs about txDelay.

Mmessiter commented 2 years ago

Ok I will!

2bndy5 commented 2 years ago

According to our Uk law, channel hopping is needed when transmit power exceeds 10 mW. With hopping, 100mW is allowed.

This is strange. I've never heard of this before. Looking at the specs for that module, you're max PA is 20dBm (~100mW). I've only ever known channel hoping to be used for avoiding polluted airwaves (with too many RF signals), which is why BLE and WiFi do channel hoping. Do you participate in some kind of drone convention/competition? How far out do you expect to be flying? What data rate are you using? Sorry if these questions seem like newbie queries, I'm just very curious.

Mmessiter commented 2 years ago

I’m glad you’re curious! I am too. Yes the Uk regulations are seldom read in full by anyone. I did read all because the man who runs our local flying club needed reassurance that we remain legal, and hence insured. I just fly for fun with the occasional F3C competition. I am a retired oboe player. But in 1982 I bought an IBM PC to run Mail shots to promote concerts. The software was terrible so I taught myself 8086 assembler and re wrote it all - editor, database, etc. Then I wrote a comms app to get my code onto other popular machines. The Comms app grew into “TRANS-SEND” which sold over 3 million copies. The Internet killed it off in 1994. Long story. Now I’m learning C++ and micro electronics to keep brain ticking over in old age!!

Mmessiter commented 2 years ago

I fly only line of sight of course which is perhaps less than one km. But I want the security of knowing I will not loose control at a great distance. So I tested up to one mile or so. These helicopters cost over £2000 per crash. Better not to crash!!

Mmessiter commented 2 years ago

If I live long enough, I hope to develop the code so that first it has stability, then autonomy, then return-to-home on loss of signal. I think the hardware can do it if I add GPS and an MPU6050. …. Whether I can write the needed code remains to be seen.

Mmessiter commented 2 years ago

I’m using lowest (250k) data rate and max power - for max range. This can update servo positions about 400x per second which is plenty fast enough. They only need about 50x per second.

2bndy5 commented 2 years ago

assembly language is coming back to popularity with the RP2040's new feature to run assembly programs on any GPIO pin (its very exciting - I just haven't had the time to try it out).

I know 250kbps data rate will get you the best distance, but it tends to suffer in terms of reliability (especially when using ACK payloads). The nRF24L01 datasheet recommends increasing the auto-retry delay for ACK payloads on 250kbps (based on the length of the ACK payload + the length of the outgoing payload)

GPS+autonomy requires a magnetometer and calculating your location's declination. The MPU6050 is great for off-loading some expensive calculations (the extra software must be loaded on boot every time though), but it doesn't have a magnetometer. There is mention of attaching another I2C slave to the MPU6050 to act as a magnetometer (in the MPU60xx datasheet), but I've never actually seen anyone try that.


Back to the issue at hand. How are the timeslots for each channel setup? In general, one radio will listen on 1 channel long enough for the other radio to try (& hop to) all channels specified in the channel hoping list. I commonly defer to nordic's gazelle protocol docs for visual aids.

Mmessiter commented 2 years ago

I puzzled last summer for weeks about FHSS algorithms. Here’s what I decided eventually: No time slots. Instead, the channel changes after a fixed number of data packets. Every packet contains a header with packet number and next channel number. Easy! After receiver has received the nth packet it just changes to the next channel. On lost contact, both ends restrict to only a few channels while searching. That allows very rapid recovery. A bonus is that since the transmitter dictates which channel is next, and also knows which channels recently failed, it can avoid these for a more robust connection.

2bndy5 commented 2 years ago

ok. Good thing that you're using a Teensy because that approach is very memory intensive.

If I read that correctly, it sounds like each radio only hops after a successful transmission between them. This should be quite reliable. But how is searching done "on a few channels"?

Mmessiter commented 2 years ago

Both receiver and transmitter know the reduced extent to search when contact is lost. I think it includes only about 10 channels (in case one or two are blocked). The tx tries each for a short period. The receiver tries each for a still shorter period. Reconnection usually takes about 0.2 of a second. Then they both revert to the full range of channels- which by the way is user definable.

2bndy5 commented 2 years ago

That part sounds like timeslots.

Mmessiter commented 2 years ago

I didn’t like the idea of time slots because re-synchronisation might be very hard - and what if time is up half way through a packet? 😳

Mmessiter commented 2 years ago

Teensy 4 is wonderful. 600 times faster than arduino. I love them! I started with Arduino but as soon as code was bigger, it was simply too slow. I wrote a test: just calculate a value for PI to ten places, 50 million times. Arduino took ten minutes to complete. Teensy 4 took one second 🤩

2bndy5 commented 2 years ago

I totally understand. I would've switched it around though. Let TX side do shorter bursts than the RX side listens longer on each channel for searching-based bursts. 10 channels is still a large list of channels for pairing operations. I would've started with a list of 3 (maybe even 6) channels. BLE only uses 3 channels and that latency is laughable.

Mmessiter commented 2 years ago

Incidentally, servo data needed is 12 BITS long so I must store them locally in a 16 bit array. But the send buffer only allows 32 bytes. That’s why my compress library exists. The ignored highest four bits are “not sent” this lossless compression and decompression happens for every packet - and it’s really fast! 😀

Mmessiter commented 2 years ago

… because there are 16 channels plus header etc!

Mmessiter commented 2 years ago

Maybe I should reduce the size of the reconnection channel range! Thanks! I may learn eventually!

2bndy5 commented 2 years ago

The only 2 reason I don't have a Teensy:

  1. $$
  2. Their processing power feels like overkill (my applications aren't that complex)
Mmessiter commented 2 years ago

Overkill is a very good thing in my view! Even rather clumsy code runs quite fast enough 😀

Mmessiter commented 2 years ago

Gotta go for Covid test now…. See you later!