nRF24L01+PA+LNA not working with Uno and Mega

Hello,

I'm trying to establish wireless communication between an Arduino Uno and Mega, both of which are connected to an nRF24L01+PA+LNA module. I've tried to send a "Hello World" message from my Uno to my Mega, but for some reason my Mega couldn't receive it.

Here are the connections I've made:

Arduino Uno - nRF24L01+PA+LNA
9 - CE
10 - CSN
11 - MOSI
12 - MISO
13 - SCK

Arduino Mega - nRF24L01+PA+LNA
49 - CE
50 - MISO
51 - MOSI
52 - SCK
53 - CSN

The transceiver modules are plugged into nRF24L01 adapters (which have an onboard regulator and capacitors from what I've read). These are powered using the 5V pins from the Arduinos, and I'm not using any capacitors besides the ones on the adapters.

In case anyone needs it, here's a picture of my setup:

Here is the code for the transmitter (Uno):

#include <SPI.h>
#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>

RF24 radio(9, 10);
const byte address[6] = "00001";

void setup() {
  // put your setup code here, to run once:
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
}

void loop() {
  // put your main code here, to run repeatedly:
  const char text[] = "Hello World";
  radio.write(&text, sizeof(text));
  delay(1000);
}

And here is my receiver code (Mega):

#include <SPI.h>
#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>

RF24 radio(49, 53);
const byte address[6] = "00001";

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(53, OUTPUT);
  digitalWrite(53, LOW);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
}

void loop() {
  // put your main code here, to run repeatedly:
  if (radio.available()) {
    char text[32] = "";
    radio.read(&text, sizeof(text));
    Serial.println(text);
  }
  else {
    Serial.println("Waiting...");
  }
}

If anyone has any ideas on how to fix this issue, feel free to let me know. Any help will be greatly appreciated. Thanks! :slight_smile:

Thanks for code and pictures. But.... Could You please post the schematics? All helpers don't have the function of the pin numbers in their heads.
When the question involves wireless it's always interesting to see the wiring, especially the powering of things.
Code for the receiver will likely be interesting later...

You don't need that if you are using 53 as CSN for the NRF.

Your 9V battery will not be able to deliver the needed current.

It is very unsensible to print things on every round of loop, especially with that ancient baud rate.

1 Like

Actually the else statement was there to test whether the serial monitor was working properly or not. There were times when it wouldn't display anything even though it should. But I agree, it's a good idea to remove that line.

Also, what power source would you recommend if a 9V battery isn't good enough? I'm trying to make the Uno portable so plugging it into my computer isn't really an option.

Good observation that I missed. Remove those PP3 batteries from the market....... At least from the Arduino "market"..

Two 18650 or any other two cell configuration of LiPos should work well
(via VIN or step down to 5V attached to 5V).
One cell and a step up to 5V would also work (attached to 5V).

1 Like

An USB charger is one option. USB batteries can work but some of them switch off if the current consumption is too low.
I've managed to trick some of them, getting help from this forum.

1 Like

A better idea is, to replace it by something sensible,
like checking whether some time (10 seconds?) elapsed since the last valid reception. :wink:

You could also add printf_begin() and a radio.printDetails() to the setups,
so you would see any connection (hardware) problems with the same test sketches.

1 Like

You only need

#include <printf.h>
#include <RF24.h>

So I've made some changes to the receiver code, but I currently don't have any LiPo batteries lying around. I'll try and order some online, which means it might take a few days for them to arrive. In the meantime, let me know if there are any more issues.

Really appreciate the advice you guys are giving. Guess I won't be using 9V batteries any more (but at least I have a paperweight now).

Why would you need a battery for the test?

Sure, if everything is working, the battery mode has to be tested too,
but you can verify the NRF communication with USB power.

You did not post the changed code.

I only have one USB cable, so I can't connect both Arduino boards to my computer.

Here is my updated transmitter code:

#include <printf.h>
#include <RF24.h>

