NRF24L01 Causes servo to vibrate

I have a RC car project with Arduino, NRF24L01 & Servo + DC motor (driver). The problem is when I send data to NRF through remote (Arduino, NRF24L01, 2 joystick pots + LCD), the servo vibrates randomly. When there's no data, servo stays calm. I checked servo through multiple ways, servo is OK, wiring is OK, signals are sent and received properly both on Servo & NRFs. But this random vibration is annoying and not good for turning the car. When I bind NRF interrupt with Arduino, the problems seems increased.

I'm also curious if NRF signal pulses cause servo to do annoying vibrations.

  • I've used 2x Arduino pro mini 5V, 16MHz.
  • Arduinos are supplied by 1A, 3.7 (Battery) to 5V boost converter.
  • I've already added 3x 470uF capacitor with both Arduinos' power supplies.
  • Motor driver powered directly by battery.
  • NRFs powered by 3.3V linear regulators and .
  • 10uf and 100nf capacitor with both NRFs.

Remote is:

  • Arduino pro mini
  • 0.96" OLED
  • Joystick Potentiometers (I've used their custom range because of some mechanical issue).
  • NRF
  • Switch to turn ON lights of car remotely.

RC Car contains:

  • Arduino Pro Mini
  • Servo
  • Motor Driver (not powered by 5V but through 3.7V Battery).
  • LED Lights.

Transmitter Code:

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

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);      // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Res = 12
RF24 radio(6, 8);  // CE, CSN
int Stearing = A0;
int Throttle = A1;
int BatteryP = A2;
int HLight = 3;
//int Hornp = 4;

int Temp[1];
int Text[1];
char* label = "EV";    // some custom gauge labels
const byte addresses [][6] = {"62281", "62282"};

int speedread, speedo, Turn;
int pHLights, HLights, BLights;
int pHorn, Horn;
int BatteryC;
int BatteryR;

int Batery = 1023;
int Batmin = 1023;
long average = 0;

int NeedleAngle=0;
int xmax=128;                                   // max length x-axis
int ymax=62;                                    // max length y-axis
int xcenter=xmax/2;                             // center of x-axis
int ycenter=ymax/2+10;                          // center of y-axis
int arc=ymax/2;                           
int p, w, m,a = 10;

long fgh, timei, Average;
char Gear = 0;
u8g_uint_t xx = 0;

// ---------------------------------------------------------------------------------------------------------
// ------------------------------------------------------ Setup() ------------------------------------------

void setup() {
  
  pinMode (Stearing, INPUT);                     
  pinMode (Throttle, INPUT);
  pinMode (BatteryP, INPUT);
  pinMode (HLight, INPUT);
  //pinMode (Hornp, INPUT);

  Serial.begin(9600);

  //Wire.begin(); Wire.setClock(1000000);
  u8g.setFont(u8g_font_chikita);
  u8g.setColorIndex(1);

  // assign default color value
  if ( u8g.getMode() == U8G_MODE_R3G3B2 )         { u8g.setColorIndex(255); }// white
  else if ( u8g.getMode() == U8G_MODE_GRAY2BIT )  { u8g.setColorIndex(3); }// max intensity
  else if ( u8g.getMode() == U8G_MODE_BW )        { u8g.setColorIndex(1); }// pixel on
  else if ( u8g.getMode() == U8G_MODE_HICOLOR )   { u8g.setHiColorByRGB(255,255,255); }

  radio.begin();
  radio.openWritingPipe(addresses[1]);
  radio.openReadingPipe(1, addresses[0]);
  radio.startListening();
  
}

// --------------------------------------------------------------------------------------------------------
// ------------------------------------------------- Functions() ------------------------------------------

