NRF24L01 works with Nano but not with Pro Mini

Hi,

I am trying to build this RC transmitter and receiver. I build one setup with an arduino nano and it works perfect. The transmitter has a thumstick which controls 2 DC motors with L298N motor driver on the receiver side(car).

However when I build the same setup but this time with a pro mini on the transmitter instead of a nano the NRF24L01 does not communicate.

What do I want to reach:

  • Using a joystick on the arduino pro mini transmitter to move 2 dc motors with L298N motorshield on the receiver

Setup:
Transmitter

  • Arduino pro mini 5v 328P 16mhz
  • NRF24L01 + PA + LNA
  • NRF24L01 breakout board
  • 2x lipo 2300 mah

Receiver

  • Arduino uno
  • L298N motorshield
  • NRF24L01 + PA + LNA
  • NRF24L01 breakout board
  • 3x lipo 2300 mah

What did I try:

  • Changed the pro mini, maybe it’s a faulty one. Tried 4 of them. All same issue.
  • Tested the pro mini with serial monitor - works perfect
  • Used an arduino NANO instead of a pro mini - works perfect (used the same nrf breakout + module so this one is working fine)

!! What did I noticed / having doubts:
When I connect the pro mini to the PC USB for powering AND I power up the NRF24 directly (through the breakout board) onto the LIPO(2x 3.7 volt 2300mah) (so nrf is not powered by arduino!) it all works fine.
I noticed this small led on the pro mini is blinking while transmitting/running the code.

However, when I power up the NRF24 directly (though the breakout board) onto the LIPO(2x 3.7 volt 2300mah) (so nrf is not powered by arduino!) and this time also connect the arduino pro mini directly onto the LIPO (Using the RAW pin) it does not work!
I noticed this small led on the pro mini is not blinking while transmitting/running the code.

And guess what, I want to power up the arduino pro mini with the LIPO’s. So what am I doing wrong?
Should I not power up the pro mini directly on the LIPO using the RAW pin? Or should I change the code/pinning of the NRF because using the RAW pin?

Code transmitter

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

RF24 radio(8, 9); // CE, CSN
const byte address[6] = "00001";

char xyData[32] = "";
String xAxis, yAxis;

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

void loop() {
  
  xAxis = analogRead(A0); // Read Joysticks X-axis
  yAxis = analogRead(A1); // Read Joysticks Y-axis
  
  // X value
  xAxis.toCharArray(xyData, 5); // Put the String (X Value) into a character array
  radio.write(&xyData, sizeof(xyData)); // Send the array data (X value) to the other NRF24L01 modile
  
  // Y value
  yAxis.toCharArray(xyData, 5);
  radio.write(&xyData, sizeof(xyData));
  delay(20);
}

Code receiver

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

#define enA 2  
#define in1 4
#define in2 5
#define enB 3   
#define in3 6
#define in4 7

RF24 radio(8, 9); // CE, CSN
const byte address[6] = "00001";

char receivedData[32] = "";
int  xAxis, yAxis;

int motorSpeedA = 0;
int motorSpeedB = 0;

void setup() {
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
}