RF24 radio(9, 10);
const byte address[6] = "00001";

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  printf_begin();
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
  radio.printDetails();
}

void loop() {
  // put your main code here, to run repeatedly:
  const char text[] = "Hello World";
  radio.write(&text, sizeof(text));
  delay(1000);
}

Meanwhile, here is my updated receiver code:

#include <printf.h>
#include <RF24.h>

RF24 radio(49, 53);
const byte address[6] = "00001";

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  printf_begin();
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
  radio.printDetails();
}

void loop() {
  // put your main code here, to run repeatedly:
  if (radio.available()) {
    char text[32] = "";
    radio.read(&text, sizeof(text));
    Serial.println(text);
  }
}

This is what "radio.printDetails()" gave me:

Transmitter:

SPI Speedz	    = 10 Mhz
STATUS		    = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1	= 0x3130303030 0xc2c2c2c2c2
RX_ADDR_P2-5	= 0xc3 0xc4 0xc5 0xc6
TX_ADDR		    = 0x3130303030
RX_PW_P0-6	    = 0x20 0x20 0x20 0x20 0x20 0x20
EN_AA		    = 0x3f
EN_RXADDR   	= 0x03
RF_CH		    = 0x4c
RF_SETUP	    = 0x01
CONFIG		    = 0x0e
DYNPD/FEATURE	= 0x00 0x00
Data Rate	    = 1 MBPS
Model		    = nRF24L01+
CRC Length	    = 16 bits
PA Power	    = PA_MIN
ARC		        = 15

Receiver:

SPI Speedz	    = 10 Mhz
STATUS		    = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1	= 0x3130303030 0xc2c2c2c2c2
RX_ADDR_P2-5	= 0xc3 0xc4 0xc5 0xc6
TX_ADDR		    = 0xe7e7e7e7e7
RX_PW_P0-6	    = 0x20 0x20 0x20 0x20 0x20 0x20
EN_AA		    = 0x3f
EN_RXADDR	    = 0x03
RF_CH		    = 0x4c
RF_SETUP	    = 0x01
CONFIG		    = 0x0f
DYNPD/FEATURE	= 0x00 0x00
Data Rate	    = 1 MBPS
Model		    = nRF24L01+
CRC Length	    = 16 bits
PA Power	    = PA_MIN
ARC		        = 0

Setup is identical to the one in the picture above.

So the wiring and communication between MCU and NRF seem to be ok. :grinning:

I would lose the

  // put your setup code here, to run once:
  // put your main code here, to run repeatedly:

Noob lines.

The baud rate is ancient, I use 115200 (only because it is the highest rate that the
version of the new IDE I use supports for the serial monitor).

If you want to use more than two pipes, two addresses have to share the uppermost 4 bytes.
So, while your pipe "00001" is absolutely correct,
it will lead you in a wrong direction if you add more pipes.
The logical (IMHO) second pipe would be "00002", if you use pipe 0 and 1 it will work as expected.
A valid third pipe on the other hand, could not be "00003", but has to be something like
"10001" or "10002", depending on which address you select for pipe 1.

Using more than one pipe can be useful, each pipe can be configured differently.

This is 12 byte 'meaningful' data and 20 bytes zeros,
which is slower than sending only the useful part and has a bigger collision chance.
radio.enableDynamicPayloads() allows you to automatically adjust the packets.
radio.getPayloadSize() allows the receiver to access the length of a received packet.

Why are you not interested in the outcome of the send?
It checks the acknowledgement that is sent back from the receiver,
useful information in a test setup,
and allows for packet repeats for more than the automatic number of retries,
error messages or something else in a production sketch.

Even for a test program, don't use delay. Buttons can be very useful for testing.

1 Like

I have heard that the higher powered (with external antennas) rf24 radios can have trouble communicating if they are too close together. Move them a couple of meters apart.

1 Like

If I decided to use 6 pipes for example, what would their addresses look like? Two of them need to share the first 4 bytes, but what about the other four pipes?

