Adding servos to existing RF24 project

Hello everyone, this is my first time on the forum, hopefully I set this up correctly. I have a project I have been working on, an RC tank using RF24. I have the tank working fine, transmitter is fine, I finally got that sorted and it was a monumental thing for me.
Now, I want to add a "pan/tilt" camera mount on it using two servos. I have the device printed and the servos connected, I am just having a hard time adding in this new servo code. I have been working on this for about a week, and have looked all over for code, I have found examples and got it working, though when I combine it with my existing code it never works.

I have attached what I feel like is my best attempt at combining them. Though with this sketch, power is finiicky and the motors will not even work anymore. Servos will work at the start and then stop.

I will put the backslashes in the code next to the added servo attempt, so you can see what the original is.

Another note, I am trying to get the servos to not retract back to their original position every time they are used. I have found some examples of this but never could transfer it. It is to move a camera, so if it resets back to the middle when I let go of the joystick it is a pain in the behind.

Thank you so much for reading, this thing has been driving me insane. Its my first relatively big Arduino project, I cant give up now!

Receiver

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>//////////////////
Servo Tilt;///////////////////
Servo Pan;///////////////////////
#define enA 6
#define in1 7
#define in2 5
#define enB 3
#define in3 4
#define in4 2

RF24 radio(9, 10); // CE, CSN
const byte address[][6] = {"00001", "00002"};
char receivedData[32] = "";
int  xAxis, yAxis;
int motorSpeedA = 0;
int motorSpeedB = 0;
int joystick[4];   ////////// joystick was [2]
int servoAngleA = 0;/////////
int servoAngleB = 0; ////////////////////
int servo_pin = 8;//////////
int servo_pin2 = A1;/// with motor controller I am low on pins, thus A1,

void setup() {
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address[1]);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();

Tilt.attach(servo_pin); ///////////////////
Pan.attach(servo_pin2);//////////////////

  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
}
void loop() {

  if (radio.available()) {   // If the NRF240L01 module received data

    radio.read( joystick, sizeof(joystick) );

    radio.read(&receivedData, sizeof(receivedData));
    yAxis = joystick[0];
    xAxis = joystick[1];
    servoAngleA = joystick[2]; //////////////
    servoAngleB = joystick[3]; //////////////

    Serial.println(yAxis);
    Serial.println(xAxis);
    Serial.println(servoAngleA); ////////////
    Serial.println(servoAngleB); /////////////
  }

  if (yAxis < 470) {

    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);

    digitalWrite(in3, HIGH);
    digitalWrite(in4, LOW);

    motorSpeedA = map(yAxis, 470, 0, 0, 255);
    motorSpeedB = map(yAxis, 470, 0, 0, 255);
  }
  else if (yAxis > 550) {

    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);

    digitalWrite(in3, LOW);
    digitalWrite(in4, HIGH);

    motorSpeedA = map(yAxis, 550, 1023, 0, 255);
    motorSpeedB = map(yAxis, 550, 1023, 0, 255);
  }

  else {
    motorSpeedA = 0;
    motorSpeedB = 0;
  }

  if (xAxis < 470) {

    int xMapped = map(xAxis, 470, 0, 0, 255);

    motorSpeedA = motorSpeedA - xMapped;
    motorSpeedB = motorSpeedB + xMapped;
    // Confine the range from 0 to 255
    if (motorSpeedA < 0) {
      motorSpeedA = 0;
    }
    if (motorSpeedB > 255) {
      motorSpeedB = 255;
    }
  }
  if (xAxis > 550) {

    int xMapped = map(xAxis, 550, 1023, 0, 255);

    motorSpeedA = motorSpeedA + xMapped;
    motorSpeedB = motorSpeedB - xMapped;

    if (motorSpeedA > 255) {
      motorSpeedA = 255;
    }
    if (motorSpeedB < 0) {
      motorSpeedB = 0;
    }
  }

  if (motorSpeedA < 70) {
    motorSpeedA = 0;
  }
  if (motorSpeedB < 70) {
    motorSpeedB = 0;
  
    analogWrite(enA, motorSpeedA); // Send PWM signal to motor A
    analogWrite(enB, motorSpeedB); // Send PWM signal to motor B
  }
  ////////////////////////////All of this is new below//////////////////////////////
  if (receivedData[2] < 460) {
    servoAngleA--;
    Tilt.write(servoAngleA);
  }
  if (servoAngleA <= 10) {
    servoAngleA = 10;
  }
  if (receivedData[2] > 564) {
    servoAngleA++;
    Tilt.write(servoAngleA);
  }
  if (servoAngleA >= 160) {
    servoAngleA = 160;
  }

  if (receivedData[3] < 460) {
    servoAngleB--;
    Pan.write(servoAngleB);
  }
  if (servoAngleB <= 10) {
    servoAngleB = 10;
  }
  if (receivedData[3] > 564) {
    servoAngleB++;
    Pan.write(servoAngleB);
  }
  if (servoAngleB >= 160) {
    servoAngleB = 160;
  }
}

