SOLVED - NRF24L01 module not communicating with RF-Nano radio

Hey everyone. First time post, so thanks in advance for any and all help you may provide.

+++++++++++++++++++++++++++++++++++++++++++++++
Solution: The RF-Nano can use the nRF24L01 library by ensuring CE is on Pin 10, and CSN is on Pin 9. Most examples for nRF24L01 library have these reversed. It is fine if you are using a separate radio module but on RF-Nano it’s integrated – no choice in the matter.

Thanks to markd833 for pointing this out.
+++++++++++++++++++++++++++++++++++++++++++++++

Background: I’m working on a halloween prop which involves communication between arduinos to not have wires across the walkway (trip hazard). It involves turning pumpkins based on sensor input (based on the Creepy Pumpkin Patch sketch from the Cranky Coder). I was able to get that all working with a Mega and Uno using NRF24L01 modules. Then I started thinking I could potentially get rid of all wires if each pumpkin had it’s own board and radio. I found the RF-Nano by eMakeFun (emakefun-nano-plus/RF-Nano at master · emakefun/emakefun-nano-plus · GitHub) which is an arduino Nano with and INTEGRATED NRF24L01 chip. (So please don’t ask how I’m powering the RF24 with it’s 3.3V, it’s integrated onto the nano board.) They’re cheap and small, so I thought they may be just the thing. I just can’t get them to communicate across radio types (i.e. separate radio module vs integrated into board).

Problem: I have two sets of sketches using NRF24L01 radios. One set is used on a Mega/Uno combination and uses the RF24 library and nRF24L01.h. The other set is used on a pair RF-Nanos and uses nRF24L01.h with Mirf.h and MirfHardwareSpiDriver.h. I have been unsuccessful in getting a Mega/RF-Nano or Uno/RF-Nano combination to communicate.

What I am seeking is assistance in digging deeper into the Mirf and RF24 libraries to see if there is a non-conformance anywhere that would prevent these two radios communicating. I’ve looked at each, but there is nothing that stands out to me.

If anyone out there has had success in getting an NRF24L01 module to communicate with an RF-Nano, I’ll take whatever lessons learned you may have.

Each pair of Transmitter/Receiver sketches (below) work between their respective boards, i.e. Uno/Mega running with NRF24L01 modules, RF-Nanos running their respective sketches. The sketches below are the sample sketches from Robin2 for the NRF24L01 module, and from eMakeFun GitHub. The only modifications are to make the addresses and transmitted datatype match across all sketches.

I’ve also tried using the optional configurator functions (that’s the term in the documentation - I’m not making it up) for the RF-Nano to match settings in the RF24 sketches, but no success there, either, so I removed that to have the simplest working sketches possible.

I am not including pictures of wiring because, as stated, each set of boards work among themselves, just not across types. So it’s not a wiring issue.

Here is the NRF24L01 Transmitter code:

// SimpleTx - the master or the transmitter

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

#define CE_PIN   9
#define CSN_PIN 10

const byte slaveAddress[5] = {'A','B','C','D','E'};

RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

byte dataToSend = 0;

unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 1000; // send once per second

//===================
void setup() {

    Serial.begin(9600);

    Serial.println("SimpleTx Starting");

    radio.begin();
    radio.setDataRate( RF24_250KBPS );
    radio.setPALevel(RF24_PA_MAX);
    radio.setChannel(90);
    radio.setRetries(3,5); // delay, count
    radio.openWritingPipe(slaveAddress);
}

//====================

void loop() {
    currentMillis = millis();
    if (currentMillis - prevMillis >= txIntervalMillis) {
        send();
        prevMillis = millis();
    }
}

//====================

void send() {

    bool rslt;
    rslt = radio.write( &dataToSend, sizeof(dataToSend) );
        // Always use sizeof() as it gives the size as the number of bytes.
        // For example if dataToSend was an int sizeof() would correctly return 2

    Serial.print("Data Sent ");
    Serial.print(dataToSend);
    if (rslt) {
        Serial.println("  Acknowledge received");
        updateMessage();
    }
    else {
        Serial.println("  Tx failed");
    }
}

//================

void updateMessage() {
        // so you can see that new data is being sent
    dataToSend = random(0,255);
}

Here is the NRF24L01 Receiver code:

// SimpleRx - the slave or the receiver

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

#define CE_PIN   9
#define CSN_PIN 10

const byte thisSlaveAddress[5] = {'A','B','C','D','E'};

RF24 radio(CE_PIN, CSN_PIN);

byte dataReceived; // this must match dataToSend in the TX
bool newData = false;

//===========