void loop() {

  if (radio.available()) {   // If the NRF240L01 module received data
    radio.read(&receivedData, sizeof(receivedData)); // Read the data and put it into character array
    xAxis = atoi(&receivedData[0]); // Convert the data from the character array (received X value) into integer
    delay(10);
    radio.read(&receivedData, sizeof(receivedData));
    yAxis = atoi(&receivedData[0]);
    delay(10);
  }
  
  // Y-axis used for forward and backward control
  if (yAxis < 470) {
    // Set Motor A backward
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
    // Set Motor B backward
    digitalWrite(in3, HIGH);
    digitalWrite(in4, LOW);
    // Convert the declining Y-axis readings for going backward from 470 to 0 into 0 to 255 value for the PWM signal for increasing the motor speed
    motorSpeedA = map(yAxis, 470, 0, 0, 255);
    motorSpeedB = map(yAxis, 470, 0, 0, 255);
  }
  else if (yAxis > 550) {
    // Set Motor A forward
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
    // Set Motor B forward
    digitalWrite(in3, LOW);
    digitalWrite(in4, HIGH);
    // Convert the increasing Y-axis readings for going forward from 550 to 1023 into 0 to 255 value for the PWM signal for increasing the motor speed
    motorSpeedA = map(yAxis, 550, 1023, 0, 255);
    motorSpeedB = map(yAxis, 550, 1023, 0, 255);
  }
  // If joystick stays in middle the motors are not moving
  else {
    motorSpeedA = 0;
    motorSpeedB = 0;
  }

  // X-axis used for left and right control
  if (xAxis < 470) {
    // Convert the declining X-axis readings from 470 to 0 into increasing 0 to 255 value
    int xMapped = map(xAxis, 470, 0, 0, 255);
    // Move to left - decrease left motor speed, increase right motor speed
    motorSpeedA = motorSpeedA - xMapped;
    motorSpeedB = motorSpeedB + xMapped;
    // Confine the range from 0 to 255
    if (motorSpeedA < 0) {
      motorSpeedA = 0;
    }
    if (motorSpeedB > 255) {
      motorSpeedB = 255;
    }
  }
  if (xAxis > 550) {
    // Convert the increasing X-axis readings from 550 to 1023 into 0 to 255 value
    int xMapped = map(xAxis, 550, 1023, 0, 255);
    // Move right - decrease right motor speed, increase left motor speed
    motorSpeedA = motorSpeedA + xMapped;
    motorSpeedB = motorSpeedB - xMapped;
    // Confine the range from 0 to 255
    if (motorSpeedA > 255) {
      motorSpeedA = 255;
    }
    if (motorSpeedB < 0) {
      motorSpeedB = 0;
    }
  }
  // Prevent buzzing at low speeds
  if (motorSpeedA < 70) {
    motorSpeedA = 0;
  }
  if (motorSpeedB < 70) {
    motorSpeedB = 0;
  }
  analogWrite(enA, motorSpeedA); // Send PWM signal to motor A
  analogWrite(enB, motorSpeedB); // Send PWM signal to motor B
}

Schematic of the transmitter is attached.

Forgive my English, I’m not a native speaker.
If you need any additional information, please let me know.

Thanks for you help, much appreciated.

Greetings
Joe

Image from Original Post so we don't have to download it. See this Simple Image Posting Guide

...R

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.

If you are using the high-power nRF24s (with the external antenna) make sure there is sufficient distance between the two nRF24s so that the signal does not overwhelm the receiver - try 3 metres separation. If you are new to nRF24s it may be better to start with a pair of low power modules with the pcb antenna.

I am not familiar with the ProMini but I think it uses the same Atmega 328 as the Uno and nano. But if it is a 5v ProMini it may not work from a 1S LiPo.

NOTE that the voltage from a 1S LiPo is too high for the Vcc pin on an nRF24 which has a max of 3.6v. I put a diode between the battery and my nRF24s to drop the voltage by about 0.6v. (The other nRF24 pins are OK with 5v)

...R

Thanks Robin.
Went through the whole tutorial you gave, it was really helpfull. Tested the NRF modules and they all work fine.

I changed to an Arduino nano and the RC im building is working pretty good.
The NRF24l01 has it’s own dedicated powersource.

I created this RC transmitter RC Transmitter - NANO
The original came from Howtomechatronics.com

I’m facing a new issue now.

What I try to do:
I am sending the data from the TX remote (button inputs etc) to the receiver using a data package structure as shown on the website of the original creator - and in the code of the TX below.

What happens
When I send the whole package, so all buttons/switches/joysticks from TX to RX nothing happens when I try them on the TX remote.
When I send partial data from the TX to the RX it works fine. Could it be that I try to send to much data at once?

As long as I don’t send data from the following inputs it works fine Because of this I now keep these buttons etc. commented // - but that’s not what I want:

  • Joystick buttons 1 and 2
  • Joystick 2
  • Potentiometer 2

The question:
What should I do to send the whole data package and make it work?

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


// Define the digital inputs
//#define jB1 1  // Joystick button 1 - rechts
//#define jB2 0  // Joystick button 2 - Links
#define t1 4   // Toggle switch 1 - Links
#define t2 7   // Toggle switch 2 - Rechts
#define b1 8   // Button 1 - Left under
#define b2 9   // Button 2 - Left upper
#define b3 2   // Button 3 - Richt upper
#define b4 3   // Button 4 - Right under



RF24 radio(5, 6);   // nRF24L01 (CE, CSN)
const byte address[6] = "00001"; // Address


// Max size of this struct is 32 bytes - NRF24L01 buffer limit
struct Data_Package {
byte j1PotX;
byte j1PotY;
//byte j1Button;
//byte j2PotX;
//byte j2PotY;
//byte j2Button;
byte pot1;
//byte pot2;
byte tSwitch1;
byte tSwitch2;
byte button1;
byte button2;
byte button3;
byte button4;
};