Transmitter

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9,10); // CE, CSN
const byte address[][6] = {"00001", "00002"};
char xyData[32] = "";
int joystick[4]; /////////// was at [2]



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


}
void loop() {

  joystick[0] = analogRead(A4);
  joystick[1] = analogRead(A3);
  joystick[2] = analogRead(A0);/////////////
  joystick[3] = analogRead(A1);/////////////////

  
  radio.write( joystick, sizeof(joystick) );
  
}

Why 2 reads? What is receivedData? Where is receivedData coming from? Not the transmitter.

1 Like

The original sketch had one joystick for x and y axis of the motor controller to make the tank move. Now, I have another joystick to control two servos. That received data is the angle of the servo from the joystick. Well, that was my intention. I know this is a mess, but man, I have been trying.

In the code I posted I designated the servo code I tried to add in, hopefully that is easy enough to see. If you have any suggestions or know how I should do it I would really appreciate it.
I have seen your name pop up on other forums that I have been learning from, so I am sure you are the guy I need to talk to!
I really appreciate your time, this thing has been giving me headaches for a long while.

Your transmitter code is on the right track with the 4 joystick axes in an array. And the receiver receives the array. I suggest that you get rid of all of the receiveData code, it is not needed at all. Then work with the ints from the joystick array.

I took out the references to receivedData and put in data from the joystick array in the transmit code. The Receive code is OK as is.

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>//////////////////
Servo Tilt;///////////////////
Servo Pan;///////////////////////
#define enA 6
#define in1 7
#define in2 5
#define enB 3
#define in3 4
#define in4 2

RF24 radio(9, 10); // CE, CSN
const byte address[][6] = {"00001", "00002"};
//char receivedData[32] = "";
int  xAxis, yAxis;
int motorSpeedA = 0;
int motorSpeedB = 0;
int joystick[4];   ////////// joystick was [2]
int servoAngleA = 0;/////////
int servoAngleB = 0; ////////////////////
int servo_pin = 8;//////////
int servo_pin2 = A1;/// with motor controller I am low on pins, thus A1,

void setup()
{
   pinMode(enA, OUTPUT);
   pinMode(enB, OUTPUT);
   pinMode(in1, OUTPUT);
   pinMode(in2, OUTPUT);
   pinMode(in3, OUTPUT);
   pinMode(in4, OUTPUT);
   Serial.begin(9600);
   radio.begin();
   radio.openReadingPipe(0, address[1]);
   radio.setPALevel(RF24_PA_MIN);
   radio.startListening();

   Tilt.attach(servo_pin); ///////////////////
   Pan.attach(servo_pin2);//////////////////

   digitalWrite(in1, LOW);
   digitalWrite(in2, LOW);
   digitalWrite(in3, LOW);
   digitalWrite(in4, LOW);
}
void loop()
{
   if (radio.available())     // If the NRF240L01 module received data
   {
      radio.read( joystick, sizeof(joystick) );

      yAxis = joystick[0];
      xAxis = joystick[1];
      servoAngleA = joystick[2]; //////////////
      servoAngleB = joystick[3]; //////////////

      Serial.println(yAxis);
      Serial.println(xAxis);
      Serial.println(servoAngleA); ////////////
      Serial.println(servoAngleB); /////////////
   }

   if (yAxis < 470)
   {
      digitalWrite(in1, HIGH);
      digitalWrite(in2, LOW);

      digitalWrite(in3, HIGH);
      digitalWrite(in4, LOW);

      motorSpeedA = map(yAxis, 470, 0, 0, 255);
      motorSpeedB = map(yAxis, 470, 0, 0, 255);
   }
   else if (yAxis > 550)
   {
      digitalWrite(in1, LOW);
      digitalWrite(in2, HIGH);

      digitalWrite(in3, LOW);
      digitalWrite(in4, HIGH);

      motorSpeedA = map(yAxis, 550, 1023, 0, 255);
      motorSpeedB = map(yAxis, 550, 1023, 0, 255);
   }

   else
   {
      motorSpeedA = 0;
      motorSpeedB = 0;
   }

   if (xAxis < 470)
   {
      int xMapped = map(xAxis, 470, 0, 0, 255);

      motorSpeedA = motorSpeedA - xMapped;
      motorSpeedB = motorSpeedB + xMapped;
      // Confine the range from 0 to 255
      if (motorSpeedA < 0)
      {
         motorSpeedA = 0;
      }
      if (motorSpeedB > 255)
      {
         motorSpeedB = 255;
      }
   }
   if (xAxis > 550)
   {
      int xMapped = map(xAxis, 550, 1023, 0, 255);

      motorSpeedA = motorSpeedA + xMapped;
      motorSpeedB = motorSpeedB - xMapped;

      if (motorSpeedA > 255)
      {
         motorSpeedA = 255;
      }
      if (motorSpeedB < 0)
      {
         motorSpeedB = 0;
      }
   }

   if (motorSpeedA < 70)
   {
      motorSpeedA = 0;
   }
   if (motorSpeedB < 70)
   {
      motorSpeedB = 0;

      analogWrite(enA, motorSpeedA); // Send PWM signal to motor A
      analogWrite(enB, motorSpeedB); // Send PWM signal to motor B
   }
   ////////////////////////////All of this is new below//////////////////////////////
   if (servoAngleA < 460)
   {
      servoAngleA--;
      Tilt.write(servoAngleA);
   }
   if (servoAngleA <= 10)
   {
      servoAngleA = 10;
   }
   if (servoAngleA > 564)
   {
      servoAngleA++;
      Tilt.write(servoAngleA);
   }
   if (servoAngleA >= 160)
   {
      servoAngleA = 160;
   }

   if (servoAngleB < 460)
   {
      servoAngleB--;
      Pan.write(servoAngleB);
   }
   if (servoAngleB <= 10)
   {
      servoAngleB = 10;
   }
   if (servoAngleB > 564)
   {
      servoAngleB++;
      Pan.write(servoAngleB);
   }
   if (servoAngleB >= 160)
   {
      servoAngleB = 160;
   }
}

