NRF24L01 sending but not receiving on MEGA2560 but works perfectly fine on UNO

In my current setup I have a raspberry pi setup with an NRF24L01 transmitter to send and receive data to my arduinos. I got the communication to work with my Arduino UNO but realized that the pins wouldn't be enough for all my Sensors so I moved everything over to the MEGA 2560.
I made sure that the MISO, MOSI and SCK pins were connected correctly and am able to send packets over to my pi but I can't receive the packets sent from my pi.
I am running the exact same program on both arduinos yet one arduino can send and receive while the other can only send.

I'm using this library and my connections are as follows:

UNO:
MISO -> 12
MOSI -> 11
SCK -> 13
CE -> 7
CSN -> 8
GND -> GND
VCC -> 3.3v

MEGA 2560:
MISO -> 50
MOSI -> 51
SCK -> 52
CE -> 7
CSN -> 8
GND -> GND
VCC -> 3.3v

And this is the code I'm running. It waits for the pi to send the GETSTRING command and answers (If I want to send a message no matter what, I uncomment the three lines before the delay at the end):

#include<SPI.h>
#include<RF24.h>

RF24 radio(7,8);
int i = 0;
void setup() {
  Serial.begin(9600);
  
  radio.begin();
  radio.setPALevel(RF24_PA_MAX);
  radio.setChannel(0x76);
  radio.openWritingPipe(0xF0F0F0F0E1LL);
  const uint64_t pipe = 0xE8E8F0F0E1LL;
  radio.openReadingPipe(1,pipe);
  
  radio.enableDynamicPayloads();
  
  radio.powerUp();

}

void loop() {
  
 radio.startListening();
 Serial.println("Starting loop. Radio on.");
 char receivedMessage[32] = {0};
 if(radio.available()){
  radio.read(receivedMessage, sizeof(receivedMessage));
  Serial.println(receivedMessage);
  Serial.println("Turning off radio");
  radio.stopListening();

  String stringMessage(receivedMessage);
  Serial.println(receivedMessage);
  
  if(stringMessage == "GETSTRING"){
    String returnMsg = "SensorDaten: ";
    returnMsg.concat(i);
    // Serial.println(i);
    const char text[returnMsg.length()+ 1];// = returnMsg;
    returnMsg.toCharArray(text,returnMsg.length() + 1);
    radio.write(&text,sizeof(text));
    Serial.println("Sent String");
  }
 }
  // radio.stopListening();
   //const char text[] = "Hello Pi!";
    //radio.write(&text,sizeof(text));
    delay(100);
i++;

}

Do you have a capacitor (2-10µF) directly connected to the NRF's power pins?

Whandall:
Do you have a capacitor (2-10µF) directly connected to the NRF's power pins?

I tried connecting a 10 uF electrolytic capacitor to both transmitters but that didn't help :confused:

Satrex:
I am running the exact same program on both arduinos yet one arduino can send and receive while the other can only send.

Are you using two different nRF24s on the Mega and on the Uno? Maybe one of them is faulty?

...R

void loop() {
 
 radio.startListening();
 
 if(radio.available()){
  radio.read(receivedMessage, sizeof(receivedMessage));

  radio.stopListening();

  if(stringMessage == "GETSTRING"){

    radio.write(&text,sizeof(text));
  }
 }
}

What makes you think the Mega receives packets like you claimed in the thread title?

Your sketch sends after a reception only,
so I think you have a wiring error on the Mega and the thread-title is just misleading.

Calling startListening each iteration of loop is not very clever,
you should call startListening in setup and after each call of stopListening,
when you are done with the transmission(s).

Whandall:
What makes you think the Mega receives packets like you claimed in the thread title?

Sorry english is not my first language, that is not what I was claiming. It doesn't receive but it does transmit. In my first post I explained that the three commented lines at the end of my program can be uncommented to force it to transmit which I then receive on my pi. Thanks for the tip on when to call startListening(); but I managed to completely break one of the transmitters so I'm hoping it was already faulty and that I'll have more success with the next one. Thank you all for your help!

If the Pi sends a packet (with needed acknowledgement) the Mega has to receive it and answer.

Well the new transmitter just arrived and the same weird thing is happening :confused:

