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

RPi not receiving data from Arduino using RF24 #685

Closed igal92 closed 3 years ago

igal92 commented 3 years ago

I'm about to pull my hair out, working on this issue for a month already. Tried changing to different RPi's and different Arduinos, but the issue is the same. Confirmed that the hardware is OK as this worked between 2 Arduinos - data successfully transferred.

The idea is to transfer data from Arduino UNO to Raspberry Pi in a 1 way direction.

i also tried the pingpair_dyn and gettingstarted examples from RF24 library on RPi, and the same examples on Arduino - nothing :-( This is really frustrating, any help would be much appreciated!

Connection to RPi: nRF24L01 connection to RPi

RPi PINS are connected as seen here:

My Arduino code is: removed

Raspberry Pi 3B code in the RPi.txt file: removed

Any suggestions what to change?

2bndy5 commented 3 years ago

Thank you for posting so much detail. It seems that is a rare quality when people come here for answers.

pasting the code here it doesn't look good

its all good. github uses markdown syntax, so using 3 backtick (```) to encapsulate your code will look like

```c++ // your code here ```

I suspect a power problem...

  1. What type of radio are you using? Is it the nRF24L01+PA+LNA?
  2. Do you have a capacitor in parallel with the radio's PWR/GND pins? (see also COMMON_ISSUES.md)
  3. Just curious, but can you post what radio.printDetails(); prints out? I'm more concerned with RPi but Uno output would also be appreciated.

About the Uno sketch

About the RPi program

useless suggestions

igal92 commented 3 years ago

Thank you for posting so much detail. It seems that is a rare quality when people come here for answers.

pasting the code here it doesn't look good

its all good. github uses markdown syntax, so using 3 backtick (```) to encapsulate your code will look like

// your code here

I suspect a power problem...

  1. What type of radio are you using? Is it the nRF24L01+PA+LNA?
  2. Do you have a capacitor in parallel with the radio's PWR/GND pins? (see also COMMON_ISSUES.md)
  3. Just curious, but can you post what radio.printDetails(); prints out? I'm more concerned with RPi but Uno output would also be appreciated.

About the Uno sketch

  • setPALevel(RF24_PA_MIN); This is done in the examples to prevent power instability issues, but the solution is a bit of a hack. Using a stable power supply is the better solution. Using RF24_PA_MIN setting will cover the least distance.
  • stopListening(); well done here, this is needed to setup pipe 0 for TX-ing

About the RPi program

  • setPALevel(RF24_PA_MAX); while this is the default setting, it requires the most power. Using RF24_PA_MAX setting will cover the most distance.
  • setRetries(15, 15); this will have no affect on a RX only node as it only affects TX operation.

    • FYI the default setting is setRetries(5, 15)
  • stopListening(); this seems unnecessary as begin() sets up the radio in TX mode, and (this is the important part) you don't use pipe 0 to receive šŸ‘ .

useless suggestions

  • powerUp(); done by calling begin()
  • setDataRate(RF24_1MBPS) This is the default value
  • setChannel(125); have you tried a different channel? Setting this to the max is not like turning up the volume on a stereo. With a value of 125 you're using a frequency of 2.525 GHz (2400 + value = MHz).

    • This function is meant to avoid channels that might already be occupied by ambient signals (like WiFi or Bluetooth)

Hi 2bndy5, Thank you very much for the detailed response! I'm using nRF24L01+ modules - same one as seen in the RPi connection picture in my first post.

I'm using a brand new RPi model 3B with the same sd-card that was on the previous one, and changed the power cable as well to a new one to avoid potential power source issues.

I followed your suggestions and modified the code both in UNO and RPi, but unfortunately I still fail to transfer the data..

I solder a 10uF electrolytic capacitor straight on both of the nRF24L01 modules - when the minus is connected to the GND and the other one to VCC of course. image

For some reason the serial monitor on my arduino UNO doesn't show any output from printDetails() command, but here's my radio.printDetails() from RPi: image

The UNO and RPi are 1-2 meters apart.

The code is modified per your suggestion, i still only get until the radio.available() and the RPi cannot enter this function, i assume the radio is "not" available? also tried with different channels, nothing..

Any suggestions?

igal92 commented 3 years ago

I also tried to use gettingstarted example from both sides, trying to send from each direction - nothing... i don't see the HW Error "check cables connections", which is a good thing, but really don't know what to do now.

image

image

2bndy5 commented 3 years ago

I solder a 10uF electrolytic capacitor

This seems rather small. I usually use 100 uF. Many users from MySensor forums suggest 100 uF + 0.1 uF (which is a common requirement for linear voltage regulators).

The code is modified per your suggestion, i still only get until the radio.available() and the RPi cannot enter this function, i assume the radio is "not" available?

That's not what the function name describes. available() means "is there data in the RX FIFO available?" If the function never returns true, then the radio simply hasn't received data.

arduino UNO doesn't show any output from printDetails()

This seems odd. Usually this problem means the CPU does not have printf() support, but the Uno uses an ATMega328 (which does have printf() support). See the suggestion from the docs about printDetails()

Nonetheless, I still suspect a power problem because the software all looks good.

igal92 commented 3 years ago

I solder a 10uF electrolytic capacitor

This seems rather small. I usually use 100 uF. Many users from MySensor forums suggest 100 uF + 0.1 uF (which is a common requirement for linear voltage regulators).

The code is modified per your suggestion, i still only get until the radio.available() and the RPi cannot enter this function, i assume the radio is "not" available?

That's not what the function name describes. available() means "is there data in the RX FIFO available?" If the function never returns true, then the radio simply hasn't received data.

arduino UNO doesn't show any output from printDetails()

This seems odd. Usually this problem means the CPU does not have printf() support, but the Uno uses an ATMega328 (which does have printf() support). See the suggestion from the docs about printDetails()

Nonetheless, I still suspect a power problem because the software all looks good.

I made a few changes, i formatted the sd-card and installed a clean latest Raspberian version, and didn't updated the OS from the Raspberry Pi as i found that the updates made few changes with kernel, and sometimes this caused the library to not function properly.. i don't really understand how the kernel works and i'm kinda new to linux, so rather not to touch that :)

I'm using now a different nRF24L01+ module, but there is not soldered capacitor, but i'm using an adapter where the VCC is connected now to 5V supply on my arduino, also changed the arduino from UNO to NANO. image

The RF24 core library was installed using the SPI option for compatibility - there are 5: BCM2835, SPI, WiringPi and 2 more...

Now, there is a different issue, both RPi and Nano are 2 meters apart, and i'm using the gettingstarted example while setting the radio.setPALevel(RF24_PA_HIGH), the RF24_PA_LOW didn't worked so well.

Also i moved the testing area away from the router in case of some potential EMI/Noise.

I have a connection now between the modules, successfully transferring data from NANO to RPi, but the roundtrip is ridiculous, shouldn't it be under 100ms? the delay between the pings is 1sec, and the success rate is around 70-80%, which i guess poor performance, especially when i'll have to transfer MPU6050 gyroscope data from NANO to RPi every 50-100[ms]

Is there anything i can do to improve the performance?

image

I also changed the setChannel to 125 on both sides, looks a little bit better as there are way less Failed attempts, 3-4 meters longer distance and the success rate went up to 85-90%, but still the roundtrip time is too high, between 2000 to 50000.

Regarding the Arduino, i still don't get the printDetails() output on the GettingStarted but i do get from Pingpair_dyn example. Honestly, i don't care much as long as I see the data on my RPi.

צילום מהך 2020-11-17 093748

Any recommendations?

TMRh20 commented 3 years ago

I would try a channel on the lower end of the spectrum like ch1. Also, sometimes scraping the end of the antenna lead clean and soldering in a small 3-4ā€ wire can dramatically improve performance per https://tmrh20.blogspot.com/2019/05/rf24mesh-dynamic-mesh-networking-for.html?m=1

At this point itā€™s not a library issue but a hardware/environmental issue imho.

On Nov 17, 2020, at 2:52 AM, igal92 notifications@github.com wrote:

ļ»æ I solder a 10uF electrolytic capacitor

This seems rather small. I usually use 100 uF. Many users from MySensor forums suggest 100 uF + 0.1 uF (which is a common requirement for linear voltage regulators).

The code is modified per your suggestion, i still only get until the radio.available() and the RPi cannot enter this function, i assume the radio is "not" available?

That's not what the function name describes. available() means "is there data in the RX FIFO available?" If the function never returns true, then the radio simply hasn't received data.

arduino UNO doesn't show any output from printDetails()

This seems odd. Usually this problem means the CPU does not have printf() support, but the Uno uses an ATMega328 (which does have printf() support). See the suggestion from the docs about printDetails()

Nonetheless, I still suspect a power problem because the software all looks good.

I made a few changes, i formatted the sd-card and installed a clean latest Raspberian version, and didn't updated the OS from the Raspberry Pi as i found that the updates made few changes with kernel, and sometimes this caused the library to not function properly.. i don't really understand how the kernel works and i'm kinda new to linux, so rather not to touch that :)

I'm using now a different nRF24L01+ module, but there is not soldered capacitor, but i'm using an adapter where the VCC is connected now to 5V supply on my arduino, also changed the arduino from UNO to NANO.

The RF24 core library was installed using the SPI option for compatibility - there are 5: BCM2835, SPI, WiringPi and 2 more...

Now, there is a different issue, both RPi and Nano are 2 meters apart, and i'm using the gettingstarted example while setting the radio.setPALevel(RF24_PA_HIGH), the RF24_PA_LOW didn't worked so well.

Also i moved the testing area away from the router in case of some potential EMI/Noise.

I have a connection now between the modules, successfully transferring data from NANO to RPi, but the roundtrip is ridiculous, shouldn't it be under 100ms? the delay between the pings is 1sec, and the success rate is around 70-80%, which i guess poor performance, especially when i'll have to transfer MPU6050 gyroscope data from NANO to RPi every 50-100[ms]

Is there anything i can do to improve the performance?

I also changed the setChannel to 125 on both sides, looks a little bit better as there are way less Failed attemps, the success rate went up to 85-90%, but still the roundtrip time is too high, between 2000 to 40000.

Regarding the Arduino, i still don't get the printDetails() output on the GettingStarted but i do get from Pingpair_dyn example. Honestly, i don't care much as long as I see the data on my RPi.

Any recommendations?

ā€” You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or unsubscribe.

igal92 commented 3 years ago

Hi TMRh20,

Thanks for the recommendation.

I will try lower channel and different modules with a different Antenna.

What did you mean by scraping the end of the antenna and soldering? did you mean as seen in the link below? https://www.instructables.com/Enhanced-NRF24L01/

TMRh20 commented 3 years ago

Similar, I just do the end of the lead (red arrow) nRF24L01-Pinout

2bndy5 commented 3 years ago

you don't need to quote my entire comment everytime you respond (no offense).

i found that the updates made few changes with kernel, and sometimes this caused the library to not function properly..

This is interesting. I don't doubt it, but I'm curious to know how/where you got that info (for support purposes).

i'm using an adapter where the VCC is connected now to 5V supply on my arduino, also changed the arduino from UNO to NANO.

I also just got some of those breakout boards, and I'm also testing new library changes on the Nano šŸ˜„ . So far I'm loving these breakout boards, but I found that adding a 1uF capacitor between the Nano's 5V and GND added some stability. Those breakout boards do have capacitors soldiered in, but they're probably cheaply sourced (given that I got like 10 boards for $5 on amazon).

i moved the testing area away from the router in case of some potential EMI/Noise

Keep playing with the setChannel() because avoiding "potential EMI/Noise" is what the function is for.

shouldn't it be under 100ms

your screenshot shows microseconds (abbreviated as "us"). "ms" stands for milliseconds. I agree that the reported "round-trip delay" seems a bit high. Remember that the GettingStarted examples (or practically all examples in this library) actually do more than the application you described. Meaning that each round-trip delay measured in the examples is actually from 4 transmissions (including ACK packets). So you should see much better transmission time in your application assuming your intention is still just sending data one-way (remember the ACK packet is an automatic response transmission to every write() call). Without using ACK packets the radio has no way to know if the transmission was received (that's why its a good idea to leave it on).

MPU6050 gyroscope data from NANO to RPi every 50-100[ms]

Again I'm assuming you meant "us" instead of "ms" here. Unfortunately, I have never seen transmissions between RPi and Nano that result in anything faster than ~530 us (using library defaults in my experience). So you may need to filter down the data being sent. This is a classic problem because the MPU6050 & nRF24L01 are extremely cheap, and you're not the first to try and attempt this combination.

image

This "ARC" stands for Auto-Retry Count. 15 is the most attempts the radio will try before reporting transmission failure. You can retrieve this value (updated on every call to write()) using the getARC() function.

Regarding the Arduino, i still don't get the printDetails() output on the GettingStarted but i do get from Pingpair_dyn example.

you didn't read the docs on printDetails() this is the link

Any recommendations?

Yeah, but you're fighting hardware & environment at this point. The following might help a little:

igal92 commented 3 years ago

Hi 2bndy5.

Thank you for the detailed reply!

about the kernel changes, in 1 of my tries last month, i had the exact same problem as seen in the following link, hope you will find something to do with it: https://raspberrypi.stackexchange.com/questions/71380/rf24-system-fails-after-rpi-system-update-any-ideas

Thanks for the update regarding the us/ms units. i meant us [micro seconds] as it doesn't make any sense to be ms. 1000ms+ is more than 1sec while i received data every 1sec and the roundtrip was 2000-30000us.

2bndy5 and TMRh20, i'll try the recommendations tomorrow together with the MPU.

Thank you very much!

2bndy5 commented 3 years ago

Thanks for the link, but its 3 years old and talks about Raspbian Jessie which reached its end-of-life as of June 2020. I haven't had any problems with the recent updates (working from RPi2B+ and RPi4 with "Raspberry Pi OS" which is formerly known as "Raspbian"). I'm afraid I can't do anything to address that experience unless I can reproduce the problem on my hardware, and I won't be going out of my way to do so.

igal92 commented 3 years ago

I finally got this working. for any user that will see this post in the future, hope this helps: The cheap nRF24L01 modules you purchase online are not the original therefore they miss some internal important design modules. I found this video: https://www.youtube.com/watch?v=jfaFbjgwprI where he explains what to do if you receive a lot of times "Failed" and the success rate is not 90%+. You can try solder a wire on the antenna in order to improve the range, but what fixed the "FAILED" problem and made the success rate go up to 100% is adding the following line on both RPi and Arduino after radio.begin()

radio.setAutoAck(false);
radio.setChannel(5); //played with the channels to avoid Router interference, can be different per testing area.
 radio.setPALevel(RF24_PA_LOW); //on RPi side (Rx), this is to save some power, its receiving signal only.
radio.setPALevel(RF24_PA_MAX); //on the Arduino side (Tx).

I also used nRF24L01 with 10uF electrolytic capacitor soldered between the VCC to GND, the nRF24L01 module is also sitting inside an adapter, so it has power regulator and the capacitor soldered.

Struct of 6 integers - 2 axis from MPU6050 gyroscope and 4 flex sensors data is being transferred with a success rate of 100% every 50ms. image

Good luck!

2bndy5 commented 3 years ago

radio.setAutoAck(false)

This is not recommended! I'm glad you got it working, but you will notice that your success rate will still be 100% if the receiving end is off or not in range. You will definitely have data loss in your "one-way" application now.

It doesn't sound like you got a fake chip because you got it working with a small capacitor. Most people with an actual fake chip can't even say that much. I already asked you to try a bigger capacitor like 100 microFarads (uF).

radio.setPALevel(RF24_PA_LOW);Ā //onĀ RPiĀ sideĀ (Rx),Ā thisĀ isĀ toĀ saveĀ someĀ power,Ā itsĀ receivingĀ signalĀ only. radio.setPALevel(RF24_PA_MAX);Ā //on theĀ ArduinoĀ sideĀ (Tx).

Yes this can save power, but your RPi is not transmitting ACK packets the same distance that your Arduino is sending TX packets. This could also lead to less than 100% success rate.

Please don't believe everything you read/see on youtube (or the internet in general).

Notice that guy on youtube never once looked at the datasheet. He actually has no idea what the NO_ACK bit does. I doubt he even knows what setAutoAck() does. (They are 2 different but similar things)

p.s. "us" is commonly used for microseconds because the actual letter used to abbreviate "micro" is the greek letter "Āµ". Everyone just uses "us" because there isn't a Āµ key on the keyboard. Using "ms" may make sense to you, but everyone who knows the difference will think you mean milliseconds.

igal92 commented 3 years ago

Hi 2bndy5,

I checked again - you're right. the setAutoAck(true) returns ACK packets, and in case it didn't - i get a return "Failed" from the function:

if (!radio.write(&data, sizeof(data))){
        Serial.println(F("failed"));}

This is a very good indication, therefore i changed it back to "true" although i believe it's set to default as "true". If the RX returns ACK packets, it needs to reach back the TX somehow, so i changed the PA_LEVEL to "HIGH" in the RPi (RX) end, seems to be ok for my application.

both modules already soldered with 10uF capacitor, and they are both inside an adapter which gives extra bonus for the power problem, looks like it's working so i guess its ok.

Thank you very much for all the detailed replies and for the help!