void WirelessWrite() {
  
  if ( pHLights == HLights /*&& pHorn == Horn*/ && speedread == 500 && Turn <= 520 && Turn >= 500 ) {}
  else {
    
    radio.stopListening();
    fgh = millis();
    
    Temp[0] = HLights;    
    //Serial.print(Temp[0]);Serial.print("   ");
    radio.write(&Temp, sizeof(Temp));  //const char text[] = "Hello World"; HLights, Horn +2, speedread+4, Turn +2000};   
    //Temp[0] = Horn +2;
    //Serial.print(Temp[0]);Serial.print("   ");
    //radio.write(&Temp, sizeof(Temp));
    Temp[0] = speedread +1000;
    //Serial.print(Temp[0]);Serial.print("   ");
    radio.write(&Temp, sizeof(Temp));
    Temp[0] = Turn + 3000;
    Serial.println(Temp[0]);
    radio.write(&Temp, sizeof(Temp));
    
    pHLights  = HLights;
    pHorn = Horn;
    radio.startListening();
    timei = millis() - fgh;
  }

}

// -------------------------------------------------

void Lights() {
  
  if (digitalRead(HLight) == HIGH) { HLights = 4200; }
  else if (digitalRead(HLight) == LOW) { HLights = 4500; }
}

/*void CHorn() {
  if (digitalRead(Hornp) == HIGH) { Horn = 1; }
  else if (digitalRead(Hornp) == LOW) { Horn = 0; }
}*/

// -------------------------------------------------

void Battery() {
  
  for (int cc = 0; cc < 50; cc++) {
    Batery = analogRead(BatteryP);
    average = average + Batery; }
  average = average/50;

  /*if (average < Batmin){ */Batery = average;/* Batmin = average; }
  else { Batery = Batmin; }*/

  BatteryR = map(Batery, 738, 865, 0, 100);
  
  u8g.setFont(u8g_font_unifont_76);  
  
  if (digitalRead(HLight) == HIGH) { u8g.drawStr(30,62, "\x20"); } // Show Lights Symbol

  if (timei < 20) { u8g.drawStr(85,62, "\x4B"); }      

  u8g.drawStr(2,64, "\x9F");        //show car symbol at right side 
  
  //u8g.setFont(u8g_font_cursor);   //show driver symbol at left side
  u8g.drawStr(113,64, "\x75");

  u8g.setFont(u8g_font_chikita);    //show remote battery percentage
  //u8g.setFont(u8g_font_courR08);
  u8g.setPrintPos(1,29);           
  u8g.print(BatteryR);
  u8g.print("%");
  
  u8g.setPrintPos(110,29);     //show car battery percentage      
  u8g.print(BatteryC);
  u8g.print("%");


  //u8g.setColorIndex(1);
  u8g.drawFrame(2,5,5,4);     //remote battery drawing
  u8g.drawFrame(1,8,7,12);

  u8g.drawFrame(117,5,5,4);     //car battery drawing
  u8g.drawFrame(116,8,7,12);

  u8g.setColorIndex(0);
  u8g.drawHLine(3,8,3);
  u8g.drawHLine(118,8,3);

  u8g.setColorIndex(1);
  
  if (BatteryR>20){u8g.drawBox(3,16,3,2);            //show battery levels of remote
  if (BatteryR>40){u8g.drawBox(3,13,3,2);
  if (BatteryR>68){u8g.drawBox(3,10,3,2);
  if (BatteryR>90){u8g.drawLine(4,7,4,8);
  }}}}
  if (BatteryC>20){u8g.drawBox(118,16,3,2);          //show battery levels of car
  if (BatteryC>40){u8g.drawBox(118,13,3,2);
  if (BatteryC>68){u8g.drawBox(118,10,3,2);
  if (BatteryC>90){u8g.drawLine(119,7,119,8);
  }}}}
}

// -------------------------------------------------