So far I know:

  • My raspberry's transmitter can receive messages sent by the transmitter connected to my MEGA 2560 because if I uncomment the bottom 4 lines in the following code, the message shows up on my raspberry Pi.
  • So I also know the MEGA 2560's transmitter can send so I didn't screw up the wiring.
  • My raspberry pi's transmitter can send a message but for some reason only my Arduino UNO can receive it not the MEGA 2560 (Both running the same program with only the constructor of RF24 changed).
  • Connecting a 10 uF electrolytic capacitor to the raspberry's transmitter doesn't help either.

I'm completely lost. This problem is so weird since the receiving part of the transmission should be the easy part right?

Here are the 2 programs running on my Arduino and my Pi in case I missed something obvious:

Arduino:

#include<SPI.h>
#include<RF24.h>

RF24 radio(48,53);
int i = 0;

void setup() {
  Serial.begin(9600);
  
  radio.begin();
  radio.setPALevel(RF24_PA_MAX);
  radio.setChannel(0x76);
  radio.openWritingPipe(0xF0F0F0F0E1LL);
  const uint64_t pipe = 0xE8E8F0F0E1LL;
  radio.openReadingPipe(1,pipe);
  
  radio.enableDynamicPayloads();
  
  radio.powerUp();
  radio.startListening();
}

void loop() {
 Serial.println("Starting loop. Radio on.");
 char receivedMessage[32] = {0};
 if(radio.available()){
  radio.read(receivedMessage, sizeof(receivedMessage));
  Serial.println(receivedMessage);
  Serial.println("Turning off radio");
  radio.stopListening();

  String stringMessage(receivedMessage);
  Serial.println(receivedMessage);
  
  if(stringMessage == "GETSTRING"){
    String returnMsg = "SensorDaten: ";
    returnMsg.concat(i);
    // Serial.println(i);
    const char text[returnMsg.length()+ 1];// = returnMsg;
    returnMsg.toCharArray(text,returnMsg.length() + 1);
    radio.write(&text,sizeof(text));
    Serial.println("Sent String");
  }
  radio.startListening();
 }
   //radio.stopListening();
   //const char text[] = "Hello Pi";
   //radio.write(&text,sizeof(text));
   //radio.startListening();
    delay(100);
i++;

}

Pi (Python):

import spidev
import RPi.GPIO as GPIO
from lib_nrf24 import NRF24
import time

GPIO.setmode(GPIO.BCM)


pipes = [[0xE8, 0xE8, 0xF0, 0xF0, 0xE1],[0xF0, 0xF0, 0xF0, 0xF0, 0xE1]]
#RF24 radio(RPI_V2_GPIO_P1_22, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
radio = NRF24(GPIO, spidev.SpiDev())
radio.begin(0,17)    #22/8

radio.setPayloadSize(32)
radio.setChannel(0x76)
radio.setDataRate(NRF24.BR_1MBPS)
radio.setPALevel(NRF24.PA_MAX)

radio.setAutoAck(True)
radio.enableDynamicPayloads()
radio.enableAckPayload()

radio.openWritingPipe(pipes[0])
radio.openReadingPipe(1,pipes[1])
radio.printDetails()
#radio.startListening()

message =  list("GETSTRING")
while len(message) < 32:
        message.append(0)


while True:

        start = time.time()
        radio.write(message)
        print("Sent the message: {}".format(message))
        radio.startListening()

        while not radio.available(0):
                time.sleep(1/100)
        #       print("Geht Nich")
                if time.time() - start > 2:
                        print("Timed out.")
                        break


        receivedMessage = []
        radio.read(receivedMessage, radio.getDynamicPayloadSize())
        print("Received: {}".format(receivedMessage))

        print("Translating into unicode...")
        string = ""

        for n in receivedMessage:
                if (n >=32 and n<= 255):
                        string += chr(n)
        print("Received Message decodes to: {}".format(string))

        radio.stopListening()
        time.sleep(1)

Let me review, Forgive me if I am stating the obvious. I just want to make sure nothing gets missed.

You have a program on an RPi and on an Uno and sending and receiving works perfectly?

By that I mean that the RPi can send a message to the Uno and the Uno can display that message AND the Uno can send a different message to the RPi and the RPi can display that message. And in each direction each message is a little different - for example the final character changes so it is qwer followed by qwes etc in one direction and zxcv followed by zxcw etc in the other direction.

Is all that correct? (Obviously you can use whatever messages you like, put please tell me what you are using).

If that is not all correct then we need to fix that first. My suspicion is that there is a problem with the Uno also.

