Middle School Student Help with Receiver / Transmitter [nRF24L01.h]

Dear fellow Arduino users,

Me and two friends are having trouble on an Arduino project we are working on. We are using two arduinos and trying to have one of them send a signal to another one by a press of a button using NF24L01+ (with the antenna). Our sender code is as follows:

// Include Libraries
#include <nRF24L01.h>
#include <RF24.h>
#include <SPI.h>

// create an RF24 object
RF24 radio(9, 8); // CE, CSN

// the number of the pushbutton pin
const int buttonPin = 3;

// variable for reading the pushbutton status
int buttonState = 0;

//address through which two modules communicate.
const byte address[6] = "00001";

void setup()
{
Serial.begin(9600);
Serial.println("nrf24L01+ Transmitter Starting!\n");

// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);

radio.begin();
radio.setRetries(15, 15);

//set the address
radio.openWritingPipe(address);

radio.setPALevel(RF24_PA_MAX);

//Set module as transmitter
radio.stopListening();
}

void loop()
{
buttonState = digitalRead(buttonPin);

if (buttonState == 1) {
Serial.write("Sending the following message: \n");

//Send message to receiver
const char text[] = "\t Hello, friend!";
Serial.write(text);
Serial.write("\n\n");

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

delay(1000);
}
}

Meanwhile, here is the receiver code.

//Include Libraries

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

//create an RF24 object
RF24 radio(9, 8); // CE, CSN

//address through which two modules communicate.
const byte address[6] = "00001";

void setup()
{
Serial.begin(9600);

radio.begin();

//set the address
radio.openReadingPipe(0, address);
radio.setPALevel(RF24_PA_MAX);

//Set module as receiver
radio.startListening();
}

void loop()
{
//Read the data if available in buffer
if (radio.available())
{
Serial.print("hello");
char text[32] = "";
radio.read(&text, sizeof(text));
Serial.println(text);
}

}

However, we are not receiving any signal on the receiving end. We are pretty sure all our pins are correct. We are wondering if anyone had any advice on how we could troubleshoot. Thank you.

Please follow the instructions in Read this before posting a programming question and post your code properly as I doubt that it really has smileys in it

Have a look at this Simple nRF24L01+ Tutorial.

Wireless problems can be very difficult to debug so get the wireless part working on its own before you start adding any other features.

The examples are as simple as I could make them and they have worked for other Forum members. If you get stuck it will be easier to help with code that I am familiar with. Start by getting the first example to work

There is also 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. 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, we tried following the first example as well as the connection test program and while the Arduinos seem to be able to connect with their own transreceivers, the transreceivers can't connect with each other. We thought that there might be a problem with power and ground connections and introduced a 10, then a 100 microF capacitor (image attached below), but we still seem to be having problems with the connection. The transmitter is attempting to send signals and fails while the receiver arduino does not print anything (no packet received).

IMG_2392.png|0x0

Image from Reply #3 so we don't have to download it. See this Simple Image Posting Guide

There is something wrong with the image file. It does not show here and I have not been able to open it even after downloading it

...R

Debugging wireless problems is difficult and takes time and patience.

How are you powering your nRF24 modules?

What Arduino boards are you using?

Post the output from both Arduinos when you use my connection test program.

Also, post the actual Rx and Tx programs that YOU have uploaded to your Arduinos and post a sample of the output from each of them.

...R

Hi Robin2! Thank you for your willingness to help. We will provide as much information as we can below.

First, we are using two Arduino Unos (ELEGOO version) and powering them through our Macbook Pros' USB ports. We are also using a USB-A to USB-C adapter on one of the laptops because it's a newer one.

We ran the connection_test program that you have written. The code is almost a direct copy except our CSN_PIN is different:

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

#include <printf.h>

#define CE_PIN   9
#define CSN_PIN  8

const byte thisSlaveAddress[5] = {'R','x','A','A','A'};

RF24 radio(CE_PIN, CSN_PIN);

char dataReceived[10]; // this must match dataToSend in the TX
bool newData = false;


void setup() {
    Serial.begin(9600);
    printf_begin();

    Serial.println("CheckConnection Starting");
    Serial.println();
    Serial.println("FIRST WITH THE DEFAULT ADDRESSES after power on");
    Serial.println("  Note that RF24 does NOT reset when Arduino resets - only when power is removed");
    Serial.println("  If the numbers are mostly 0x00 or 0xff it means that the Arduino is not");
    Serial.println("     communicating with the nRF24");
    Serial.println();
    radio.begin();
    radio.printDetails();
    Serial.println();
    Serial.println();
    Serial.println("AND NOW WITH ADDRESS AAAxR  0x41 41 41 78 52   ON P1");
    Serial.println(" and 250KBPS data rate");
    Serial.println();
    radio.openReadingPipe(1, thisSlaveAddress);
    radio.setDataRate( RF24_250KBPS );
    radio.printDetails();
    Serial.println();
    Serial.println();
}


