RC with NRF24L01, dropouts when message too fast?

I’m putting together a project, a tracked RC, with a 6 DOF arm on top, and was hoping someone could give some help with my use of the NRF24L01.
so far i’ve got 2 arduino Nano clones communicating wirelessly (uni directionally) to drive on servo (the claw) using a 50k potentiometer.
the servo is driven from an Adafruit 16 channel servo driver

So far the whole system works, except if you turn the potentiometer too quickly, in which case control drops out, until you power cycle the receiver.

I’m not sure if its just a flaky transmit/receiver, i’m using these

or maybe the library. is there some checks i need to include for auto reconnection, or to change the max transmission rate?

Transmitter code

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

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

//define our potentiometers
int pot1 = A1;//claw
/*
int pot2 = A2;//clawturn
int pot3 = A3;//claw_wrist
int pot4 = A4;//elbow
int pot5 = A5;//base_angle
int pot6 = A6;//base_turn
*/
//variable to read the values from the analog pin (potentiometers)
int valPot1;// claw
/*
int valPot2;//clawturn
int valPot3;//claw_wrist
int valPot4;//elbow
int valPot5;//base_angle
int valPot6;//base_turn
*/

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

void loop()
{
  radio.stopListening();

  //claw
  valPot1 = analogRead(pot1);
  valPot1 = map (valPot1, 0, 1023, 170, 360); //scale it to use it with the servo (value between 0 and 180)
  radio.write(&valPot1, sizeof(valPot1));
  
/*  //clawturn
  valPot2 = analogRead(pot2);
  valPot2 = map (valPot2, 0, 1023, 100, 510); //scale it to use it with the servo (value between 0 and 180)
  radio.write(&valPot2, sizeof(valPot2));
  Serial.println(valPot2);

  //claw_wrist
  valPot3 = analogRead(pot3);
  valPot3 = map (valPot3, 0, 1023, 110, 440); //scale it to use it with the servo (value between 0 and 180)
  radio.write(&valPot3, sizeof(valPot3));
  Serial.println(valPot3);

  //elbow
  valPot4 = analogRead(pot4);
  valPot4 = map (valPot4, 0, 1023, 80, 450); //scale it to use it with the servo (value between 0 and 180)
  radio.write(&valPot4, sizeof(valPot4));
  Serial.println(valPot4);

  //base_angle
  valPot5 = analogRead(pot5);
  valPot5 = map (valPot5, 0, 1023, 470, 80); //scale it to use it with the servo (value between 0 and 180)
  radio.write(&valPot5, sizeof(valPot5));
  Serial.println(valPot5);

  //base_turn
  valPot6 = analogRead(pot6);
  valPot6 = map (valPot6, 0, 1023, 520, 70); //scale it to use it with the servo (value between 0 and 180)
  radio.write(&valPot6, sizeof(valPot6));
  Serial.println(valPot6);
*/
}

Receiver Code

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

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

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

//variable to read the values from the analog pin (potentiometers)
int valPot1;// claw
/*
int valPot2 = 100;//clawturn
int valPot3 = 0;//claw_wrist
int valPot4;//elbow
int valPot5;//base_angle
int valPot6;//base_turn
*/
void setup()
{
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
  pwm.begin();
  pwm.setPWMFreq(60);  // Analog servos run at ~60 Hz updates
  delay(10);
}


void loop()
{
  radio.startListening();
  if (radio.available()) {
     while (radio.available()) {

        //claw
        radio.read(&valPot1, sizeof(valPot1));
        pwm.setPWM(0, 0, valPot1);
        Serial.println(valPot1);
/*
        //claw_turn
          radio.read(&valPot2, sizeof(valPot2));
          pwm.setPWM(1, 0, valPot2);
        Serial.println(valPot2);

        //claw_wrist
        radio.read(&valPot3, sizeof(valPot3));
        pwm.setPWM(2, 0, valPot3);
        Serial.println(valPot3);

        //elbow
        radio.read(&valPot4, sizeof(valPot4));
        pwm.setPWM(3, 0, valPot4);
        Serial.println(valPot4);
        
        //base_angle
        radio.read(&valPot5, sizeof(valPot5));
        pwm.setPWM(4, 0, valPot5);
        Serial.println(valPot5);
        
        //base_turn
        radio.read(&valPot6, sizeof(valPot6));
        pwm.setPWM(5, 0, valPot6);
        Serial.println(valPot6);        
*/     }
  }
}