void setup() {

    Serial.begin(9600);

    Serial.println("SimpleRx Starting");
    radio.begin();
    radio.setDataRate( RF24_250KBPS );
    radio.setPALevel(RF24_PA_MAX);
    radio.setChannel(90);
    radio.openReadingPipe(1, thisSlaveAddress);
    radio.startListening();
}

//=============

void loop() {
    getData();
    showData();
}

//==============

void getData() {
    if ( radio.available() ) {
        radio.read( &dataReceived, sizeof(dataReceived) );
        newData = true;
    }
}

void showData() {
    if (newData == true) {
        Serial.print("Data received ");
        Serial.println(dataReceived);
        newData = false;
    }
}

Here is the rf-nano Transmitter code:

//Transmitter program

#include <SPI.h>
#include "Mirf.h"
#include "nRF24L01.h"
#include "MirfHardwareSpiDriver.h"
Nrf24l Mirf = Nrf24l(10, 9);
byte value;

void setup()
{
  Serial.begin(9600);
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();
  //Set your own address (sender address) using 5 characters
  Mirf.setRADDR((byte *)"ABCDE");
  Mirf.payload = sizeof(value);
  Mirf.channel = 90;              //Set the channel used
  Mirf.config();
}

void loop()
{
  Mirf.setTADDR((byte *)"FGHIJ");           //Set the receiver address
  value = random(255);                      //0-255 random number
  Mirf.send(&value);                //Send instructions, send random number value
  Serial.print("Wait for sending.....");
  while (Mirf.isSending())//Until you send successfully, exit the loop
  delay(1);        
  Serial.print("Send success:");
  Serial.println(value);
  delay(1000);
}

Here is the rf-nano Receiver code:

//Receiver program
#include <SPI.h>
#include "Mirf.h"
#include "nRF24L01.h"
#include "MirfHardwareSpiDriver.h"
Nrf24l Mirf = Nrf24l(10, 9);

byte value;

void setup()
{
  Serial.begin(9600);
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();
  Mirf.setRADDR((byte *)"FGHIJ"); //Set your own address (receiver address) using 5 characters
  Mirf.payload = sizeof(value);
  Mirf.channel = 90;             //Set the used channel
  Mirf.config();
  Serial.println("Listening...");  //Start listening to received data
}

void loop()
{
  if (Mirf.dataReady()) { //When the program is received, the received data is output from the serial port
    Mirf.getData(&value);
    Serial.print("Got MotorDrive data: ");
    Serial.println(value);
  }
}

Why not just use the code from my Tutorial for both projects?

My Simple nRF24L01+ Tutorial includes a connection test program to check that the Arduino can talk to the nRF24 it is connected to.

A common problem with nRF24 modules is insufficient 3.3v current from the Arduino 3.3v pin. This seems to be a particular problem with the nano. The high-power nRF24s (with the external antenna) will definitely need an external power supply. At least for testing try powering the nRF24 with a pair of AA alkaline cells (3v) with the battery GND connected to the Arduino GND.

...R

Robin2 - looks like you have a bot that provides that as a standard answer (wink). I started with your examples for the Mega/Uno pair. In fact that is the base code for my halloween project.

Let me try again:

Board A is working and can communicate with Board B.
Likewise, Board B is working and can communicate with Board A.

Board C is working and can communicate with Board D.
Board D is working and can communicate with Board C.

Board A cannot communicate with either Board C or D.
Board B cannot communicate with either Board C or D.

Picture time:

This board:

Can communicate with this board:

And this board:

Can communicate with this board:

But this combination does not work:

Likewise the Uno with an RF-Nano.

The RF-Nano is different hardware with an integrated radio chip. It requires different drivers than the standard NRF24L01 module with a Mega or Uno. Are you aware of anyone who has successfully used the RF24 library on an RF-Nano?

In the only other thread that discusses both an Uno and RF-Nano, it was suggested to use the sample code that came with the board. That's what I am doing.

Since each board can communicate with another, I know all the radios are working. I have made each board both the transmitter and the receiver, so I know they all work in both directions. It's got to be a software configuration issue, and I just don't see it.

Thanks.
Rob

Okay - so what's the trick to getting images uploaded? I've tried using the Insert Image button (see results above - no images) and manually inserting tags and neither worked. Does the site work with google drive hosted images? (Yes, they are marked that anyone with the link can view them.)

gervaisrm:
Okay - so what's the trick to getting images uploaded?

See this Simple Image Posting Guide

And I had missed the fact that you are not using a standard nano.

...R

I've not used MIRF but, as a quick guess, it looks like your first pair of boards are using the address "ABCDE" and your second pair of boards are using the address "FGHIJ".

@markd833 - yeah, I noticed that today when I looked at it again. I think I uploaded the wrong sketch there, I'll re-post code in another reply. This one I'm focusing on getting images uploaded.