void Engine() { //We create a function which control the direction and speed
  speedread = 0;
  speedo = 0;
  
  speedread = analogRead(Throttle);
  
  if (speedread>682){speedread = 682;}
  if (speedread<345){speedread = 345;}
  
  if (speedread<540 && speedread>460){ speedread = 500; }
  else if (speedread>540){ speedo = map(speedread,525,682,0,185); }
  else if (speedread<460){ speedo = map(speedread,345,490,100,0); Gear = 'R'; }
  speedo = abs(speedo); // making speedometer speed +ve
}

// -------------------------------------------------

void Turning() {
  Average = 0;
  for(int hj = 0; hj < 50; hj++) {
    Turn = analogRead(Stearing);
    Average = Average + Turn;
  }
  Turn = Average / 50;
  //Serial.println(Turn);
  /*if (Turn > 720){} else if (Turn<295){}
  else if (Turn > 707){Turn = 707;}
  else if (Turn < 307){Turn = 307;}
  Turn = map(Turn,307,707,60,120);
  if (Turn>85 && Turn <95){Turn = 90;}*/
}

// -------------------------------------------------

void Gearing() {
  Gear = 0;
  if      (speedread>540 && speedread<550){ Gear = '1'; }
  else if (speedread>550 && speedread<570){ Gear = '2'; }
  else if (speedread>570 && speedread<608){ Gear = '3'; }
  else if (speedread>608 && speedread<650){ Gear = '4'; }
  else if (speedread>650)                 { Gear = '5'; }
}

// --------------------------------------------------------------------------------------------------------

void Needle() {
  
  p = speedo;
  p+=a;     
  if( p > 1023) a= -10;
  else if( p < 0 ) a = 10;
  
  xx = map(p,0,185,0,85);          // 135 = zero position, 180 = just before middle, 0 = middle, 45 = max
  if (xx < 45){xx = xx+135; }     // positie correctie
  else {xx = xx-45; }
}

// --------------------------------------------------------------------------------------------------------

void Speedometer(uint8_t NeedleAngle) {
  
  u8g.drawCircle(xcenter,ycenter,arc+6, U8G_DRAW_UPPER_RIGHT); // draw border of the gauge
  u8g.drawCircle(xcenter,ycenter,arc+4, U8G_DRAW_UPPER_RIGHT);
  u8g.drawCircle(xcenter,ycenter,arc-9, U8G_DRAW_UPPER_RIGHT);
  u8g.drawCircle(xcenter,ycenter,arc+6, U8G_DRAW_UPPER_LEFT);
  u8g.drawCircle(xcenter,ycenter,arc+4, U8G_DRAW_UPPER_LEFT);
  u8g.drawCircle(xcenter,ycenter,arc-9, U8G_DRAW_UPPER_LEFT);
  u8g.drawDisc(xcenter, ycenter, 5, U8G_DRAW_UPPER_LEFT);
  u8g.drawDisc(xcenter, ycenter, 5, U8G_DRAW_UPPER_RIGHT);
  
  float x1=sin(2*NeedleAngle*2*3.14/360);              // needle position  (draw the needle)
  float y1=cos(2*NeedleAngle*2*3.14/360);
  u8g.drawLine(xcenter, ycenter, xcenter+arc*x1, ycenter-arc*y1);

  u8g.setFont(u8g_font_chikita);
  u8g.drawStr( 20, 42, "0");    // show scale labels
  u8g.drawStr( 25, 18, "30");
  u8g.drawStr( 60, 14, "90");
  u8g.drawStr( 95, 18, "145");
  u8g.drawStr( 105, 42, "185");

  u8g.drawLine(20,43,32,43);  //show line marks at guage labels
  u8g.drawLine(96,43,108,43);
  u8g.drawLine(64,1,64,7);
  u8g.drawLine(34,11,41,18);
  u8g.drawLine(87,18,94,11);
  
  u8g.setFont(u8g_font_6x13O);    //show "EV" on guage
  u8g.setPrintPos(59,34);           
  u8g.print(label);   //EV

  //u8g.setFont(u8g_font_6x13);   //show gear no.
  u8g.setPrintPos(62,60);
  u8g.print(Gear);
  if (Gear == 0) { u8g.print("N");}
  u8g.drawCircle(64, 55, 8, U8G_DRAW_ALL);
  
  /*u8g.setFont(u8g_font_profont22);    //show speed digitally           
  u8g.setPrintPos(50,63);
  if (speedo<10){ u8g.print("0"); }// leading 0 when value less than 10
  if (speedo){ u8g.setPrintPos(50,63); }// position at 100%
  u8g.print(speedo);*/
  
}