Have a look at this Simple nRF24L01+ Tutorial

In your Rx program you don't need the line

while (radio.available()) {

with an nRF24 if there is any data available the entire message will be available. It is not like Serial where the data comes one byte at a time.

If this was my project I would arrange for the Master (Tx) to send a message at regular intervals - say every 100 millisecs - whether the data has changed or not. That way if messages fail to arrive the Slave can know that there is a communication problem.

I find it less confusing to use the terms "Master" and "Slave" because the nRF24 is a transceiver.

...R

thanks, i checked out your examples and tried breaking out the send to a seperate method, so it wasn't called so constantly.
unfortunately had the same issue, slow movements of potentiometers are fine, but anything fast seems to kill comms.
might try without the multi channel pwm board, to see if i can isolate the issue.
are some nRF24L01 better than others?

unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 250;

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

void loop()
{
 radio.stopListening();

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

void send(){
 //claw
 valPot1 = analogRead(pot1);
 valPot1 = map (valPot1, 0, 1023, 190, 330); //scale it to use it with the servo (value between 0 and 180)
 radio.write(&valPot1, sizeof(valPot1));

I don't see anything in the code that affects the rate of transmission, so whether you move the potentiometer fast or slow should make no difference.
So I would guess that it's a problem with your circuit. Loose connection? How firmly is the pot attached to whatever it's attached to?
Or changing the pot fast is somehow affecting the power supply to the nRF24? How are your radios powered anyway?

at the TX end one (twist) potentiometer is mounted directly into a breadboard, the other (slider) is connected by socket-ended hookup wire, the potentiometers, TX NRF24 and TX nano are all powered from a 5v breadboard powersupply

i've wanted to airgap the nano's so i have separate power supplies per breadboard, and one breadboard/psu per arduino.

i've just now taken the adafruit pwm driver out of the mix (driving servo directly from RX arduino), but found the same issue, leaning towards knock off hardware not cutting it

I am inclined to agree with @bms001. This sounds like a hardware problem rather than a software problem. A loose connections seems the most likely culprit.

Have you got 10µF capacitors on the power supplies for your nRF24 modules?

Post the latest versions of your programs.

Are you using the TMRh20 version of the RF24 library as referenced in my Tutorial?

...R

Try commenting out the print lines in the transmitter. See if that helps.

Paul

Robin2:
I am inclined to agree with @bms001. This sounds like a hardware problem rather than a software problem. A loose connections seems the most likely culprit.

Have you got 10µF capacitors on the power supplies for your nRF24 modules?

Post the latest versions of your programs.

Are you using the TMRh20 version of the RF24 library as referenced in my Tutorial?

…R

i’ve made sure the breadboard connections are solid, i’ll check the solders on the NRF’s aren’t frosty when i get home.

for now the code is
TX

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

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

//define our potentiometers
int pot1 = A1;//claw
int pot2 = A2;//clawturn
/*
int pot3 = A3;//claw_wrist
int pot4 = A4;//elbow
int pot5 = A5;//base_angle
int pot6 = A6;//base_turn
*/
//variable to read the values from the analog pin (potentiometers)
int valPot1;// claw
int valPot2;//clawturn
/*
int valPot3;//claw_wrist
int valPot4;//elbow
int valPot5;//base_angle
int valPot6;//base_turn
*/

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

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

void loop()
{
  radio.stopListening();

  //claw
  valPot1 = analogRead(pot1);
  valPot1 = map (valPot1, 0, 1023, 35, 95); //scale it to use it with the servo (value between 190 and 330)
  radio.write(&valPot1, sizeof(valPot1));
/*  
  //clawturn
  valPot2 = analogRead(pot2);
  valPot2 = map (valPot2, 0, 1023, 100, 510); //scale it to use it with the servo (value between 0 and 180)
  radio.write(&valPot2, sizeof(valPot2));
  Serial.println(valPot2);

  //claw_wrist
  valPot3 = analogRead(pot3);
  valPot3 = map (valPot3, 0, 1023, 110, 440); //scale it to use it with the servo (value between 0 and 180)
  radio.write(&valPot3, sizeof(valPot3));
  Serial.println(valPot3);

  //elbow
  valPot4 = analogRead(pot4);
  valPot4 = map (valPot4, 0, 1023, 80, 450); //scale it to use it with the servo (value between 0 and 180)
  radio.write(&valPot4, sizeof(valPot4));
  Serial.println(valPot4);

  //base_angle
  valPot5 = analogRead(pot5);
  valPot5 = map (valPot5, 0, 1023, 470, 80); //scale it to use it with the servo (value between 0 and 180)
  radio.write(&valPot5, sizeof(valPot5));
  Serial.println(valPot5);

  //base_turn
  valPot6 = analogRead(pot6);
  valPot6 = map (valPot6, 0, 1023, 520, 70); //scale it to use it with the servo (value between 0 and 180)
  radio.write(&valPot6, sizeof(valPot6));
  Serial.println(valPot6);
*/
}

RX

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

//define our servos
Servo servo1;

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

//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

//variable to read the values from the analog pin (potentiometers)
int valPot1;// claw
int valPot2;//clawturn
/*
int valPot3 = 0;//claw_wrist
int valPot4;//elbow
int valPot5;//base_angle
int valPot6;//base_turn
*/
void setup()
{
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
  //pwm.begin();
  //pwm.setPWMFreq(60);  // Analog servos run at ~60 Hz updates
  delay(10);
  servo1.attach(3);// claw grab
  servo1.write(70); //define servo start position
}


void loop()
{
  radio.startListening();
  if (radio.available()) {
//     while (radio.available()) {

        //claw
        radio.read(&valPot1, sizeof(valPot1));
        servo1.write(valPot1);

 /*       
        pwm.setPWM(0, 0, valPot1);
        Serial.println(valPot1);

        //claw_turn
        radio.read(&valPot2, sizeof(valPot2));
        pwm.setPWM(1, 0, valPot2);
        Serial.println(valPot2);

        //claw_wrist
        radio.read(&valPot3, sizeof(valPot3));
        pwm.setPWM(2, 0, valPot3);
        Serial.println(valPot3);

        //elbow
        radio.read(&valPot4, sizeof(valPot4));
        pwm.setPWM(3, 0, valPot4);
        Serial.println(valPot4);
        
        //base_angle
        radio.read(&valPot5, sizeof(valPot5));
        pwm.setPWM(4, 0, valPot5);
        Serial.println(valPot5);
        
        //base_turn
        radio.read(&valPot6, sizeof(valPot6));
        pwm.setPWM(5, 0, valPot6);
        Serial.println(valPot6);        
//     }
*/  }
}

i haven’t yet chucked a Cap across the power into the NRF, a 10u 25V electrolytic will do the trick here, right?

Have you tried using the code in one of the examples in my tutorial?

Have you a spare nRF24 that you could try in case one of them is faulty?

…R

i soldered a 16vcd 10uf cap between + and - on each NRF, and rewired all the jumpers, but it’s not made any difference, the TX/RX still drops out when the potentiometre is changed too rapidly.

Robin2:
Have you tried using the code in one of the examples in my tutorial?

i haven’t becaue looking in the tutorial, it seemed to be that the code contained would either work or not, whereas my project seems to work until the knob is turned too rapidly back and forward (can move servo as much as i want, as long as its sloooooowly)
if you think it’ll help, i’ll try it.

Robin2:
Have you a spare nRF24 that you could try in case one of them is faulty?

i bought them as a set of 3, so i should have a spare around here somwhere. will swap it out for TX, and if it still fails for RX

smerwin:
if you think it'll help, i'll try it.

At this stage it can't do any harm. My tutorial code has worked for several Forum readers as well as for me.

If you try my code and the symptoms continue then I will be confident that it is a hardware problem.

...R