@Robin2 - no worries, it seems those aren't well known boards as yet. Perhaps adding a new Nano Sub-Board to Products would be appropriate?

Okay, I've read through the images stuff and I've cropped and resized my images. I'm also using a different browser - so hopefully this will work.

Mega + NRF24L01:

Uno + NRF24L01:

All right - images attached!

Moving on to updated code. I’ve just loaded and verified these sketches work on the RF-Nano boards.

RF-Nano Transmitter code:

//Transmitter program

#include <SPI.h>
#include "Mirf.h"
#include "nRF24L01.h"
#include "MirfHardwareSpiDriver.h"
Nrf24l Mirf = Nrf24l(10, 9);
byte value;

void setup()
{
  Serial.begin(9600);
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();
  //Set your own address (sender address) using 5 characters
  Mirf.setRADDR((byte *)"DEADA");
  Mirf.payload = sizeof(value);
  Mirf.channel = 90;              //Set the channel used
  Mirf.config();
}

void loop()
{
  Mirf.setTADDR((byte *)"ABCDE");           //Set the receiver address
  value = random(255);                      //0-255 random number
  Mirf.send(&value);                //Send instructions, send random number value
  Serial.print("Wait for sending.....");
  while (Mirf.isSending())//Until you send successfully, exit the loop
  delay(1);        
  Serial.print("Send success:");
  Serial.println(value);
  delay(1000);
}

RF-Nano Receiver code:

//Receiver program
#include <SPI.h>
#include "Mirf.h"
#include "nRF24L01.h"
#include "MirfHardwareSpiDriver.h"
Nrf24l Mirf = Nrf24l(10, 9);

byte value;

void setup()
{
  Serial.begin(9600);
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();
  Mirf.setRADDR((byte *)"ABCDE"); //Set your own address (receiver address) using 5 characters
  Mirf.payload = sizeof(value);
  Mirf.channel = 90;             //Set the used channel
  Mirf.config();
  Serial.println("Listening...");  //Start listening to received data
}

void loop()
{
  if (Mirf.dataReady()) { //When the program is received, the received data is output from the serial port
    Mirf.getData(&value);
    Serial.print("Data Received: ");
    Serial.println(value);
  }
}

Serial Monitor output:

Listening...
Data Received: 232
Data Received: 19
Data Received: 158
Data Received: 38
Data Received: 175
Data Received: 197
Data Received: 114
Data Received: 68

Here are the Mega/Uno sketches:

Transmitter:

// SimpleTx - the master or the transmitter

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

#define CE_PIN   9
#define CSN_PIN 10

const byte slaveAddress[5] = {'A','B','C','D','E'};

RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

byte dataToSend = 0;

unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 1000; // send once per second

//===================
void setup() {

    Serial.begin(9600);

    Serial.println("SimpleTx Starting");

    radio.begin();
    radio.setDataRate( RF24_250KBPS );
    radio.setPALevel(RF24_PA_MAX);
    radio.setChannel(90);
    radio.setRetries(3,5); // delay, count
    radio.openWritingPipe(slaveAddress);
}

//====================

void loop() {
    currentMillis = millis();
    if (currentMillis - prevMillis >= txIntervalMillis) {
        send();
        prevMillis = millis();
    }
}

//====================

void send() {

    bool rslt;
    rslt = radio.write( &dataToSend, sizeof(dataToSend) );
        // Always use sizeof() as it gives the size as the number of bytes.
        // For example if dataToSend was an int sizeof() would correctly return 2

    Serial.print("Data Sent ");
    Serial.print(dataToSend);
    if (rslt) {
        Serial.println("  Acknowledge received");
        updateMessage();
    }
    else {
        Serial.println("  Tx failed");
    }
}

//================

void updateMessage() {
        // so you can see that new data is being sent
    dataToSend = random(0,255);
}

Reciever:

// SimpleRx - the slave or the receiver

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

#define CE_PIN   9
#define CSN_PIN 10

const byte thisSlaveAddress[5] = {'A','B','C','D','E'};

RF24 radio(CE_PIN, CSN_PIN);

byte dataReceived; // this must match dataToSend in the TX
bool newData = false;

//===========

void setup() {

    Serial.begin(9600);

    Serial.println("SimpleRx Starting");
    radio.begin();
    radio.setDataRate( RF24_250KBPS );
    radio.setPALevel(RF24_PA_MAX);
    radio.setChannel(90);
    radio.openReadingPipe(1, thisSlaveAddress);
    radio.startListening();
}

//=============

void loop() {
    getData();
    showData();
}

//==============

void getData() {
    if ( radio.available() ) {
        radio.read( &dataReceived, sizeof(dataReceived) );
        newData = true;
    }
}