void loop() {

}

The following is the output of the program for the receiver Arduino:

CheckConnection Starting

FIRST WITH THE DEFAULT ADDRESSES after power on
  Note that RF24 does NOT reset when Arduino resets - only when power is removed
  If the numbers are mostly 0x00 or 0xff it means that the Arduino is not
     communicating with the nRF24

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


AND NOW WITH ADDRESS AAAxR  0x41 41 41 78 52   ON P1
 and 250KBPS data rate

STATUS		 = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1	 = 0x4141417852 0x4141417852
RX_ADDR_P2-5	 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR		 = 0x4141417852
RX_PW_P0-6	 = 0x20 0x20 0x00 0x00 0x00 0x00
EN_AA		 = 0x3f
EN_RXADDR	 = 0x03
RF_CH		 = 0x4c
RF_SETUP	 = 0x27
CONFIG		 = 0x0e
DYNPD/FEATURE	 = 0x00 0x00
Data Rate	 = 250KBPS
Model		 = nRF24L01+
CRC Length	 = 16 bits
PA Power	 = PA_MAX

The following is the output of the program on the transmitter Arduino:

Ch= PA_MAX = 0x0e
DYNPD/FEATURE = 0x00 0x00
Data Rate = 250KBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_MAX


CheckConnection Starting

FIRST WITH THE DEFAULT ADDRESSES after power on
  Note that RF24 does NOT reset when Arduino resets - only when power is removed
  If the numbers are mostly 0x00 or 0xff it means that the Arduino is not
     communicating with the nRF24

STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xe7e7e7e7e7 0x4141417852
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xe7e7e7e7e7
RX_PW_P0-6 = 0x00 0x20 0x00 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x03
RF_CH = 0x4c
RF_SETUP = 0x07
CONFIG = 0x0e
DYNPD/FEATURE = 0x00 0x00
Data Rate = 1MBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_MAX


AND NOW WITH ADDRESS AAAxR  0x41 41 41 78 52   ON P1
 and 250KBPS data rate

STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0xe7e7e7e7e7 0x4141417852
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xe7e7e7e7e7
RX_PW_P0-6 = 0x00 0x20 0x00 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x03
RF_CH = 0x4c
RF_SETUP = 0x27
CONFIG = 0x0e
DYNPD/FEATURE = 0x00 0x00
Data Rate = 250KBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_MAX

To see if the two transceivers can talk to each other, we used your simple transmitter / simple receiver code, with just the pin changed. Below is the receiver code:

// SimpleRx - the slave or the receiver

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

#define CE_PIN   9
#define CSN_PIN  8

const byte thisSlaveAddress[5] = {'R','x','A','A','A'};

RF24 radio(CE_PIN, CSN_PIN);

char dataReceived[10]; // 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.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;
    }
}

The following is the transmitter code:

// SimpleTx - the master or the transmitter

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


#define CE_PIN   9
#define CSN_PIN  8

const byte slaveAddress[5] = {'R','x','A','A','A'};


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

char dataToSend[10] = "Message 0";
char txNum = '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.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
    txNum += 1;
    if (txNum > '9') {
        txNum = '0';
    }
    dataToSend[8] = txNum;
}

When running the code, we simply get "SimpleRx Starting" on the receiver end and repeated "Data Sent Message 0 Tx failed" on the transmitter end. The transmitter board is blinking yellow every second, so I think that's good?

Also, we couldn't embed the photo into the post, so here is a google drive link to the photo of our setup for capacitors between the transceivers' power and ground connections (the warm-colored connections are live wires) as well as our entire setup:
https://drive.google.com/drive/folders/1T-95YhXyHAZtViBRGsm6kcW815LWLmPy?usp=sharing

We would appreciate any insight because we honestly have no clue why this is not working.

I guess the first question is why are you not using the same I/O pins as in my Tutorial - at least for the tests?

Your connection test seems to be working OK but while you don't have to use pin 10 with the nRF24 it really needs to be set as OUTPUT when using SPI to ensure that the Arduino acts as SPI master.

You said in your Original Post that you have high-power nRF24s with external antennas. You have not told us how you are powering them. Also, make sure they are separated by maybe 3 metres or more for your tests. When they are too close they don't work (think of someone putting their mouth close to your ear and then shouting as loud has they can).