If it is all correct then, as I understand it, the almost identical code does not work properly on the Mega. And the only difference in the programs is the line RF24 radio(48,53);

...R

Yup that's about it. The idea is that as soon as the arduino receives the "GETSTRING" command it returns "Hello Pi" + (increasing integer)" this entire program runs perfectly on my uno.

But the MEGA receives nothing. Everything it receives will be written into the serial Monitor but I just get "Starting loop. Radio on." forever. So I added 4 lines for testing that would make it send out "Hello Pi" on every loop (last 4 comments of the loop) and those I was able to receive/display on my Pi.

Satrex:
Yup that's about it.

Sorry, but long experience here has made me doubtful about that sort of response.

Post the working Uno program and its RPi counterpart that demonstrates the behaviour I described in Reply #8

...R

Robin2:
Sorry, but long experience here has made me doubtful about that sort of response.

I am using the same program on both arduinos with the same counterpart on the pi so I thought I basically ruled out a bad configuration.

But yeah, I get it here you go, freshly commented and everything :slight_smile: (if you dont want to read everything i summarized the important stuff at the end):

Arduino:

#include<SPI.h>
#include<RF24.h>

RF24 radio(7,8);                                  //RF24 radio(48,53) for MEGA   RF24 radio(ce_pin,cs_pin)
int i = 0;                                                 //Counter to add to my message

void setup() {
  Serial.begin(9600);
  
  radio.begin();
  radio.setPALevel(RF24_PA_MAX);
  radio.setChannel(0x76);                             //Setup stuffs if i did something wrong its probably here as I dont fully understand all of it.
  radio.openWritingPipe(0xF0F0F0F0E1LL);
  const uint64_t pipe = 0xE8E8F0F0E1LL;
  radio.openReadingPipe(1,pipe);
  
  radio.enableDynamicPayloads();
  
  radio.powerUp();
  radio.startListening();
}

void loop() {
 Serial.println("Starting loop. Radio on.");    
 char receivedMessage[32] = {0};
 if(radio.available()){                                          //A message was received
  radio.read(receivedMessage, sizeof(receivedMessage)); //Writes the received message to my char array
  Serial.println(receivedMessage);                         //writes it to the monitor
  Serial.println("Turning off radio");                       //getting ready for the response
  radio.stopListening();

  String stringMessage(receivedMessage);
  Serial.println(receivedMessage);                        //turns it to a string to compare with known commands in the  next step
  
  if(stringMessage == "GETSTRING"){                  //if its a certain keyword...
    String returnMsg = "SensorDaten: ";
    returnMsg.concat(i);  
    // Serial.println(i);
    const char text[returnMsg.length()+ 1]           ;// = returnMsg;
    returnMsg.toCharArray(text,returnMsg.length() + 1);
    radio.write(&text,sizeof(text));                        //respond with an everchanging integer i and constant string "Sensordaten"
    Serial.println("Sent String");                           //for the monitor
  }
  radio.startListening();
 }
   //radio.stopListening();                    //THESE 4 LINES WILL MAKE THE ARDUINO WRITE TO THE PI NO MATTER WHAT
   //const char text[] = "Hello Pi";        //THIS IS HOW I KNOW THAT THE ARDUINO IS CAPABLE OF WRITING AS I CAN RECEIVE THE MESSAGE ON MY PI
   //radio.write(&text,sizeof(text));
   //radio.startListening();
    delay(100);
i++;

}

Pi (Python):

import spidev
import RPi.GPIO as GPIO
from lib_nrf24 import NRF24
import time

GPIO.setmode(GPIO.BCM)
                                                        #weird setup Stuffs
pipes = [[0xE8, 0xE8, 0xF0, 0xF0, 0xE1],[0xF0, 0xF0, 0xF0, 0xF0, 0xE1]]
#RF24 radio(RPI_V2_GPIO_P1_22, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
radio = NRF24(GPIO, spidev.SpiDev())
radio.begin(0,17)    #22/8

radio.setPayloadSize(32)
radio.setChannel(0x76)
radio.setDataRate(NRF24.BR_1MBPS)
radio.setPALevel(NRF24.PA_MAX)

radio.setAutoAck(True)
radio.enableDynamicPayloads()
radio.enableAckPayload()

radio.openWritingPipe(pipes[0])
radio.openReadingPipe(1,pipes[1])
radio.printDetails()
#radio.startListening()                   #finished setup stuffs