// ---------------------------------------------------------------------------------------------------
// ------------------------------------------------- Loop() ------------------------------------------

void loop() {
  
  Needle();
  Gearing();
  
  u8g.firstPage();                  // Picture loop start
  
  do {
  
    if (radio.available()) {
      radio.read(&Text[0], sizeof(Text));
      BatteryC = Text[0];  }
    
    Speedometer(xx);
    Battery();
    Lights();
    //CHorn();
    Engine();
    Turning();  
    WirelessWrite();  
    //Serial.println(timei);

  } while( u8g.nextPage() );
  
}`Preformatted text`

Receiver Code:

#iinclude <SPI.h>
#include <RF24.h>
#include <Servo.h>
#include <nRF24L01.h>
//#include <RF24_config.h>


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

RF24 radio(7, 8);  // CE, CSN
int BatteryP = A0;
int mservo = 10;
int EngSpe = 5; // Motor input 1
int EngDir = 4; // Motor input 2
int BLights = 3; //with PWM
int HLights = 6;
int tesl = 1;
int BlinLight = A1;
//int Hornp = ;
Servo Stear;
long curt = 0;
int ll = 0;

//const byte address[6] = "62281";//address through which two modules communicate.
const byte addresses [][6] = {"62281", "62282"};
int Temp[1];
int Text[1];
int speedR, speedRN, speedF, speedFN, speedread = 500;
int BatteryC = 0;
int HLight = 0;
int Horn = 0;
long Tait;
int Pattery;
int Light1, Light2 = 0;
int Turno, Turns, Turner, Turn = 90;
int jhu = 1;
float speedFNS = 0;
float Tuner = 90;
long Wait = 0;
int Battery, Batery = 1023;
int Batmin = 1023;
long average = 0;
int Kait = 0;
int No = 1;


// ---------------------------------------------------------------------------------------------------------
// ------------------------------------------------------ Setup() ------------------------------------------

void setup() {
  
  Serial.begin(9600);
  
  pinMode (BatteryP, INPUT);
  pinMode(EngSpe, OUTPUT);
  pinMode(EngDir, OUTPUT);
  pinMode(HLights, OUTPUT);
  pinMode(BLights, OUTPUT);
  pinMode(BlinLight, OUTPUT);
  Stear.attach(mservo);

  //radio.setAutoAck(1); // Ensure autoACK is enabled so rec sends ack packet to let you know it got the transmit packet payload
  //radio.enableAckPayload(); //allows you to include payload on ack packet
  radio.maskIRQ(1,1,0); //mask all IRQ triggers except for receive (1 is mask, 0 is no mask)
 
  radio.begin();
  radio.openWritingPipe(addresses[0]);      //Setting the address at which we will send the data
  radio.openReadingPipe(1, addresses[1]);   //Setting the address at which we will receive the data
  radio.startListening();
  //Serial.println(Turner);
  //attachInterrupt(digitalPinToInterrupt (2), WirelessRead, FALLING);
}

// --------------------------------------------------------------------------------------------------------
// ------------------------------------------------- Functions() ------------------------------------------

