clone mg996r problems

I picked up some cheap servos from amazon to eventually make a custom steering system for a RC car.

everything works fine, until the servo freaks out. It just starts spinning.

I searched and most of the answers I found just said that it is a 360deg servo, and conversation ends. I took apart the servo, there is no limiting pin, but has a POT. testing also shows that it is a 180deg servo as advertised.

I created the following sketch to test what happens when the wrong signals are sent and find the limits. Code works fine, accept for sending a microsecond pulse too short, then it jumped around. everything else pointed to it being a 180deg servo.

hardware setup. Nano clone on a breadboard, 2s powering the servo and connected to Vin and ground on nano. servo connected to pin 6. Nano connected to pc via USB.

One time I disconnected the battery while it was connected to the pc, and it started spinning. seemed the power was flowing out through the Vin pin.

I am looking for ideas about what is actually causing the problem, trying to solve the before I break more parts, these have lots of torque.

//seeing what happens when different signals are sent to the servo each test will be done, and then commentend out
//test one: simple sweep 0 -180 sweep, 550 - 2500 microsecond sweep works properly
//test two: extended sweep -20 to 200 - effectivly pauses when out of range
//test three: extended sweep via microsecond 450 -2600 - jumps around below 544 the larger the difference the larger the jump
//test four: goes from 544 and down - does not seem to delay the correct amount, 
//                      delay 100ms jumps back and forth around 160 and 180
//                      delay 300ms jumps back and forth  around 180 and 90
//                      delay 500ms jumps back and forth around 20 and 160
//                      delay 1000ms jumps back and forth around 20 and 180 long enough to see the delay.
//test five: turn servopin high to low - servo defaulted to 90deg and stayed there.
//test six: continually sending 90deg to the servo: just sits there. no motor noise

#include <Servo.h>

Servo myservo;
int servopin = 6;
int x = 0;

void setup() 
{ 
  myservo.attach(servopin);
  
}

void loop() 
{
  //simplemssweep();
  //simpledegreesweep();
  //extendeddegreesweep();
  //extendedmssweep();
  //outofrangeslow();
  //turnoffpin();
  send90();
  
  
}

void send90()
{
  myservo.write(90);
  delay(50);
}
void turnoffpin()
{
  digitalWrite(6,HIGH);
  delay(500);
  digitalWrite(6,LOW);
  delay(500);
}
void outofrangeslow()
{
  myservo.write(544);
  delay(1000);
  myservo.write(500);
  delay(1000);
  myservo.write(450);
  delay(1000);
  
}
void extendedmssweep()
{
   int x;
  for (x=544; x<=1000; x++)
  {
    myservo.write(x);
    delay (2);
  }
    for (x=1000; x>=544; x--)
  {
    myservo.write(x);
    delay (2);
  } 
}
void extendeddegreesweep()
{
  int x;
  for (x=-20; x<=200; x++)
  {
    myservo.write(x);
    delay (20);
  }
    for (x=200; x>=-20; x--)
  {
    myservo.write(x);
    delay (20);
 }
}

void simpledegreesweep()
{
  int x;
  for (x=0; x<=180; x++)
  {
    myservo.write(x);
    delay (20);
  }
    for (x=180; x>=0; x--)
  {
    myservo.write(x);
    delay (20);
 }
}
void simplemssweep()
{
  int x;
  for (x=550; x<=2500; x++)
  {
    myservo.write(x);
    delay (2);
  }
    for (x=2500; x>=550; x--)
  {
    myservo.write(x);
    delay (2);
  } 
}

“I searched and most of the answers I found just said that it is a 360 deg servo, and conversation ends. I took apart the servo, there is no limiting pin, but has a POT. testing also shows that it is a 180 deg servo as advertised.”

I don’t have any of the MG995 or MG996R servos, but I’ve modified other brands of servos for continuous rotation. That being said, the MG996R is probably a continuous rotation servo, and yes, it probably still contains a pot. In some cases the pot shaft actually is needed to support the output gear. Usually the output gear connection to the pot shaft is removed so the pot shaft is not moved (may be something you need to do). To setup the servo, I send the servo a 1500us command, then tweak the put until the motor stops rotating. A tiny drop of glue might be needed on the pot shaft to keep it from moving during operation and causing issues. Then the full rotation range in both directions is something like 1400us to 1600us. Below is simple servo code I use to setup and test the servos using the serial monitor.