...R

PS ... please just add your images as an attachment to your next Reply and then make them visible in the Reply. I have give a link to the instructions.

Hello Robin2,

We are now using the same I/O as from your tutorial and we further set pin 10 as OUTPUT as you suggested. Additionally, we ensured that the transmitter and receiver Arduino units were at least 3 meters apart, however, we are still getting the same outputs as before, i.e. the transmitter end says "Data Sent Message 0 Tx failed" while the receiver end says "SimpleRx Starting" .

Do you have suggestions on how we should move forward to diagnose the problem? Thanks so much for you help so far!

P.S. We have also attached an image of our current set-up below.

IMG_6358.png|0x0

I can't open your image - even when I download it. Please make it visible in your Post so e don't have to download it. See this Simple Image Posting Guide

You have still not said how you are powering your nRF24s.

Do you have some spare nRF24s in case one of them is faulty?

It would probably be easier to do the initial debugging with a pair of low-power nRF24s. The exact same program will work with the high power modules.

...R

Hello, Robin!

Thank you for all of your help you've given us some time ago. I hope you are staying safe and well in these hectic times.

Since our last post, we've made a lot of progress! We ended up getting the cheap non-antenna nRF24 modules and ended up having them communicate! To our "sensor" Arduino, we hooked up a simple analog water sensor whose data we then analyze and send over to the "master" Arduino that simply prints the data out.

After that, we decided to add a button, so that the "master" Arduino can "request" data from the "sensor" Arduino whenever the button is pushed. We followed your slave-master switching code example for our prototype. However, we keep getting "FAILED: Request for Data" on the "master" Arduino while our "sensor" Arduino's Serial Monitor remains empty.

We would really appreciate it if you took a quick look at our code. I think we must be missing something.

This is our "master" Arduino code (the one that is supposed to first send a request by button then read data):

// SimpleRx - the slave or the receiver

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

#define CE_PIN   9
#define CSN_PIN  8
#define BUTTON   4

int buttonState = 0;  // the status of the button
int prevButtonState = 0; // the previous state of the button

const byte slaveAddress[5] = {'R','x','A','A','A'};
const byte masterAddress[5] = {'T','X','a','a','a'};

RF24 radio(CE_PIN, CSN_PIN);

char dataReceived[20]; // this must match dataToSend in the TX
int requestData[2] = {109, -4000}; // the two values to be sent to the master
bool newData = false;

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

void setup() {

    pinMode(BUTTON, INPUT);
    
    Serial.begin(9600);

    Serial.println("---------------------------------------------------------");
    Serial.println("SimpleRx Starting");
    Serial.println("---------------------------------------------------------");
    radio.begin();
    radio.setDataRate( RF24_250KBPS );
    radio.openWritingPipe(masterAddress); 
    radio.openReadingPipe(1, slaveAddress);
    radio.setRetries(3,5); // delay, count
}

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

void loop() {
    buttonState = digitalRead(BUTTON);
    if (buttonState != prevButtonState) {
       prevButtonState = buttonState;
       send();
       getData();
       showData();  
    }
}

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

void send() {
    
    radio.stopListening();
    bool rslt;
    rslt = radio.write(&requestData, sizeof(requestData));
    
    radio.startListening();

    if (rslt) {
      Serial.println("Request for Data Sent");
    }
    else {
      Serial.println("FAILED: Request for Data");
    }
    Serial.println();
}

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

void getData() {
  for (int i = 0; i < 2; i++) {
      if ( radio.available() ) {
        radio.read( &dataReceived, sizeof(dataReceived) );
        newData = true;
    }
  }
}

void showData() {
    for (int i = 0; i < 2; i++) {
      if (newData == true) {
        Serial.print("Data received ");
        Serial.println(dataReceived);
      }
    }
    Serial.println("---------------------------------------------------------");
    newData = false;
}

This is our "sensor" Arduino code that waits for a request for data collection, the collects data and sends it back.

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

//---------------------------------------------------------------------------------------

#define CE_PIN   9
#define CSN_PIN  8

// Configuration values:
#define SERIES_RESISTOR     2000    // Value of the series resistor in ohms.   
#define SENSOR_PIN          0      // Analog pin which is connected to the sensor.

#define ZERO_VOLUME_RESISTANCE    2320000    // Resistance value (in ohms) when no liquid is present. [546]
#define CALIBRATION_RESISTANCE    637000    // Resistance value (in ohms) when liquid is at max line. [188]
#define CALIBRATION_VOLUME        980      // Volume (in mL) when liquid is at max line.