void WirelessRead() {

  if (radio.available()) {  //char Text[32] = {0};  int Text[32] = {0};  radio.read(Text,1);
    //digitalWrite(BlinLight, HIGH);
    
    radio.read(&Text, sizeof(Text));

    if (Text[0] > 1000 && Text[0] < 3000) { speedread = Text[0] -1000; }
    else if (Text[0] > 3000 && Text[0] < 4000) { Turno = Text[0] -3000; }
    else if (Text[0] >= 4200 && Text[0] < 5000){ HLight = Text[0]; }

    Wait = millis();
    Kait = millis()/1000;
    No = 0;
    Serial.println (Text[0]);
  }
}

void Stops() {
  //else {
    if (millis() - Wait >=100 ) {
      Turno = 510;
      No = 1;
      speedread = 500; }
      //Kait = millis();
  //}
}

// -------------------------------------------------

void Batterys() {
  average = 0;
  
  if (((millis()/1000)-Kait > 3) && speedread == 500  && Turns == 90) {

    for (int cc = 0; cc < 50; cc++) {
      Batery = analogRead(BatteryP);
      average = average + Batery; }
    average = average/50;
    
    /*if (average < Batmin)*/{ Batery = average; }
    //else { Batery = Batmin; }
    //Serial.println(Batery);
    Battery = map(Batery, 738, 865, 0, 100); }

  if (jhu == 0 && (millis()-Tait > 20) && speedread == 500  && Turns == 90) {

    radio.stopListening();

    Temp[0] = Battery;
    //Batmin = Batery;
    radio.write(&Temp, sizeof(Temp));
    //RestartWireless();
    jhu = 1;
  }
  
  if (jhu == 1 && speedread != 500  || Turns != 90) {
    jhu = 0;
    Tait = millis();
    //Kait = millis();
  }
}

// -------------------------------------------------

void Engine() {
  
  if (speedread>675){speedread = 675;}
  if (speedread<345){speedread = 345;}
  
  speedR = map(speedread,345,490,70,255); //Reverse  Speed
  speedF = map(speedread,525,675,0,255); //Forward Speed

  if (speedread<540 && speedread>460){
    digitalWrite(EngSpe,LOW); digitalWrite(EngDir,LOW);
    speedFNS = 0;
    speedRN = 0;
  }
  
  else if (speedread>540){
    if (speedF > speedFN+100){ speedFN+=50; }
    else if (speedF > speedFN+50){ speedFN+=25; }
    else if (speedF > speedFN+10){ speedFN+=5; }
    else if (speedF < speedFN){ speedFN=speedF; }
    digitalWrite(EngDir, LOW); analogWrite(EngSpe,speedFN);
  }
  
  else if (speedread<460){
    if (speedR > speedRN+100){ speedRN+=50; }
    else if (speedR > speedRN+50){ speedRN+=25; }
    else if (speedR > speedRN+10){ speedRN+=5; }
    else if (speedR < speedRN){ speedRN=speedR; }
    digitalWrite(EngDir, HIGH); analogWrite(EngSpe,speedR);
  }
  
  //Serial.println(speedread);
  if (digitalRead(EngDir) == LOW) { Light1 = 0;}
  else if (digitalRead(EngDir) == HIGH) { Light1 = 200;}
}

// -------------------------------------------------

void Stearing() {
  //Serial.println(Turno);
  if (No == 1) { Turno = 500;}
  //if (Turno > 720){} else if (Turno<295){}
  else if (Turno > 720){Turno = 720;}
  else if (Turno < 310){Turno = 310;}
  Turns = map(Turno,310,720,65,115);
  if (Turns>85 && Turns <95){Turns = 90;}
  /*
  if (Turns == Turn){}
  else if (Turns > Turn){ Turn+=1; }
  else if (Turns < Turn){ Turn-=1; }
  //Serial.println(Turn);
  */
  /*
  //if ((Turn > Tuner + 61) || Turn < Tuner - 61) {}
  if (Turns == Tuner){}
  else if (Turns > Tuner){ Tuner+=0.1; }
  else if (Turns < Tuner){ Tuner-=0.1; }
  Turner = Tuner;
  Stear.write(Tuner);*/

  //if (Stear.read()>Tuner+1 || Stear.read()<Tuner-1){
  //Tuner = Stear.read(); }
  if (Turns == Stear.read()){}
  else if (Turns > Stear.read()){ Tuner+=0.1; }
  else if (Turns < Stear.read()){ Tuner-=0.1; }
  Turner = Tuner;
  Stear.write(Tuner);
  //Serial.println(Turner);
  
}