// zoomkat 7-30-10 serial servo test
// type servo position 0 to 180 in serial monitor
// for writeMicroseconds, use a value like 1500
// Powering a servo from the arduino usually *DOES NOT WORK*.

String readString;
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);
  myservo.attach(9);
}

void loop() {

  while (Serial.available()) {

    if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
      delay(3);
    } 
  }

  if (readString.length() >0) {
    Serial.println(readString);
    int n = readString.toInt();
    Serial.println(n);
    myservo.writeMicroseconds(n);
    //myservo.write(n);
    readString="";
  } 
}

I have seen servos that operated as normal servos, properly moving to the specified angle ans a standard servo.
UNTIL you gave the servo a command that was too low or too high.
If you servo.Writemicroseconds() and give it a value between say, 1000 and 2000, the the servo moved as expected for a standard servo.
BUT if you wrote a value of 600, it would spin continuously.
A fix for this situation was to use the optional parameters in the servo.attach() to set the min and max values.
servo.Attach(servopin, 1000, 2000)

Does this sound like what you are experiencing? You might experiment with different min and max values.

vinceherman:
If you servo.Writemicroseconds() and give it a value between say, 1000 and 2000, the the servo moved as expected for a standard servo.
BUT if you wrote a value of 600, it would spin continuously.

Best of both worlds. I wonder if that's an actual intended feature, or a bug?

During my initial searching I found zoomkat’s servo testing code, but just using the write() command. Testing the writeMicrosecond() command it would not move with an out of range signal.

I had tested with for loops with just the write(), and the servo would jump around if I used sent a value between 300 and 440. Changing to writeMicrosecond(); the servo now ignores out of range signals.

It looks like you can move the final drive pin high enough that no longer actuates the POT but still supports the rod. Or replace the pot with a couple of resistors.

I am now looking at incorrect power causing the problem, My guess is that the way I am powering the system is dipping just a bit low and the processor is getting confused. I am going to try putting a POT between the power and the servo+ line and see if I can recreate the problem.

my final design will likely need to power the servos directly from the battery, rather than through the rc receiver + esc.

void extendedmssweep()
{
   int x;
  for (x=400; x<=3000; x++)
  {
    //myservo.write(x);
    myservo.writeMicroseconds(x);
    delay (2);
  }
    for (x=3000; x>=400; x--)
  {
    //myservo.write();
    myservo.writeMicroseconds(x);
    delay (2);
  } 
}
void extendeddegreesweep()
{
  int x;
  for (x=-20; x<=200; x++)
  {
    myservo.write(x);
    delay (20);
  }
    for (x=200; x>=-20; x--)
  {
    myservo.write(x);
    delay (20);
 }
}

Using servo.write() with value outside the normal 0-180 range means that the code will try to translate your value into a writeMicroseconds() call. So e.g. write(1500) is equivalent to write(90). I wish it didn't because it's really confusing but there you go.

But the thing that's puzzling is that the Servo code normally limits the microsecond value to 544 - 2400. So I'd expect that values in range 300-440 would do absolutely nothing. And apparently if you do it properly using writeMicroseconds() that's what it does.

So maybe you've found a way to break the Servo write() by abusing it something rotten. But honestly if you want to use microseconds and not angles then use the correct command.

Steve

When tracking down a weird problem you have to find a way to recreate it. So I tried :slight_smile: Originally I was just using degrees, I never would have dug into this if things had worked properly.

Honestly these are cheap servos, the kind most of us getting into this hobby will likely buy. The servo board might be the problem. I also know that someone else will run into this issue and will keep finding the same answer, "you have a 360 degree servo" so i decide to find the problem.

I tried installing a POT vary the voltage to the servo, but it would just slow down then stop.
I then removed the ground from the 3rd pin. I found that if set the resistance to 80 ohm it would recreate the problem. I will power the system differently to avoid this.

The problem comes down a power supply issue...