This compiles with no warnings or errors, but is untested.

Can you post a schematic?

How are the servos and the motor powered?

1 Like


Thank you so much! I have not had a chance to test yet, my girlfriend is waiting impatiently for me to get into bed. I will test out the receiver changes you made. I cant tell you how much I appreciate it! Ill give an update tomorrow asap.

Hopefully the photos helped somewhat, I looked into creating a diagram but none of the tools I found had all the parts. I thought just a photo would be better than me trying to describe it. The two motors are not connected, they are in the tank at the moment, built in, though I have one to plug in just to test.

They will both be powered by a Lipo, with the adafruit powerboost 1000c. While I am testing and working on them I have them plugged into the computer, and also with an external barrel plug cord with variable power. One of the photos you can see one of the barrel plugs in the breadboard.

I did a test today. It almost looks like the array is confused, the servos will listen to the joysticks for a second, but then they are erratic. Then everything will quit working all together. I have not got the motors to run at all on the new sketch, makes me think the servo array is taking over or something. Granted I am the furthest from an expert, but it acts like the servo array is getting all 4 inputs, and is going haywire. I am changing up the power sources, seeing if that will do anything, no luck so far.

Another bit of info, not sure if it is related. When I first put this code in, nothing worked at all. I had to strip it down and do the NRF tests, one of my NRF modules needed to be reset then it worked again. I think this is unrelated, but wanted to give you all the information possible. I feel like we are really close here!

What power supply(s) are being used? Until you have good solid power to the radios, motors and servos all bets are off and no amount of code will make things work.

1 Like

Right now I have both Arduino Nanos plugged in to the PC from their port. Then via the "vin" I have a barrel jack wired in. Attached to that barrel jack is a "Shnitpwr" adapter. It plugs into the wall, has a knob so you can control the voltage coming in. So even if I increase that voltage the servos still freak out.

For each of the components you need not only the correct voltage, but enough current. What is the current capacity of the power supply?

Be careful when using the power plug or Vin. Powering through Vin or the power jack means that the Arduino and all peripherals that are on the 5V rail are powered by the onboard 5V regulator. The on board 5V regulator is not heat sinked so will supply limited current before it overheats and shuts down. The amount of current depends on the voltage input to Vin or the power jack. The higher the voltage the less current can by supplied. I would use a buck converter to drop the higher power supply voltage to 5V and connect that to the 5V on the Arduino, bypassing the, weak, 5V regulator. Then the rated current of the DC DC converter is available on the 5V line.

To analyze the current needs you need to know the rated voltage and stall current specifications of the motors and servos. Data sheets for those devices should list those specifications

I will take a look at that right now and get back to you. Thank you so much!

Ok, I think you were dead right about the power. I separated the servos on another breadboard and kept the common ground. Then used another power source. I used the breadboard power supply, I know its not a buck converter but its the best I have at them moment. It did do much better, still acting crazy, but not as bad, and did seem to listen to commands from the joystick, the motors also worked just fine.

Important note, an embarrassing one I hesitate to mention, when I first tested this I did not use the breadboard power supply and thought I was about to see fireworks. I am amazed the servos are alive, and amazed my other projects have not been destroyed by this.

I am confused though, because even when the main power source going into the Arduino is from the Adafruit 1000C connected to a lipo battery. This still happens, from my very limited knowledge and experience, this is why I bought that very expensive Adafruit 1000C.

Is ordering a buck converter my only option do you think? Is there another way to go about doing this?

Priorities! :rofl:

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.