So instead of using one address for sending and receiving data ("00001"), I should use two ("00001" for sending and "00002" for receiving, for instance)?

What if the modules need to send/receive data at certain time intervals (every 1 second in my case) as opposed to (almost) instantaneously?

This worked for a little bit. I've placed the antennas roughly 50cm apart and increased the baud rate to 115200 as @Whandall suggested. Here's what my receiver serial monitor showed:

SPI Speedz	    = 10 Mhz
STATUS		    = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1	= 0x3130303030 0xc2c2c2c2c2
RX_ADDR_P2-5	= 0xc3 0xc4 0xc5 0xc6
TX_ADDR		    = 0xe7e7e7e7e7
RX_PW_P0-6	    = 0x20 0x20 0x20 0x20 0x20 0x20
EN_AA		    = 0x3f
EN_RXADDR	    = 0x03
RF_CH		    = 0x4c
RF_SETUP	    = 0x01
CONFIG		    = 0x0f
DYNPD/FEATURE	= 0x00 0x00
Data Rate	    = 1 MBPS
Model		    = nRF24L01+
CRC Length	    = 16 bits
PA Power	    = PA_MIN
ARC		        = 0
Hello World
Hello World

I'll try moving them further apart to see if they work, although they didn't the last time I did it.

Pipe addresses are LSB, so if you use a char representation, only the first chars vary.

I like to stick those addresses in one array and select them by offsetting in the char array.

Only pipe 0 and pipe 1 have 5 bytes, pipe 2 to 6 are merely one byte extensions of pipe 1,
they get their "the first 4 bytes of the address matched"-signal from pipe 1.

Only five of the six pipe addresses (1 to 6) have to share the high part, so a good strategy is
to use compatible addresses and pipe 1 (and some of 2 to 6) for up to 5 pipes,
so you have pipe 0 free if you want to communicate to someone outside your address group.
Pipe 0 takes a group address too, but does not have to get one.

Pipe 0 is also used by the auto-ack process so the driver has to rewrite its address on each
startListening, because the hardware could have changed it.

So it is best left alone, until you really want to use 6 pipes at the same time.

const char adrs[] = "a_adr" "b_adr" "c_adr" "d_adr" "e_adr" "f_adr";

  radio.openReadingPipe(1, adrs+3*5); // d_adr

Or you could create a function to create pipe addresses with a fixed prefix and use that.

  radio.openReadingPipe(1, genAddr('d')); // d_adr

const char *genAddr(char sel) {
static char nadr[] = "?_adr";
  nadr[0] = sel;
  return (const char*)nadr;
}

Use a millis based timing.

1 Like

I've tested the code a few more times and it seems to be working slightly. I've seen a few more "Hello World" messages appear on my receiver serial monitor, although they were few and far between. From what I can tell, the modules can only communicate (for a very brief moment) immediately after I disconnect the battery from the transmitter.

I haven't made any major changes to the code; instead, I only changed the baud rate and removed a few unnecessary lines before testing.

Transmitter code:

#include <printf.h>
#include <RF24.h>

RF24 radio(9, 10);
const byte address[6] = "00001";

void setup() {
  Serial.begin(115200);
  printf_begin();
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
  radio.printDetails();
}

void loop() {
  const char text[] = "Hello World";
  radio.write(&text, sizeof(text));
}

Receiver code:

#include <printf.h>
#include <RF24.h>

RF24 radio(49, 53);
const byte address[6] = "00001";

void setup() {
  Serial.begin(115200);
  printf_begin();
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
  radio.printDetails();
}

void loop() {
  if (radio.available()) {
    char text[32] = "";
    radio.read(&text, sizeof(text));
    Serial.println(text);
  }
}

Just not that "smoke alarm" battery. If you must use a 9 V battery (but a bad idea to power UNO or Mega 2560 from "Vin" or the "barrel jack"), use a 6 cell "AA" carrier.

Seriously?