NRF24L01+ only working when connected via USB

I haven't had much luck in my past, but I decided to pull out my NRF24L01+ chips again the other day and give it another go, and I am now having much more luck - I actually have them communicating correctly! However I just hit a weird issue today and was hoping for some input. At the moment, the devices only communicate when connected to my PC via USB. The boards (both are perfboard setups with plug-ins for a Nano and the NRF) work when disconnected from the PC, but only SOMETIMES. When connected to the PC, they seem to work fine. Here are quick drawings of the setups.

I would like to be able to use the NRF set to MAX power for maximum range, but that seems to be when the issues come about. I haven't had any luck with MAX power working at all, and HIGH power is when I get the issue I am bringing about here. Is the USB somehow providing extra current or something? When I use MIN power, I can communicate with external power disconnected totally, but only for very short distances.

Will post programs as replies as they are too long to fit. (There are a few places in codes commented "Truncated for space" so that they would fit on the forum 9000 char limit. This is mostly repeats of code for additional buttons/LEDs and some test patterns that just digitalWrite the LEDs on and off. It shouldn't make a difference to the way the radios communicate but if it seems critical, please let me know)

/* This Sketch is for the Reciever */

const int baud = 9600;  //Serial baud rate
const bool startTest = true; //Run an LED test on startup?
const int rfCH = 120;    //Radio Channel

const int errorTol = 100; //How many errors to allow? (One per rfTimeout)
const int resetDelay = 1000; //How long to stay in error moe
const int KaReset = 30000; //After this, reset due to no new data

const int dlyXShort = 50;
const int dlyShort = 200;
const int dlyMid = 300;
const int dlyLong = 500;
const int dlyXLong = 1000;

//Includes
#include "Arduino.h"
#include <SPI.h>
#include <RF24.h>
#include <avr/wdt.h>

//Decalre Pins

const int led1 = 7;
const int led2 = 6;
const int led3 = 5;
const int led4 = 4;
const int led5 = 3;
const int ledCxn = A0;

//Storage
int data;
int dataOld = 9001;
int ackData;
int ackDataOld = 9001;
bool TxFlag = true;
int errorCount = 0;
bool rfCxn = false;

//Timing
unsigned long KaTimer = 0;


//Radio Stuff
RF24 radio(9, 10);
byte addresses[][6] = {"1Node","2Node"};

void setup()
{
//Pin Modes
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(led5, OUTPUT);
pinMode(ledCxn, OUTPUT);

//Set Initial LED States
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);
digitalWrite(led4, LOW);
digitalWrite(led5, LOW);
digitalWrite(ledCxn, LOW);

//Start Serial
Serial.begin(baud);
// Initiate the radio object
radio.begin();
// Set the transmit power to lowest available to prevent power supply related issues
radio.setPALevel(RF24_PA_HIGH);
// Set the speed of the transmission to the quickest available
radio.setDataRate(RF24_2MBPS);
// Use a channel unlikely to be used by Wifi, Microwave ovens etc
radio.setChannel(rfCH);

// Open a writing and reading pipe on each radio, with opposite addresses
radio.openWritingPipe(addresses[0]);
radio.openReadingPipe(1, addresses[1]);

//Run LED Test on startup?
if (startTest == true)
{ledTest();}

//Start Listening
radio.startListening();
}

void hardReset()
{
  Serial.println("");
  Serial.println("REBOOTING PLEASE WAIT");
  Serial.println("");
  wdt_disable();
  wdt_enable(WDTO_15MS);
  while (1) {}
}

void loop()
{
rxData();
setLEDs();
if (TxFlag == true)
  {txData();}
kaTiming();
}

void kaTiming()
{
if (millis() - KaTimer >= KaReset/2)
  {
  Serial.println("Caution! Halfway to Keepalive Reset!");
  }
if (millis() - KaTimer >= KaReset)
  {
  Serial.println("Keepalive reset activated... Resetting in 3s");
  delay(3000);
  hardReset();
  }
}

