Possible nRF24L01 code Issues on a RC Car

Hello, I'm having some issues with getting two nRF24Ls to connect to each other. I'm building a basic RC Car with a brushless motor and servo powered by LiPos and two Arduino Nanos. This used to work, but a short killed the Uno I was using, and after migrating to a new Nano I can't get my Remote to control the car. I've dug through several videos and posts over the topic and have found some errors, but none have allowed my remote to control the servo or motor. I've also verified all my connections are working with a multimeter to my radio modules. I'll include a picture of my diagrams and codes. I'm posting here to hopefully rule out a code error, as I'm sure my code has holes in it not allowing it to work properly. I've tried to include all info to help I can, let me know if you need more.
Note: This mainly isn't my code, its someone else's I've edited quite a bit.
Sorry for everything looking so first gradeish.


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

RF24 radio(9, 10);   // nRF24L01 (CE, CSN)
const byte address[6] = "00001"; // Address
// Max size of this struct is 32 bytes - NRF24L01 buffer limit
struct Data_Package {
  byte j1PotY;
  byte j2PotX;
};
Data_Package data; //Create a variable with the above structure
void setup() {
  Serial.begin(9600);
  pinMode(27, OUTPUT);
  // Define the radio communication
  radio.begin();
  radio.openWritingPipe(address);
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_LOW);
  radio.stopListening();

  // Set initial default values
  // Values from 0 to 255. When Joystick is in resting position, the value is in the middle, or 127. We actually map the pot value from 0 to 1023 to 0 to 255 because that's one BYTE value
  data.j1PotY = 127;
  data.j2PotX = 127;
}
void loop() {
  // Read all analog inputs and map them to one Byte value
  data.j1PotY = map(analogRead(A0), 0, 1023, 0, 255);
  data.j2PotX = map(analogRead(A2), 0, 1023, 0, 255);

  // Send the whole data from the structure to the receiver
  radio.write(&data, sizeof(Data_Package));
}
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>
RF24 radio(9, 10);   // nRF24L01 (CE, CSN)
const byte address[6] = "00001";
unsigned long lastReceiveTime = 0;
unsigned long currentTime = 0;
Servo esc;  // create servo object to control the ESC
Servo servo1;
int escValue, servo1Value, servo2Value;
// Max size of this struct is 32 bytes - NRF24L01 buffer lit
struct Data_Package {
  byte j1PotY;
  byte j2PotX;
};
Data_Package data; //Create a variable with the above structure
void setup() {
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_LOW);
  radio.startListening(); //  Set the module as receiver
  resetData();
  esc.attach(6, 1000, 2000); // Arduino digital pin D10 - CH9 on PCB board
  servo1.attach(5); // D3 - CH1
}
void loop() {
  // Check whether we keep receving data, or we have a connection between the two modules
  currentTime = millis();
  if ( currentTime - lastReceiveTime > 250 ) { // If current time is more then 1 second since we have recived the last data, that means we have lost connection
    resetData(); // If connection is lost, reset the data. It prevents unwanted behavior, for example if a drone jas a throttle up, if we lose connection it can keep flying away if we dont reset the function
  }
  // Check whether there is data to be received
  if (radio.available()) {
    radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure
    lastReceiveTime = millis(); // At this moment we have received the data
  }
  // Controlling servos
  servo1Value = map(data.j2PotX, 0,  255, 0, 180); // Map the receiving value form 0 to 255 to 0 to 180(degrees), values used for controlling servos
  servo1.write(servo1Value);
  // Controlling brushless motor with ESC
  escValue = map(data.j1PotY, 127, 255, 1000, 2000); // Map the receiving value form 127 to 255 to  1000 to 2000, values used for controlling ESCs
  esc.writeMicroseconds(escValue); // Send the PWM control singal to the ESC
}
void resetData() {
  data.j1PotY = 127;
  data.j2PotX = 127;
}

The Nano 3.3V regulator very likely does not have the current capability to power a rf24 radio module. Try powering the radio with a 2 AA battery pack (3V).

Images of code are nearly useless. We cannot copy the code to a text editor or IDE for examination or to run the code. Nor can we copy lines of code into a post. Read the forum guidelines to see how to properly post code.

Use the IDE autoformat tool (ctrl-t or Tools, Auto format) before posting code in code tags.

Alright, ill see what that does.
Ill reupload with the proper format.

Please do post the code properly. I have at least one question about the code, but need to copy the line so that you know what I am asking about.

There, should be redone right.

1 Like

I have 2 Unos set up with rf24 radios and loaded your code to them. The sender has a joystick attached. I don't have a servo or ESC handy.

