Controlling 2 servos using nrf24l01+pa+lna modules on Uno : Latency Issues.

Hello everyone,

I am using 2 servos, 2 nrf24l01+pa+lna modules, a joystick and 2 arduino uno boards.

I'm having latency issues and was wondering if i'm doing everything correctly or as efficient as possible. It all works at the moment......... but my servos seem to be receiving my commands late/slow while a LED activated by a joystick button on receiver end happens instantly..

I am also supplying the 3.3v input pin through a capacitor for the antennas to work properly (as per google).

Its noticeably faster when using a single servo, and sending just a single int to the receiver.

When I try to send an int array containing X axis, Y axis, and button 1/0, it has almost a second latency to it. The button on the joystick is lighting a LED on the receiver end pretty much instantly. The servos, however, have at least a second of delay to them when the joystick is moved.

Here is the latest version of my code, thanks for all your help!

Transmitter:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); // CE, CSN    
const uint64_t pipe = 0xE8E8F0F0E1LL;

int x_key = A0;                                               
int y_key = A1; 
int sw_key = A2;
                                              
int x_pos;
int y_pos;
int sw;

boolean echo = 0; //Serial output
unsigned long previousMillis = 0;        // will store last time LED was updated

const long interval = 10; 

void setup() {
  pinMode(sw_key, INPUT);
  pinMode (x_key, INPUT) ;                     
  pinMode (y_key, INPUT) ;  
  Serial.begin(9600);
  radio.begin();                  //Starting the Wireless communication
  //radio.setRetries(15, 15);
  radio.openWritingPipe(pipe); //Setting the address where we will send the data
  //radio.powerUp();
  //radio.setDataRate(RF24_1MBPS);
  //radio.enableDynamicPayloads();
  radio.setPALevel(RF24_PA_MIN);  //You can set it as minimum or maximum depending on the distance between the transmitter and receiver.
  radio.stopListening();          //This sets the module as transmitter

}


void loop() {

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
    
    x_pos = analogRead (x_key) ; 
    x_pos = map(x_pos, 0, 1023, 0, 180);
    y_pos = analogRead (y_key) ;
    y_pos = map(y_pos, 0, 1023, 0, 180);
    sw = analogRead (sw_key);
    
    int pos[3] = {x_pos, y_pos, sw};//data to send
    radio.write(&pos, sizeof(pos));
  
    if (echo) {
      Serial.print(pos[0]);
      Serial.print(',');
      Serial.print(pos[1]);
      Serial.print(',');
      Serial.println(pos[2]);
    }
  }
}

Receiver:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>
Servo servoX;
Servo servoY;
RF24 radio(9, 10); // CE, CSN

const uint64_t pipe = 0xE8E8F0F0E1LL;

int servoX_pin = 5;
int servoY_pin = 4;

int pos[3]; //expects a 3 int item array

int x_pos ; //joystick x
int x_pos_s; //servo x
int y_pos ; //joystick y
int y_pos_s; //servo y
int sw; //joystick button
int mid = 92; //mid point
int tol = 2; //tolerance
boolean echo = 0; //Serial output

void setup() {
  pinMode(6, OUTPUT);
  Serial.begin(9600);
  radio.begin();
  servoX.attach (servoX_pin ) ; 
  servoY.attach (servoY_pin ) ; 
  radio.openReadingPipe(1, pipe);   //Setting the address at which we will receive the data
  radio.setPALevel(RF24_PA_MIN);       //You can set this as minimum or maximum depending on the distance between the transmitter and receiver.
  radio.startListening();              //This sets the module as receiver
}
void loop(){
  if (radio.available()) {

    radio.read(&pos, sizeof(pos));
    
    x_pos = pos[0];
    x_pos_s = servoX.read();
    
    y_pos = pos[1];
    y_pos_s = servoY.read();

    sw = pos[2];
    
    if (echo){
      Serial.print(x_pos);
      Serial.print(',');
      Serial.println(y_pos);
      //Serial.print(',');
      //Serial.println(sw);
    }
    
    //servoX.write(x_pos);
    //servoY.write(y_pos);
    
    if (x_pos > mid+tol){
      servoX.write(x_pos_s+1);
      //delay(1);
      
    }
    else if (x_pos < mid-tol){
      servoX.write(x_pos_s-1);
      //delay(1);
      
    }
    else {
      servoX.write(mid);
      //delay(1);
      }
    
    
    if (y_pos > mid+tol){
      servoY.write(y_pos_s+1);
      //delay(1);
      
    }
    else if (y_pos < mid-tol){
      servoY.write(y_pos_s-1);
      //delay(1);
      
    }
    else {
      servoY.write(mid);
      //delay(1);
    }
  
    if(sw == 0)  {
      digitalWrite(6, HIGH);
    }
    else if(sw != 0)  {
      digitalWrite(6, LOW);
    }
    //delay(15);
    
  }
  
}

Hi,
Welcome to the forum.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html .

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

I am also supplying the 3.3v input pin through a capacitor for the antennas to work properly (as per google).

A assume the capacitor is across the 3.3V and gnd at the NRF pins?

Thanks.. Tom.. :slight_smile:

Hi Tom thank you for you prompt reply!

Here is a link to my Tinkercad sketch.

I've also attached PNG images along with this post.

...and yes my capacitors are on the 3.3v to ground going to the nrf module. The capacitor rating is 4.7uf 50v (..i might need to choose a lower voltage rating capacitor since its utilizing less than 10%).

Transmitter:
Arduino Uno
nrf24l01+pa+lna
joystick with button
4.7uf 50v Cap

Receiver:
Arduino Uno
nrf24l01+pa+lna
2 servos
LED
1k resistor
4.7uf 50v Cap

You seem to be sending data with an interval of 10 millisecs. To my mind that is much too short and everything will probably be overwhelmed with new data. Try increasing the interval to 200 millisecs (i.e. 5 times per second). That should be more than sufficient for the ability of servos to react.

Also, why have you all the IF tests in your receiver. Why not just send to the receiver the values needed for the servos and then receiver can just implement them without thought. For example

radio.read(&pos, sizeof(pos));
servoX.write(pos[0]);
servoY.write(pos[1]);
digitalWrite(6, pos[2]);

...R