void showData() {
    if (newData == true) {
        Serial.print("Data received ");
        Serial.println(dataReceived);
        newData = false;
    }
}

Receiver Serial Monitor output:

SimpleRx Starting
Data received 0
Data received 232
Data received 19
Data received 158
Data received 38
Data received 175
Data received 197
Data received 114
Data received 68
Data received 188
Data received 109

And with the same boards, using the same sketches above, if I use the Mega (Transmitter) with the RF-Nano (Receiver). The Serial Monitor has "Listening..." and nothing more.

I have contacted eMakeFun to ask why in the Emitter sketch (Transmitter) they use the following:
In Setup:
//Set your own address (sender address) using 5 characters
Mirf.setRADDR((byte *)"DEADA");

In Loop:
Mirf.setTADDR((byte *)"ABCDE"); //Set the receiver address

In Mirf.cpp:
void Nrf24l::setRADDR(uint8_t * adr) // Sets the receiving device address
and
void Nrf24l::setTADDR(uint8_t * adr) // Sets the transmitting device address

It seems the functions do just the opposite of what they suggest. But it works...

gervaisrm:
All right - images attached!

I know you have put a lot of effort into your images but, sadly, some simple pencil drawings showing how things are connected would be a lot more informative. Photos of hardware with wires are too easy to misinterpret.

And I'm afraid I can't help with the RF-nanos - I know nothing about them.

...R

I don't have an RF-Nano but looking at the schematic for it, they use a Mega328P-AU device. The schematic shows it has a 16MHz crystal and is running from +5V. So it's pretty much like my Arduino UNO clone I have on the bench.

I could compile the code you used for your RF-Nano so it ran on my UNO. I spent a bit of time with your RF-Nano code running on one UNO and your UNO code running on a separate UNO. Unfortunately, I didn't get anywhere myself either. I did add a line of code to set the data rate for the Mirf to 250kbps in the hope that was the answer, but sadly, no!

But, here's something to try...

On the RF-Nano, the nRF24L01 is wired to use the hardware SPI interface (MOSI, MISO, SCK). CSN is wired to D9 (PB1) and CE is wired to D10 (PB2). These two signals are wired the opposite to how they are shown in Robin's tutorial.

So, from what I can see, you should be able to use the code you have on the UNO and upload it to your RF-Nano. The only changes I can see you would have to do is swap the definitions of CE_PIN and CSN_PIN over so that CE_PIN is 10 and CSN_PIN is 9.

That way, at least all your devices would be using the same radio library.

markd833:
I don't have an RF-Nano but looking at the schematic for it, they use a Mega328P-AU device.

I have been assuming it has one of the newer faster microprocessors. If it has an Atmega 328 then the code from my Tutorial should work fine.

...R

Thanks folks. I’ll try your suggestions. After looking through the code more last night I was thinking it was perhaps how the addresses get loaded. I’ll dig into that more, but I’ll also try swapping the pin definitions as Mark suggests and try Robins code.

I guess I was hoping someone out there had already solved this. Looks like I’m blazing the trail. I’ll periodically check in and let you know how it goes.

markd833 – Brilliant! I swapped the pin definitions and the RF24 library works on the RF-Nano. Thanks for that. I had noticed the pins were in the opposite order, but it hadn’t occurred to me to swap them in the NRF code - D’oh.

I’m on my way now.

I guess next I need to learn how to generate Fritzing diagrams to upload wiring diagrams, per Robin’s suggestion. You don’t want to see anything I write by hand, honest.

That's great that you got it working. It'll be a lot easier for you now that your various boards are using the same library.

If you can modify the title of your original post to indicate that the problem is solved - just add "[Solved]" or something similar, then hopefully others will spot the thread and it'll help them out too.

And thanks for letting us know that you got it working. ;D

gervaisrm:
I guess next I need to learn how to generate Fritzing diagrams to upload wiring diagrams, per Robin's suggestion.

Please Please Please do not use Fritzing. Those pictures look very nice but they are very easy to misinterpret.

Never mind how bad your drawing is, it will be a lot easier to make sense of than Fritzing.

...R

@mark
Just marked it solved. Also added what the solution is at the top of the first post, I figured it would save reading time if someone is just looking for the answer. I am very happy to be able to use just one library - I stayed up way too late last night getting started on the software.

@Robin
I just found the "how to post a diagram" thread. I'm curious how you feel they're easy to misinterpret? I've found them to be useful. Just a question, I'm happy (well maybe willing) to hand draw when necessary. Although I'll likely generate a board outline somehow just so I don't have to hand draw every time.

In any case, I am off and running. Thank you both for your help.

Robin2:
Please Please Please do not use Fritzing. Those pictures look very nice but they are very easy to misinterpret.

Right, drawings are crap. If anything, learn how to use Eagle.