Servos twitching uncontrollably when given command via bluetooth

I've created a robot arm using 3 servo motors and when I adjust the sliders on an app the servos all twitch. I tried using a capacitor to stabilize the current flow but that was not enough to calm it down. Other posts about the twitching problem say it's because of a lack of power supply. My li-po battery has enough voltage (7.4V) to provide and has a high discharge rate (25c) meaning it should be able to handle all 3 servos. I was able to control them before using potentiometers.

My materials:

  • Arduino Nano
  • HC-05 Bluetooth module
  • 3 MG996R servo motors (datasheet attached)
  • 1 L298N Motor driver
  • 2 DC Gearbox motors
  • Turnigy 7.4V 2200mAh Lipo
  • Li-on 3.7V

My code:

#include <SoftwareSerial.h>
#include <Servo.h> // servo library 
Servo myservo1, myservo2, myservo3; // servo name
int motorOne = 3;
int motorOne2 = 4;
int motorTwo = 5;
int motorTwo2 = 6;
int en1 = 2;
int en2 = 7;
int bluetoothTx = 10;
int bluetoothRx = 11;
SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);


// MUST HAVE enA and enB, edit the first while loop to include bluetooth, 3.7v lipo small batt, and reattach robot claw then yearly project is done! YAYY!!

//initial motors pin

char command; 
char Value;

void setup()
{
  myservo1.attach(9); // attach servo signal wire to pin 9
  myservo2.attach(12);
  myservo3.attach(13);
   
  //Setup usb serial connection to computer
  Serial.begin(9600);
  bluetooth.begin(9600);
  //Setup Bluetooth serial connection to android

}
void loop()
{
  while (bluetooth.available() > 0) {
    Value = bluetooth.read();
    Serial.println(Value);
  }

  if ( Value == 'F') {
    // Robo Pet Run Forward
    digitalWrite(en1, HIGH);
    digitalWrite(en2, HIGH);
    digitalWrite(motorOne, HIGH);
    digitalWrite(motorOne2, LOW);
    digitalWrite(motorTwo, HIGH);
    digitalWrite(motorTwo2, LOW);
  } else if (Value == 'B') {
    //Robo Pet Run Backward
    digitalWrite(en1, HIGH);
    digitalWrite(en2, HIGH);
    digitalWrite(motorOne, LOW);
    digitalWrite(motorOne2, HIGH);
    digitalWrite(motorTwo, LOW);
    digitalWrite(motorTwo2, HIGH);
  } else if (Value == 'L') {
    //Robo Pet Turn Left
    digitalWrite(en1, HIGH);
    digitalWrite(motorOne, HIGH);
    digitalWrite(motorOne2, LOW);
    digitalWrite(motorTwo, LOW);
    digitalWrite(motorTwo2, LOW);
  } else if (Value == 'R') {
    //Robo Pet Turn Right
    
    digitalWrite(en1, HIGH);
    digitalWrite(motorTwo, HIGH);
    digitalWrite(motorTwo2, LOW);
    digitalWrite(motorOne, LOW);
    digitalWrite(motorOne2, LOW);
  } else if (Value == 'S') {
    //Robo Pet Stop
    digitalWrite(motorOne, LOW);
    digitalWrite(motorOne2, LOW);
    digitalWrite(motorTwo, LOW);
    digitalWrite(motorTwo2, LOW);
  }

  //Read from bluetooth and write to usb serial
  if(bluetooth.available()> 0 )
  {
    unsigned int servopos = bluetooth.read();
    unsigned int servopos1 = bluetooth.read();
    unsigned int realservo = (servopos1 *256) + servopos;
    Serial.println(realservo);
    if (realservo >= 1000 && realservo <1180) {
      int servo1 = realservo;
      servo1 = map(servo1, 1000, 1180, 0, 180);
      myservo1.write(servo1);
      Serial.println("Servo 1 ON");
      delay(10);
    }
    if (realservo >= 2000 && realservo <2180) {
      int servo2 = realservo;
      servo2 = map(servo2, 2000, 2180, 0, 180);
      myservo2.write(servo2);
      Serial.println("Servo 2 ON");
      delay(10);
    }
    if (realservo >= 3000 && realservo <3180) {
      int servo3 = realservo;
      servo3 = map(servo3, 3000, 3180, 0, 180);
      myservo3.write(servo3);
      Serial.println("Servo 3 ON");
      delay(10);
    }
    
  }
}

The app i'm using for controlling servos:
https://drive.google.com/file/d/1CMS4IN4Hxd922cu4Q6afkjA03YsoZK6r/view