char volumeDataToSend[20];
char heightDataToSend[20];
int dataReceived[2]; // to accept the request for data
bool request = false;

//---------------------------------------------------------------------------------------

// CONSTANTS: volume of container = , radius of container = 3.0 cm
float radius = 3.0;
const byte slaveAddress[5] = {'R','x','A','A','A'};
const byte masterAddress[5] = {'T','X','a','a','a'};

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

//---------------------------------------------------------------------------------------

// SET UP TRANSMISSION
void setup(void) {
    Serial.begin(9600);
    Serial.println("SimpleTx Starting");

    radio.begin();
    radio.setDataRate( RF24_250KBPS );
   
    radio.openWritingPipe(slaveAddress);
    radio.openReadingPipe(1, masterAddress);

    radio.setRetries(3,5); // delay, count
}

//---------------------------------------------------------------------------------------

void loop(void) {

    radio.startListening();
    getRequest();
    radio.stopListening();
    if (!request) {
      return;
    }
    request = false;
    
    // Measure sensor resistance.
    float resistance = 0;
    for (int i = 0; i < 20000; i++) {
      resistance += readResistance(SENSOR_PIN, SERIES_RESISTOR); // get 20 readings
    }
    
    resistance = resistance / 20.0; 
    Serial.print("Resistance: ");
    Serial.print(resistance, 2);
    Serial.println(" ohms");
    
    // Map resistance to volume.
    float volume = resistanceToVolume(resistance, ZERO_VOLUME_RESISTANCE, CALIBRATION_RESISTANCE, CALIBRATION_VOLUME);
    Serial.print("Calculated volume: ");
    Serial.println(volume, 5);

    // Map resistance to height.
    float height = volume / (3.1415 * radius * radius);
    Serial.print("Calculated height: ");
    Serial.println(height, 5);

    // send the data
    String s = "Volume: " + String(volume) + " mL";
    s.toCharArray(volumeDataToSend, sizeof(volumeDataToSend));

    String s2 = "Height: " + String(height) + " cm";
    s2.toCharArray(heightDataToSend, sizeof(heightDataToSend));
    
    // sendTest();
    send();
}

//---------------------------------------------------------------------------------------
//void sendTest() {
//  bool rslt;
//  // SENDINNG VOLUME
//    char volumeDataToSend[20] = "I have coronavirus.";
//    rslt = radio.write( &volumeDataToSend, sizeof(volumeDataToSend));
//
//    Serial.print(volumeDataToSend);
//    if (request) {
//        Serial.println("  Acknowledge received: volume successfully sent");
//    }
//    else {
//        Serial.println("  Tx failed volume");
//    }
//}
//---------------------------------------------------------------------------------------

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

//---------------------------------------------------------------------------------------

void send() {

    bool rslt;

    // SENDINNG VOLUME
    rslt = radio.write( &volumeDataToSend, sizeof(volumeDataToSend));
    Serial.print(volumeDataToSend);
    
    if (rslt) {
        Serial.println("  Acknowledge received: volume successfully sent");
    }
    else {
        Serial.println("  Tx failed volume");
    }

    // SENDING HEIGHT
    rslt = radio.write( &heightDataToSend, sizeof(heightDataToSend));
        

    Serial.print(heightDataToSend);
    if (rslt) {
        Serial.println("  Acknowledge received: height successfully sent");
    }
    else {
        Serial.println("  Tx failed height");
    }
    Serial.println("\n---------------------------------------------------------");
}

//---------------------------------------------------------------------------------------

float readResistance(int pin, int seriesResistance) {
    // Get ADC value.
    float resistance = analogRead(pin);

    // Convert ADC reading to resistance.
    resistance = (1023.0 / resistance) - 1.0;
    resistance = seriesResistance / resistance;
    return resistance;
}

//---------------------------------------------------------------------------------------

float resistanceToVolume(float resistance, float zeroResistance, float calResistance, float calVolume) {
  
    if (resistance > zeroResistance || (zeroResistance - calResistance) == 0.0) {
    // Stop if the value is above the zero threshold, or no max resistance is set (would be divide by zero).
        return 0.0;
    }
    
    // Compute scale factor by mapping resistance to 0...1.0+ range relative to maxResistance value.
    float scale = (zeroResistance - resistance) / (zeroResistance - calResistance);
    
    // Scale maxVolume based on computed scale factor.
    return calVolume * scale;
}

Any help would be appreciated. Have a great week!

LostMiddleSchoolStudent:
We followed your slave-master switching code example for our prototype.

Did you start with my example without any changes?

If not, then that is the place to start.

When that works add your extra bits a few lines at a time testing carefully after every change.

...R