Data_Package data; //Create a variable with the above structure



void setup() {
  Serial.begin(9600);
  
   // Define the radio communication
  radio.begin();
  radio.openWritingPipe(address);
  //radio.setAutoAck(false);
  //radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();

    // Activate the Arduino internal pull-up resistors
//pinMode(jB1, INPUT_PULLUP);
//pinMode(jB2, INPUT_PULLUP);
pinMode(t1, INPUT_PULLUP);
pinMode(t2, INPUT_PULLUP);
pinMode(b1, INPUT_PULLUP);
pinMode(b2, INPUT_PULLUP);
pinMode(b3, INPUT_PULLUP);
pinMode(b4, INPUT_PULLUP);

  // Set initial default values
data.j1PotX = 127; // 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;
//data.j2PotY = 127;
//data.j1Button = 1;
//data.j2Button = 1;
data.pot1 = 1;
//data.pot2 = 1;
data.tSwitch1 = 1;
data.tSwitch2 = 1;
data.button1 = 1;
data.button2 = 1;
data.button3 = 1;
data.button4 = 1;

}


void loop() {
  // Read all analog inputs and map them to one Byte value
  data.j1PotX = map(analogRead(A2), 0, 1023, 0, 255); // Convert the analog read value from 0 to 1023 into a BYTE value from 0 to 255
  data.j1PotY = map(analogRead(A3), 0, 1023, 0, 255);
  //data.j2PotX = map(analogRead(A2), 0, 1023, 0, 255);
  //data.j2PotY = map(analogRead(A3), 0, 1023, 0, 255);
  data.pot1 = map(analogRead(A7), 0, 1023, 0, 255);
  //data.pot2 = map(analogRead(A6), 0, 1023, 0, 255);
// Read all digital inputs
  //data.j1Button = digitalRead(jB1);
  //data.j2Button = digitalRead(jB2);
  data.tSwitch1 = digitalRead(t1);
  data.tSwitch2 = digitalRead(t2);
  data.button1 = digitalRead(b1);
  data.button2 = digitalRead(b2);
  data.button3 = digitalRead(b3);
  data.button4 = digitalRead(b4);



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

  delay(20);
}

PLease let me know is something is unclear.
Thanks in advance.

It seems like there are only 9 bytes in your struct and a message can have up to 32 bytes.

Maybe the problem is in your RX program. You should always post both programs.

I don't know if it will make any difference but I would have sizeof(data) rather than sizeof(Data_Package)

...R

Hi Robin,

Exactly 32 bytes are possible - I read that. No idea how I could know it’s 9 bytes now - sorry, my profession is (financial)auditor and have zero (proffesional) experience with electronics or programming. But, I do like it!

Please find below also the RX code: - In the meantime I will look into:

sizeof(data) rather than sizeof(Data_Package)

//==========CODING STARTS HERE==========

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

// Define the digital inputs
#define enA 2   
#define in1 4
#define in2 5
#define enB 3
#define in3 6
#define in4 7

int led_pin = 10;


RF24 radio(8, 9);   // nRF24L01 (CE, CSN)

const byte address[6] = "00001";
unsigned long lastReceiveTime = 0;
unsigned long currentTime = 0;

// Max size of this struct is 32 bytes
struct Data_Package {
byte j1PotX;
byte j1PotY;
//byte j1Button;
//byte j2PotX;
//byte j2PotY;
//byte j2Button;
  byte pot1;
//byte pot2;
  byte tSwitch1;
  byte tSwitch2;
  byte button1;
  byte button2;
  byte button3;
  byte button4;
};

Data_Package data; //Create a variable with the above structure

int  xAxis, yAxis;
int motorSpeedA = 0;
int motorSpeedB = 0;
int headlights;
int taillights;


void setup() {
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  pinMode(led_pin, OUTPUT);
  
  
  Serial.begin(9600);
  
  radio.begin();
  radio.openReadingPipe(0, address);
  //radio.setAutoAck(false);
  //radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening(); //  Set the module as receiver
  resetData();
}