// -------------------------------------------------

void Lights() {
  if (HLight == 4200) {
    digitalWrite(HLights, HIGH);
    Light2 = 55; }
  else if (HLight == 4500) {
    digitalWrite(HLights, LOW);
    Light2 = 0; }

  analogWrite(BLights,Light1+Light2);
}

// -------------------------------------------------

void RestartWireless() {
  radio.begin();
  radio.openWritingPipe(addresses[0]);      //Setting the address at which we will send the data
  radio.openReadingPipe(1, addresses[1]);   //Setting the address at which we will receive the data
  radio.startListening();
  //Serial.println(Turner);
  attachInterrupt(digitalPinToInterrupt (2), WirelessRead, FALLING);
}

// -------------------------------------------------
/*
void Chorn() {
  if (Horn == 1) { tone(Hornp, 850); }
  else if (Horn == 0) {noTone(Hornp); }
}
*/
// ---------------------------------------------------------------------------------------------------
// ------------------------------------------------- Loop() ------------------------------------------

void loop() {
  
  //if (radio.isChipConnected()) {
    //Serial.println("CHIP CONNECTED"); }
    //else {Serial.println("No");}

    //if( millis()-curt > 1000) { RestartWireless(); curt = millis(); }

    if( millis()-curt > 50) {
    if ( ll == 0) { digitalWrite(BlinLight, HIGH); ll = 1; }
    else { digitalWrite(BlinLight, LOW); ll = 0; }
    curt = millis(); }

  
  
  WirelessRead();
  Stops();
  Lights();
  //Chorn();
  Engine();
  Stearing();
  digitalWrite(BlinLight, LOW);
  Batterys();

}`Preformatted text`

The problem is probably in the sketches that you have not posted, or possible in the circuits that you have not posted

The easier you make it to read and copy your code the more likely it is that you will get help

Please follow the advice given in the link below when posting code , use code tags and post the code here

If you get errors when compiling please copy them from the IDE using the "Copy error messages" button and paste the clipboard here in code tags

Ohh Sorry. Now it's right.

The Servo library uses interrupts for timing. If you have an ISR that runs longer than a couple of microseconds (like SoftwareSerial) you will get jitter in the servo outputs.

Perhaps the output buffer is filling up and this line in WirelessRead() is your problem:

"servo vibrates" is usually due to an inadequate servo power supply, which must be able to supply 1 to 3 Amperes at 5-6V, depending on the size of the servo. Do not use the Arduino 5V output.

4xAA batteries work well for one or two small servos, or one large servo.

Hi John, I had attached the interrupt (pin) with NRF and that seemed to incease the problem but I commented it out. Also that line is commented. It was added just as a check point while developing the program.

@jremington, I know so, the supply to servo is adequate. It runs perfectly if I remove NRF or do not send signal through it in above programs. Even I tried to run just the servo through NRF and a single POT, the result was smooth. I heard that POTs reading must not be taken together, so I separated them with 20ms and commenting out many things, the results seemed better but as I added other things back, the problem returned but at lower level. So, 20ms separation of POT readings seems a trick (I don't know why it's so). Trying other things step by step by removing and adding them back.

May there's still something which I'm missing. As I send something from receiver, the problem starts again :frowning:

Is it normal, or possibly a problem, to be using two nRF24L01 libraries in one sketch? The RF24 library example doesn't include nRF24L01.h.

No, but it also shouldn't effect anything and it doesn't (it seems) except eating some memory if it isn't used (I didn't I think it is).