Schematic of connections:

Datasheet of servos:

Hopefully, I provided all the information you need. Any tips and help would be much appreciated.

Thank you!

Please don't do that, you will do more harm than good, depending where you put it.
It would be useful if you printed out what you are trying to drive the servos to, rather than just saying it is on. Then you can see if your values are changing rapidly. This will cause servos to twitch.

I am assuming your servo ground is connected to the Arduino ground. You don't show it on your diagram.

The stall current is 2.5 amp at 6 volt. 3 servo adds to 7.5 amps.
What does the datasheet/specification say regarding current delivery of that battery?

Hi,
As @Grumpy_Mike has mentioned, have you got the Arduino gnd and servo power supply gnd connected.
Did this problem occur when you programmed in stages?
That is did you code JUST to get a servo to sweep?
When you got that working then code to JUST get the 3 servos to sweep.
When you have that working, write code JUST to test your Bluetooth connection.
When you have that working combine the two.
That way you have a fair idea where any bug has developed and you have solved it before combining the big picture.

Thanks.. Tom.. :smiley: :+1: :coffee: :australia:

what you are trying to drive the servos to,

I don't understand what you mean by the above quote. The servos are the joints of a robotic arm and I'm trying to get them to turn.

The capacitor stopped twitching when I used potentiometers to operate the servos. The servos started to twitch again when I removed the en2 pin from the L298N motor driver which drives the wheels of the car that the robot arm sits on. Both the gear motors and servos are attached to a breadboard for the Nano.

I currently operate the servos with Servocontrol.apk via bluetooth, but the twitching occurred with the potentiometer as stated above, and with the bluetooth control.

I forgot to mention, I'm using a LM2596s step-down buck converter. Here is an updated schematic. I used kiCad for this:

That is because you only quote half the sentence. The full sentence is.

He key words here are **printed out **
You are trying to drive the servos to a certain position. What is that position?
It would be good to see what that position is by printing it out.

Yes of course it would with pots, because the A/D will only give the position of the pots to +/- one bit, as is the nature of A/D converter.

Where on earth would you put capacitors without pots. Putting them from control signal to ground is silly.

The new diagram still doesn't make it clear if the negative end of the battery is connected to the Arduino ground.

The maximum current the battery can deliver is 55 amps.

I multiplied the C rating by its storage (25*2.2) which resulted in 55 amps.

Is this the correct formula?

Really? Impressive and enough.

Oops. That's woodoo to me, please explain. Tell the storage. C10... I know what stands for. What do you say it is?

I plugged the negative end of the servo power supply and my Arduino Gnd into the negative side of the power rail on the breadboard. Does this qualify as a connection?

Originally, I did not program in stages. I took the code from another project. (https://www.youtube.com/watch?v=dZmM_bcPicc&t=69s)
That code is in the original post.

So I went back and took your advice and programmed in stages.

NOTE: I was able to achieve what you describe above i.e I was able to command the servos with the mobile app via bluetooth. However, the problem reappears when I add the code for the gear motors on the car that serves as the base for the robot arm.

The following is a description of the steps I took.

First, I reconnected the potentiometers to the servos. Then I tested one servo and 3 servos separately with code snippets that are not part of the code in the original post. The code below is for testing a single servo. For both the single and 3 servo tests, they rotate from left to right as the code dictates. There was no twitching as described in the original post.

/* Sweep
 by BARRAGAN <http://barraganstudio.com>
 This example code is in the public domain.

 modified 8 Nov 2013
 by Scott Fitzgerald
 https://www.arduino.cc/en/Tutorial/LibraryExamples/Sweep
*/

#include <Servo.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0;    // variable to store the servo position

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

void loop() {
  for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15 ms for the servo to reach the position
  }
}

Since this test code operates the servos with no problem, I am assuming there are no issues with the power supply or wiring that would cause the twitching. Do you agree?

Then I tested the operation of the servos with the bluetooth module. I used the code from the project linked here: https://www.youtube.com/watch?v=dZmM_bcPicc&t=69s (NOTE: This is the same as the project linked above.)

The result of this test was that the servos operated as they should with no twitching.

Here is the code:

#include <SoftwareSerial.h> // TX RX software library for bluetooth
#include <Servo.h> // servo library 
Servo myservo1, myservo2, myservo3; // servo name
int bluetoothTx = 10; // bluetooth tx to 10 pin
int bluetoothRx = 11; // bluetooth rx to 11 pin
SoftwareSerial bluetooth(bluetoothTx, bluetoothRx);
void setup()
{
  myservo1.attach(9); // attach servo signal wire to pin 9
  myservo2.attach(12);
  myservo3.attach(13);

  //Setup usb serial connection to computer
  Serial.begin(9600);
//Setup Bluetooth serial connection to android
  bluetooth.begin(9600);
}
void loop()
{
  //Read from bluetooth and write to usb serial
  if(bluetooth.available()>= 2 )
  {
    unsigned int servopos = bluetooth.read();
    unsigned int servopos1 = bluetooth.read();
    unsigned int realservo = (servopos1 *256) + servopos;
    Serial.println(realservo);
if (realservo >= 1000 && realservo <1180) {
      int servo1 = realservo;
      servo1 = map(servo1, 1000, 1180, 0, 180);
      myservo1.write(servo1);
      Serial.println("Servo 1 ON");
      delay(50);
    }
    if (realservo >= 2000 && realservo <2180) {
      int servo2 = realservo;
      servo2 = map(servo2, 2000, 2180, 0, 180);
      myservo2.write(servo2);
      Serial.println("Servo 2 ON");
      delay(50);
    }
    if (realservo >= 3000 && realservo <3180) {
      int servo3 = realservo;
      servo3 = map(servo3, 3000, 3180, 0, 180);
      myservo3.write(servo3);
      Serial.println("Servo 3 ON");
      delay(50);
    }
  }
}

At this point I reuploaded the code from the original post. Servo twitching reappeared with a new problem - the gear motors spin when I attempt to control the servos with the mobile app.

I assume this means there is a problem with the original code. I tried to fix the code by experimenting with the first if statement. Both the Gear motors and servos need to read data that is being received from the HC-05 module. They read inputs differently and were overlapping each other so I erased the gear motors input, replaced it with the servos input reading function and tested this and vice versa. This time servos functioned without problem but when I attempt to control the gear motors they don't respond.

The input reading function for Gear motor & servos:
Car -

while (bluetooth.available() > 0) {
    Value = bluetooth.read();
    Serial.println(Value);
  }

Servo -

if  (bluetooth.available() >= 2) {
    unsigned int servopos = bluetooth.read();
    unsigned int servopos1 = bluetooth.read();
    unsigned int realservo = (servopos1 *256) + servopos;
    Serial.println(realservo);
    
  }

The last thing I have done is try to find code from other projects that read inputs differently so it won't affect the gear motors and servos. However, all other projects use the same WHILE and IF statements.

I'm a beginner coder and I don't know the proper way to troubleshoot code. What do you recommend at this point?

Thank you!

The Li-po battery stores 2200mAh. The discharge rate of the li-po is actually 30C so 2.2 Ah * 30 which is equal to 66. Other posts explained that in order to calculate the current a li-po can deliver is to multiply it’s storage by the C rating. I know you are saying C10 is something else, but I can't find the answer.

C10 means that if You pull 2200 mAh / 10 = 220 mA You will get 2200 mAh of energy from the cell. If You use C20, 110 mA You will get more energy out. Using 440 mA You will get less energy out of the cell.
All batteries have some internal resistance that burns energy. The higher current the higher loss and the lees energy coming out.
The maximum current possible to use is not told by the capacity data, the mAh figure.

Edited to add that none of this seems to be germane to the problem.

A point of clarification:

You two are saying similar things, but with somewhat different nomenclature.

The "C" rate is the discharge (or charge) rate in amps divided by the battery capacity in amp-hours. It is usually shown as unit-less.

For C rates greater than 1, the usual nomenclature is, for example, 10C, which corresponds to a nominal 22 amp rate from 2.2 A-hr battery (22/2.2 = 10)

And for C rates less than 1, it is often expressed as the letter C followed by a fraction (including the fraction symbol). For example, a C rate of 0.1 is shown as C/10, which corresponds to a 0.22 A or 220 mA rate from a 2.2 A-hr battery (0.22 / 2.2 = 1/10)

And @Railroader is tacking on another concept, which is that less energy is available at high discharge rates. Which is true, due to internal heating and other effects.

Another tacking, yes, but I never got the impression that the capacity tells anything about the maximum current the battery can deliver/ is made for. A quick and easy assumption is: the higher currents used, the shorter life of the battery.

More to the point, there is (or at least was) a conflict between SoftwareSerial and the servo library. Google it. Try your combined code using Serial (via your computer) only, no BT, no SoftwareSerial. If that works, then ditch SoftwareSerial and use Serial for BT. (You'll have to disconnect BT to upload to the Arduino, and then reconnect BT.)

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