void rxData()
{
dataOld = data;

if ( radio.available())
  {
  while (radio.available())
    {
    radio.read( &data, sizeof(data));
    TxFlag = true;
    rfCxn = true;
    KaTimer = millis();
    }
//Serial Debug
Serial.print("Rx'd: ");
Serial.println(data);
  }
}

void txData()
{
//Stop listening so we can talk
radio.stopListening();
ackData = data+1000;
radio.write( &ackData, sizeof(ackData) );
TxFlag = false;

//Serial debug (data + 1000)
Serial.print("TX'd: ");
Serial.println(ackData);

// Now, resume listening so we catch the next packets.
radio.startListening();
}

void setLEDs()
{
//Connection LED
if (rfCxn == true)
  {
    digitalWrite(ledCxn, HIGH);
  }
  
int keep1 = digitalRead(led1);
int keep2 = digitalRead(led2);
int keep3 = digitalRead(led3);
int keep4 = digitalRead(led4);
int keep5 = digitalRead(led5);
switch (data) {
  case 0:
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
    digitalWrite(led4, LOW);
    digitalWrite(led5, LOW);
    break;
  case 1:
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
    digitalWrite(led4, LOW);
    digitalWrite(led5, HIGH);
    break;
  case 2:
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
    digitalWrite(led4, HIGH);
    digitalWrite(led5, LOW);
    break;
//Truncated for space, follows binary pattern
  case 31:
    digitalWrite(led1, HIGH);
    digitalWrite(led2, HIGH);
    digitalWrite(led3, HIGH);
    digitalWrite(led4, HIGH);
    digitalWrite(led5, HIGH);
    break;
  default:
    digitalWrite(led1, keep1);
    digitalWrite(led2, keep2);
    digitalWrite(led3, keep3);
    digitalWrite(led4, keep4);
    digitalWrite(led5, keep5);
    break;
}
};