void loop() {
  // Check whether we keep receving data, or we have a connection between the two modules
  currentTime = millis();
  if ( currentTime - lastReceiveTime > 1000 ) { // 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
  }
  xAxis = data.j1PotX;
  yAxis = data.j1PotY;

  // Y-axis used for forward and backward control
  if (yAxis < 110) {
    // Set Motor A backward
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
    // Set Motor B backward
    digitalWrite(in3, HIGH);
    digitalWrite(in4, LOW);
    // Convert the declining Y-axis readings for going backward from 110 to 0 into 0 to 255 value for the PWM signal for increasing the motor speed
    motorSpeedA = map(yAxis, 110, 0, 0, 255);
    motorSpeedB = map(yAxis, 110, 0, 0, 255);
    Serial.print(motorSpeedA);
    Serial.print("  ");
    Serial.println(yAxis);
  }
  else if (yAxis > 140) {
    // Set Motor A forward
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);
    // Set Motor B forward
    digitalWrite(in3, LOW);
    digitalWrite(in4, HIGH);
    // Convert the increasing Y-axis readings for going forward from 140 to 255 into 0 to 255 value for the PWM signal for increasing the motor speed
    motorSpeedA = map(yAxis, 140, 255, 0, 255);
    motorSpeedB = map(yAxis, 140, 255, 0, 255);
  }
  // If joystick stays in middle the motors are not moving
  else {
    motorSpeedA = 0;
    motorSpeedB = 0;
  }
  // X-axis used for left and right control
  if (xAxis < 110) {
    // Convert the declining X-axis readings from 140 to 255 into increasing 0 to 255 value
    int xMapped = map(xAxis, 110, 0, 0, 255);
    // Move to left - decrease left motor speed, increase right motor speed
    motorSpeedA = motorSpeedA - xMapped;
    motorSpeedB = motorSpeedB + xMapped;
    // Confine the range from 0 to 255
    if (motorSpeedA < 0) {
      motorSpeedA = 0;
    }
    if (motorSpeedB > 255) {
      motorSpeedB = 255;
    }
  }
  if (xAxis > 140) {
    // Convert the increasing X-axis readings from 110 to 0 into 0 to 255 value
    int xMapped = map(xAxis, 140, 255, 0, 255);
    // Move right - decrease right motor speed, increase left motor speed
    motorSpeedA = motorSpeedA + xMapped;
    motorSpeedB = motorSpeedB - xMapped;
    // Confine the range from 0 to 255
    if (motorSpeedA > 255) {
      motorSpeedA = 255;
    }
    if (motorSpeedB < 0) {
      motorSpeedB = 0;
    }
  }
  // Prevent buzzing at low speeds (Adjust according to your motors. My motors couldn't start moving if PWM value was below value of 70)
  if (motorSpeedA < 70) {
    motorSpeedA = 0;
  }
  if (motorSpeedB < 70) {
    motorSpeedB = 0;
  }
  analogWrite(enA, motorSpeedA); // Send PWM signal to motor A
  analogWrite(enB, motorSpeedB); // Send PWM signal to motor B

//Read if lights are on or off
headlights = data.tSwitch1;

  if((headlights) == HIGH){
    digitalWrite(led_pin, LOW);
  }
  if((headlights) == LOW){
    digitalWrite(led_pin, HIGH);
  }
}


void resetData() {
  // Reset the values when there is no radio connection - Set initial default values
  data.j1PotX = 127;
  data.j1PotY = 127;
//data.j2PotX = 127;
//data.j2PotY = 127;
//data.j1Button = 1;
//data.j2Button = 1;
data.pot1 = 1;
//data.pot2 = 1;
data.tSwitch1 = 1;
data.tSwitch2 = 1;
data.button1 = 1;
data.button2 = 1;
data.button3 = 1;
data.button4 = 1;
}

Thanks so much, your help is really appreciated.

Duindra:
Exactly 32 bytes are possible - I read that. No idea how I could know it's 9 bytes now

Count the bytes in the struct.

I can't immediately see anything wrong with your program. I suggest that you make a backup copy of the programs and the delete all the code in the RX program after this bit

  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
  }

and just write some code to print out the values that have been received.

ALSO reduce the frequency with which data is being sent by changing delay(20); to delay(1000);. You can always speed things up later but I suspect sending 5 (or at most 10) messages per second would be sufficient.

NB. If you slow down the transmission you must also alter the RX code that checks for a transmission failure. The simplest thing is to comment-out the call to resetData();

Separately, your code for sending data

radio.write(&data, sizeof(Data_Package));

does not check if the message is sent successfully. Look at the examples in my Tutorial.

...R