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`