I added prints to the receiver to see what is received and the code sure seems to be receiving fine.

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>
RF24 radio(9, 10);   // nRF24L01 (CE, CSN)
const byte address[6] = "00001";
unsigned long lastReceiveTime = 0;
unsigned long currentTime = 0;
Servo esc;  // create servo object to control the ESC
Servo servo1;
int escValue, servo1Value, servo2Value;
// Max size of this struct is 32 bytes - NRF24L01 buffer lit
struct Data_Package
{
   byte j1PotY;
   byte j2PotX;
};
Data_Package data; //Create a variable with the above structure
void setup()
{
   Serial.begin(9600);
   radio.begin();
   radio.openReadingPipe(0, address);
   radio.setAutoAck(false);
   radio.setDataRate(RF24_250KBPS);
   radio.setPALevel(RF24_PA_LOW);
   radio.startListening(); //  Set the module as receiver
   resetData();
   esc.attach(6, 1000, 2000); // Arduino digital pin D10 - CH9 on PCB board
   servo1.attach(5); // D3 - CH1
}
void loop()
{
   // Check whether we keep receving data, or we have a connection between the two modules
   currentTime = millis();
   if ( currentTime - lastReceiveTime > 250 )   // If current time is more then 1 second since we have recived the last data, that means we have lost connection
   {
      resetData(); // If connection is lost, reset the data. It prevents unwanted behavior, for example if a drone jas a throttle up, if we lose connection it can keep flying away if we dont reset the function
   }
   // Check whether there is data to be received
   if (radio.available())
   {
      radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure
      lastReceiveTime = millis(); // At this moment we have received the data

      Serial.print("Y axis = ");
      Serial.print(data.j1PotY);
      Serial.print("    X axis = ");
      Serial.println(data.j2PotX);
   }
   // Controlling servos
   servo1Value = map(data.j2PotX, 0,  255, 0, 180); // Map the receiving value form 0 to 255 to 0 to 180(degrees), values used for controlling servos
   servo1.write(servo1Value);
   // Controlling brushless motor with ESC
   escValue = map(data.j1PotY, 127, 255, 1000, 2000); // Map the receiving value form 127 to 255 to  1000 to 2000, values used for controlling ESCs
   esc.writeMicroseconds(escValue); // Send the PWM control singal to the ESC
}
void resetData()
{
   data.j1PotY = 127;
   data.j2PotX = 127;
}

Receiver output

Y axis = 143 X axis = 153
Y axis = 135 X axis = 178
Y axis = 107 X axis = 195
Y axis = 63 X axis = 198
Y axis = 25 X axis = 208
Y axis = 1 X axis = 209
Y axis = 1 X axis = 185
Y axis = 0 X axis = 134
Y axis = 0 X axis = 70
Y axis = 1 X axis = 28
Y axis = 18 X axis = 19

So if your receiver is not getting the data my first guess as to why not is that there is a power problem like I said in reply #2. The Nano has a weak 3.3V supply.

I would also recommend slowing down the sender. I would send 20 to 50 times a second, that should be plenty. The more often that you send, the more power is required.

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

RF24 radio(9, 10);   // nRF24L01 (CE, CSN)
const byte address[6] = "00001"; // Address
// Max size of this struct is 32 bytes - NRF24L01 buffer limit
struct Data_Package
{
   byte j1PotY;
   byte j2PotX;
};
Data_Package data; //Create a variable with the above structure
void setup()
{
   Serial.begin(9600);
   pinMode(27, OUTPUT);
   // Define the radio communication
   radio.begin();
   radio.openWritingPipe(address);
   radio.setAutoAck(false);
   radio.setDataRate(RF24_250KBPS);
   radio.setPALevel(RF24_PA_LOW);
   radio.stopListening();

   // Set initial default values
   // Values from 0 to 255. When Joystick is in resting position,
   //the value is in the middle, or 127. We actually map the pot value
   //from 0 to 1023 to 0 to 255 because that's one BYTE value
   data.j1PotY = 127;
   data.j2PotX = 127;
   Serial.println(sizeof(Data_Package));
}
void loop()
{
   static unsigned long timer = 0;
   unsigned long interval = 50; // 20 sends per second
   if (millis() - timer >= interval)
   {
      timer = millis();

      // Read all analog inputs and map them to one Byte value
      data.j1PotY = map(analogRead(A0), 0, 1023, 0, 255);
      data.j2PotX = map(analogRead(A1), 0, 1023, 0, 255); // changed to A1 from A2

      Serial.print("Y axis = ");
      Serial.print(data.j1PotY);
      Serial.print("    X axis = ");
      Serial.println(data.j2PotX);

      // Send the whole data from the structure to the receiver
      radio.write(&data, sizeof(Data_Package));
   }
}
   

to learn about millis() for timing:

Several things at a time.
Beginner's guide to millis().
Blink without delay().

oh wow, that's a lot more than I was expecting. Thank you so much! Ill definitely add a power source for the radios other than the 3.3v rail. Thanks for the advice on the millis timing too, ill be using that for sure. Thank you for taking the time and testing the code.

1 Like