void errorLoop()
{
Serial.println("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
Serial.println("                                     ");
Serial.println("ERROR DETECTED - Resetting soon...");
Serial.println("                                     ");
Serial.println("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
bool error = true;
unsigned long resetTimer = millis();
while (error == true)
  {
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
  digitalWrite(led3, LOW);
  digitalWrite(led4, LOW);
  digitalWrite(led5, LOW);
  delay(dlyXShort);
  digitalWrite(led1, HIGH);
  delay(dlyXShort);
  digitalWrite(led1, LOW);
  digitalWrite(led2, HIGH);
  delay(dlyXShort);
  digitalWrite(led2, LOW);
  digitalWrite(led3, HIGH);
  delay(dlyXShort);
  digitalWrite(led3, LOW);
  digitalWrite(led4, HIGH);
  delay(dlyXShort);
  digitalWrite(led4, LOW);
  digitalWrite(led5, HIGH);
  delay(dlyXShort);
  digitalWrite(led5, LOW);
  digitalWrite(led4, HIGH);
  delay(dlyXShort);
  digitalWrite(led4, LOW);
  digitalWrite(led3, HIGH);
  delay(dlyXShort);
  digitalWrite(led3, LOW);
  digitalWrite(led2, HIGH);
  delay(dlyXShort);
  digitalWrite(led2, LOW);
  digitalWrite(led1, HIGH);
  delay(dlyXShort);
  digitalWrite(led1, LOW);
    if (millis() - resetTimer > resetDelay)
      {
      hardReset();
      }
  }
};

void ledTest()
{
//Truncated for space
};
/* This Sketch is for the Transmitter */
const int baud = 9600;  //Serial baud rate
const int debounceDelay = 200; //Debounce buttons delay
const bool startTest = true; //Run an LED test on startup?
const int errorTol = 100; //How many errors to allow? (One per rfTimeout)

const int rfCH = 120;    //Radio Channel
const int rfTimeout = 100; //Timeout for radio listen
const int resetDelay = 3000; //How long to stay in error mode
const int keepaliveDur = 10000; //How often to send a keepalive packet

const int dlyXShort = 50;
const int dlyShort = 200;
const int dlyMid = 300;
const int dlyLong = 500;
const int dlyXLong = 1000;

//Includes
#include "Arduino.h"
#include <SPI.h>
#include <RF24.h>
#include <avr/wdt.h>

//Decalre Pins
const int btn1 = 2;
const int btn2 = 3;
const int btn3 = 4;
const int btn4 = 5;
const int btn5 = 6;
const int btn6 = 7;
const int btn7 = 8;

const int led1 = A3;
const int led2 = A4;
const int led3 = A5;
const int led4 = A2;
const int led5 = A1;
const int ledCxn = A0;

//Storage
int btn1State;
//Also btn2-7

int btn1Old;
//Also btn2-7

int led1State;
//Also led2-5, sync, clear

int led1Old;

//Also led2-5, sync, clear

int read1;
//Also 1-7

int data = 999;
int dataOld = 9002;
int dataRx;
bool TxFlag = true;
bool verifiedFlag = false;
bool KaFlag = false;
int errorCount = 0;
bool rfCxn = false;



//Timing
unsigned long lastDebounce1 = 0;
//Also 2-7
unsigned long keepaliveTimer = 0;

//Radio Stuff
RF24 radio(9, 10);
byte addresses[][6] = {"1Node", "2Node"};

void setup() {
//Pin Modes
pinMode(btn1, INPUT_PULLUP);
pinMode(btn2, INPUT_PULLUP);
pinMode(btn3, INPUT_PULLUP);
pinMode(btn4, INPUT_PULLUP);
pinMode(btn5, INPUT_PULLUP);
pinMode(btn6, INPUT_PULLUP);
pinMode(btn7, INPUT_PULLUP);

pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(led5, OUTPUT);
pinMode(ledCxn, OUTPUT);

//Set Initial LED States
digitalWrite(led1, LOW);
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);
digitalWrite(led4, LOW);
digitalWrite(led5, LOW);
digitalWrite(ledCxn, LOW);

//Start Serial
Serial.begin(baud);
// Initiate the radio object
radio.begin();
// Set the transmit power to lowest available to prevent power supply related issues
radio.setPALevel(RF24_PA_HIGH);
// Set the speed of the transmission to the quickest available
radio.setDataRate(RF24_2MBPS);
// Use a channel unlikely to be used by Wifi, Microwave ovens etc
radio.setChannel(rfCH);

// Open a writing and reading pipe on each radio, with opposite addresses
radio.openWritingPipe(addresses[1]);
radio.openReadingPipe(1, addresses[0]);

//Run LED Test on startup?
if (startTest == true)
{ledTest();}
}

void hardReset()
{
  Serial.println("");
  Serial.println("REBOOTING PLEASE WAIT");
  Serial.println("");
  wdt_disable();
  wdt_enable(WDTO_15MS);
  while (1) {}
};

void loop()
{
/*For Testing Only
led3State = HIGH;
led4State = HIGH;
End Testing*/
readButtons();
checkSync();
checkClear();
setLEDs();
setData();
if (TxFlag == true)
  {transmitData();}
if (verifiedFlag == false)
  {verifyData();}
keepalive();
};

void readButtons()
{
//Read buttons into locals
read1 = digitalRead(btn1);
read2 = digitalRead(btn2);
read3 = digitalRead(btn3);
read4 = digitalRead(btn4);
read5 = digitalRead(btn5);
read6 = digitalRead(btn6);
read7 = digitalRead(btn7);

//Check if pressed
if (read1 != btn1Old)
{
  lastDebounce1 = millis();
}
if (read2 != btn2Old)
{
  lastDebounce2 = millis();
}
if (read3 != btn3Old)
{
  lastDebounce3 = millis();
}
if (read4 != btn4Old)
{
  lastDebounce4 = millis();
}
if (read5 != btn5Old)
{
  lastDebounce5 = millis();
}
if (read6 != btn6Old)
{
  lastDebounce6 = millis();
}
if (read7 != btn7Old)
{
  lastDebounce7 = millis();
}

//Timing/Toggle 1
if ((millis() - lastDebounce1) > debounceDelay)
  {
  if (read1 != btn1State)
    {   
    btn1State = read1;
    if (btn1State == LOW)
      {
      led1State = !led1State;
      }
    }
  }
//Truncated for space, Timing/Toggle 2-7 follow same basic code as 1
};

void setLEDs()
{
//Connection LED
if (rfCxn == true)
{
  digitalWrite(ledCxn, HIGH);
}

//Write Outputs
digitalWrite(led1, led1State);
digitalWrite(led2, led2State);
digitalWrite(led3, led3State);
digitalWrite(led4, led4State);
digitalWrite(led5, led5State);

//Store
btn1Old = read1;
btn2Old = read2;
btn3Old = read3;
btn4Old = read4;
btn5Old = read5;
btn6Old = read6;
btn7Old = read7;
};

void checkSync()
{
if (syncState == true)
  {
  Serial.println("Sync Button Pressed... Setting TxFlag TRUE");
  syncState = false;
  TxFlag = true;
  }
};

void checkClear()
{
if (clearState == true)
  {
    Serial.print("Clearing all...");
    TxFlag = true;
    led1State = LOW;
    led2State = LOW;
    led3State = LOW;
    led4State = LOW;
    led5State = LOW;
    clearState = false;
    Serial.println(" DONE!");
  }
};

void setData()
{
dataOld = data;
int newData = 0;
  if (led5State == LOW && led4State == LOW && led3State == LOW && led2State == LOW && led1State == LOW)
    {newData = 0;}
  if (led5State == HIGH)
    {newData += 1;}
  if (led4State == HIGH)
    {newData += 2;}
  if (led3State == HIGH)
    {newData += 4;}
  if (led2State == HIGH)
    {newData += 8;}
  if (led1State == HIGH)
    {newData += 16;}
data = newData;

if (data != dataOld || KaFlag == true)
  {
  Serial.print("Data is new: ");
  Serial.println(data);
  TxFlag = true;
  verifiedFlag = false;
  keepaliveTimer = millis();
  if (KaFlag == true)
    {
    KaFlag = false;
    }
  }
else
  {
  TxFlag = false;
  }
};

void keepalive()
{
if (millis() - keepaliveTimer > keepaliveDur)
  {
  KaFlag = true;
  }
}


void transmitData()
{
radio.stopListening();
unsigned long ackTimer = millis();
if (!radio.write( &data, sizeof(unsigned char) ))
  {
   Serial.print("No acknowledgement of transmission, waiting ");
   Serial.print(rfTimeout);
   Serial.println("ms...");
   if (millis() - ackTimer > rfTimeout)
    {
    errorCount++;
    Serial.print("Still no ack, error count is now: ");
    Serial.println(errorCount);
    ackTimer = millis();
    if (errorCount >= errorTol)
      {
      Serial.println("Too many errors!");
      errorLoop();
      }
    }
  }
TxFlag = false;
radio.startListening();
unsigned long timeoutTimer = millis();
while ( ! radio.available() )
  {
    if (millis() - timeoutTimer > rfTimeout)
    {
   errorCount++;
    Serial.print("No response timeout, error count is now: ");
    Serial.println(errorCount);
    timeoutTimer = millis();
    if (errorCount >= errorTol)
      {        
      Serial.println("Too many errors!");
      errorLoop();
      }
    }
  }

  // Now read the data that is waiting for us in the nRF24L01's buffer
  radio.read( &dataRx, sizeof(dataRx) );

  // Show user what we sent and what we got back
  Serial.print("Tx'd: ");
  Serial.print(data);
  Serial.print(", Rx'd: ");
  Serial.println(dataRx);
};

void verifyData()
{
Serial.print("Verifying...");

if (dataRx >= 1000 && dataRx <= 2000)
  {
  errorCount = 0;
  Serial.print("Success! ");
  Serial.print(dataRx);
  Serial.print(" is valid! Error count: ");
  Serial.println(errorCount);
  verifiedFlag = true;
  rfCxn = true;
  }
else if (dataRx == 0)
  {
  errorCount += 20;
  Serial.print("Unknown! ");
  Serial.print(dataRx);
  Serial.print(" is a null value! Error count: ");
  Serial.println(errorCount);
  verifiedFlag = true;
  rfCxn = false;
  }
else
  {
  errorCount++;
  Serial.print("Failure! ");
  Serial.print(dataRx);
  Serial.print(" is NOT valid! Error count: ");  
  Serial.println(errorCount);
  verifiedFlag = false;
  rfCxn = false;
  }

  if (errorCount >= errorTol)
    {
    errorLoop();
    } 
  
}

void errorLoop()
{

Serial.println("ERROR DETECTED - Resetting soon...");
bool error = true;
unsigned long resetTimer = millis();
while (error == true)
  {
 //Truncated for space
    if (millis() - resetTimer > resetDelay)
      {
      hardReset();
      }
  }
}

void ledTest()
{
//Truncated for space
};

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

Using the code from the tutorial on the same hardware, things seem to work fine. Here is a screenshot of the COM windows. This is the result when connected to the external 12v power source as I described in my initial post (with the 12v fed to the arduino on Vin/GND and also to the 3.3v linear regulator and then to the NRF).

I planned to do some rewriting of the code anyway, so I will use your tutorial as the starting point and make changes one at a time to see where that gets me. I have already added added
radio.setPALevel(RF24_PA_MAX); to the code, and the tutorial code still works okay, so that should be a good sign. My problems didn't originate until I started trying to put some distance between the units, though, so hopefully things work better this time. I may have just tried to move too quickly with additional features in my first iteration.

Fyre_Foxe:
Using the code from the tutorial on the same hardware, things seem to work fine.

Thanks for the update.

For the future please don't post pictures of text, just copy and paste the text - it will be much easier to read.

...R

Robin2:
..please don't post pictures of text..

Sure, sorry about that! Just wanted to show the side-by-side of the two device communications for "proof" that it was working.

Interestingly, when I pare down my original sketches to just process the buttons inputs and set the LED outputs (getting rid of my previous attempts at error detection/auto reset) and use the code from your tutorial as the radio communication (versus the previous example code from someone else that was being used) I am still encountering the same issue in that, it works great when connected to both external power AND via USB to the serial monitor. However, if I unplug the devices from USB they stop communicating. I have, of course, also tried unplugging them totally, and plugging in only the external power, in different order (RX or TX device first, resetting one or the other first, etc) and I still can't seem to get them to communicate.... Until I plug them back into the PC and then they work. Suggestions?

Fyre_Foxe:
I am still encountering the same issue in that, it works great when connected to both external power AND via USB to the serial monitor.

You need to post that version of your pair of programs.

...R

Unfortunately, I've hit the point where everything just totally stopped working and I've basically just given up. May resume some other time, but at this point any progress seems unlikely as when hardware just stops working entirely for no reason, then it is probably my fault for being too dumb to make it work. The only thing I can think is that from plugging in/unplugging the NRF moduels too many times, I've already worn out connections and/or broken some solder joints or something so I would need to completely start over and make new boards and everything at this point.

Fyre_Foxe:
Unfortunately, I've hit the point where everything just totally stopped working and I've basically just given up.

Is that true even with the programs from my tutorial?

...R