message =  list("GETSTRING")       #the command to write to the arduino
while len(message) < 32:
        message.append(0)               #adding zeros to the rest of the 32 bytes for weird behaviour?


while True:

        start = time.time()                #timeout to wait for a response
        radio.write(message)
        print("Sent the message: {}".format(message))    #wrote the command
        radio.startListening()

        while not radio.available(0):    #waiting for a response or basically any message
                time.sleep(1/100)
        #       print("Geht Nich")
                if time.time() - start > 2: #wait for a maximum of 2 seconds and then time out
                        print("Timed out.")
                        break


        receivedMessage = []
        radio.read(receivedMessage, radio.getDynamicPayloadSize())  //received message is written to a variable
        print("Received: {}".format(receivedMessage)) #outputs the received message

        print("Translating into unicode...")
        string = ""

        for n in receivedMessage:
                if (n >=32 and n<= 255):             #turns the whole thing into ascii characters
                        string += chr(n)
        print("Received Message decodes to: {}".format(string))

        radio.stopListening() 
        time.sleep(1)                                         #wait a second

So the Pi sends the command "GETSTRING" to my arduino every second. This command is instantly printed to the serial Monitor (only on the uno). The Arduino then responds with ("Sensordaten: " + integer) and this is printed to the pi console. Since the MEGA doesn't enter this part of the program at all I added 4 comments at the bottom part of the arduino program which will constantly send the message "Hello Pi" and since the pi is dumb it thinks that's the response to the GETSTRING command and prints this to the console.

Satrex:
Since the MEGA doesn't enter this part of the program at all

I have taken copies of your code and I will think about it some more.

However the piece I have quoted caught my eye. Why would the Mega not enter a part of the code - I thought you said the program for the Mega is exactly the same as for the Uno, apart from the pin mapping?

And can you post a link to the documentation for the Python nRF24 library.

...R

I have now spent a long time on this. I don't have an RPi so I modified one of my example programs to take its place. It took a while to align it with all the settings in your program but i got it working.

There seems to be an error in your program on this line (around line 54, I think)

const char text[returnMsg.length()+ 1]           ;// = returnMsg;

It would not compile until I removed the "const"

I first tried your program on an Uno using pins 9 and 10 for CE and CSN.

I then tried it UNCHANGED on my Mega using pins 9 and 53 and it worked just the same as on the Uno.

...R

Thanks a lot for taking the time!

Robin2:
Why would the Mega not enter a part of the code[...]?

The MEGA doesn't enter the part of the program responsible for the response since it doesn't receive the "trigger", the "GETSTRING" command from the Pi.

This is the nRF24 library: GitHub - BLavery/lib_nrf24: Python library for NRF24L01+ Transceivers
and I just basically copied the setup from this video: https://www.youtube.com/watch?v=_68f-yp63ds
(please don't judge)

Robin2:
There seems to be an error in your program on this line (around line 54, I think)

While mine compiles perfectly fine, I have no idea why I made the returnMsg a constant. Thank you for that, but changing this sadly did not help.

I'm going to try to get the communication going between my UNO and MEGA in case the Pi is the culprit but I'm starting to think that the most likely explanation is that there's something wrong with the mega.

Why don't you look at the retun code of radio.write() on the Pi?

If the target can not receive (or send) the write will return an error code (after the configured retries).

Alright so I took the Pi out of the equation and got the same results. I could write from the MEGA to the UNO but not the other way around.

Is there a possibility that I somehow connected the transmitter to the MEGA in a way that it cant read data but write it?
Electrical engineering isn't my fortè so this is very much possible.

If you ever send a packet with acknowledgement between two nodes,
both of them are able to send and receive.

If the communication is not stable, wiring and power are the most common reasons.
Wiring via breadboards, weak power supply, no capacitor can all be such reasons.

Whandall:
If you ever send a packet with acknowledgement between two nodes,
both of them are able to send and receive.

Well I can only send in one direction without the acknowledgement ever reaching the sender since one has problems receiving. This also means that sending a message the other way is fruitless as the receiver has problems receiving and thus can't send an acknowledgement since it never receives anything.

Whandall:
If the communication is not stable, wiring and power are the most common reasons.
Wiring via breadboards, weak power supply, no capacitor can all be such reasons.

I am not using a breadboard but just switched out all the wires I am using and it didn't help. Now looking into another PSU.

Satrex:
Well I can only send in one direction without the acknowledgement ever reaching the sender

Which basically means you can not send.