A problem combining mg996r servos, MPU6050 and Arduino Uno

Hello. For my college project my friend and I decided we will build a robotic arm controlled wirelessly by a glove, built to imitate our movements. Since the beginning we had problems understanding how to properly contol the servos through C language. Wev'e got a stock code from the internet, but we are not sure if it fits the servo. It's my first time working with Arudino devices, and using C language ( I'm working with C++ ), but we are determined to make a good project from what we got and what we will learn in the journey.

We have tried the knob servo stock program but the servo ignores the program and tries to keep spinning, griding its gears, even when we tweaked the code to make it turn 180 degrees back and forth. Is there a different library for that servo?

Here is the example code:

#include <Servo.h>

Servo myservo; 

int potpin = 0; 
int val; 

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

void loop() 
{ 
  val = analogRead(potpin);         
  val = map(val, 0, 1023, 0, 180);   
  myservo.write(val);                 
  delay(15);                          
}

We have tried out own program to try and move the servos but encountered these problems listed below:

As seen at the first seconds, the servo is at is limit/edge. When power is turned on, it bounces to life and goes around until it hits the end, then tries to move more, buzzing and possibly forcing the gears. Note that the generator shows a short circuit. I don't really understand where's the problem and why it's short. We kept all cables seperated and clear. From what I've seen it's the case with all the servos. What's going on?

Next thing we tried to do is to figure out how to work with an MPU6050. We have used an internet code, connected to MPU6050 to the board, and got odd results. Extreme constant acceleration, degrees of MPU ( allegedly ) that always move but balance in the end to around -200. Is this how the MPU is suposed to work?

Code used on MPU:

#include<Wire.h>
const int MPU=0x68;  // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
void setup()
{
  Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  Serial.begin(9600);
}
void loop()
{
  Wire.beginTransmission(MPU);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU,14,true);  // request a total of 14 registers
  AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)     
  AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Tmp=Wire.read()<<8|Wire.read();  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
  GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
  
  Serial.print("Accelerometer: ");
  Serial.print("X = "); Serial.print(AcX);
  Serial.print(" | Y = "); Serial.print(AcY);
  Serial.print(" | Z = "); Serial.println(AcZ);
  //equation for temperature in degrees C from datasheet
  Serial.print("Temperature: "); Serial.print(Tmp/340.00+36.53); Serial.println(" C "); 
  
  Serial.print("Gyroscope: ");
  Serial.print("X = "); Serial.print(GyX);
  Serial.print(" | Y = "); Serial.print(GyY);
  Serial.print(" | Z = "); Serial.println(GyZ);
  Serial.println(" ");
  delay(333);
}

All information and help would be much appreciated. We are stuck, and so is our director.
Thanks.

You need a pot connected to analogue pin A0 on the UNO for your servo program to work. As you move the pot above or below centre, the servo will move left and right. (Perhaps you should have read the example sketch's comments, instead of deleting them. :slight_smile: )

Can't help with the MPU6050. I've never used one.

Most servo problems are due to inadequate power. Servos MUST be powered separately than the Arduino. Budget 1 ampere per servo, and be sure to connect the grounds of the two power supplies together.

jremington:
Most servo problems are due to inadequate power. Servos MUST be powered separately than the Arduino. Budget 1 ampere per servo, and be sure to connect the grounds of the two power supplies together.

In this case, it's a matter of no pot connected at all, as evidenced in the video.

I see you're using a dual power supply. Do the two supplies share a common ground?

As jremington mentioned, the two supplies have to have a common ground connection.

Where did you get the MPU6050 software?

Have you tried the super amazing I2Cdevlib code? If not, try it. It's amazing.

We have tried the knob servo stock program but the servo ignores the program and tries to keep spinning, griding its gears, even when we tweaked the code to make it turn 180 degrees back and forth. Is there a different library for that servo?

That type of srvo behavior us usually due to mal formed servo control pulses, or failure to connect the servo power supply ground and arduino grounds together, like in the attached pix.

servo-wire.jpg

No one else thinks that not having a pot connected might cause the problem?
(Although it might be that the two halves of the power supply don't have a common ground as well.)

So, RoiMan, you have two issues to check. :wink:

I'm not sure what hardware setup is being used. If the knob code is being run, then a pot is needed for the analog input pin, otherwise the pin may float and cause errattic servo behavior. Below is very simple servo test code that can be used with the serial monitor to check the servo operation and trouble shooting.

//zoomkat 7-30-10 serial servo test
//type servo position 0 to 180 in serial monitor
// 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);
  Serial.println("servo-test"); // so I can keep track of what is loaded
}

void loop() {

  while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the String readString
    delay(2);  //slow looping to allow buffer to fill with next character
  }

  if (readString.length() >0) {
    Serial.println(readString);  //so you can see the captured String 
    int n = readString.toInt();  //convert readString into a number
    Serial.println(n); //so you can see the integer
    myservo.write(n);
    readString="";
  } 
}

zoomkat:
I'm not sure what hardware setup is being used. If the knob code is being run, then a pot is needed for the analog input pin, otherwise the pin may float and cause errattic servo behavior.

Yep, my point exactly. RoiMan's video definitely showed no pot attached anywhere. (You can clearly see his hardware setup.)
Aside from that, the "Knob" example that he used should work, provided of course, the power supplies share a common ground as pointed out by everyone.

OldSteve:
You need a pot connected to analogue pin A0 on the UNO for your servo program to work. As you move the pot above or below centre, the servo will move left and right. (Perhaps you should have read the example sketch's comments, instead of deleting them. :slight_smile: )

Can't help with the MPU6050. I've never used one.

jremington:
Most servo problems are due to inadequate power. Servos MUST be powered separately than the Arduino. Budget 1 ampere per servo, and be sure to connect the grounds of the two power supplies together.

zoomkat:
That type of srvo behavior us usually due to mal formed servo control pulses, or failure to connect the servo power supply ground and arduino grounds together, like in the attached pix.

Thank you all! Got into lab with partner and project guide and tried the common ground, powering the servos with sufficient power and the Arduino with a seperate phone battery charger thing. Worked like a charm. I didn't find anything about the A0 or how it connects because the servos pretty much connect to 3 things - pin 9, VCC and GND. But putting in slighty modified on the fly, very simple code we got it to move with neatly with small fall of power sometimes but either way great.

#include <Servo.h>

Servo myservo;  // create servo object to control a servo

int potpin = 0;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin

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

int i;

void loop() 
{ 
  for(i=0;i<180;i++){
      myservo.write(i);                  // sets the servo position according to the scaled value 
      delay(15);                           // waits for the servo to get there 
  }
  for(i=180;i>0;i--){
      myservo.write(i);                  // sets the servo position according to the scaled value 
      delay(15);                           // waits for the servo to get there 
  }
}

Regarding the MPU6050:

DuaneDegn:
Where did you get the MPU6050 software?

Have you tried the super amazing I2Cdevlib code? If not, try it. It's amazing.

We took it off the web, which didn't have that much info on how to deal with MPUs. We used that code in the official Arduino app with the serial magnifiying glass thing to seen on screen the changes which at least to me don't make much sense. Not even 30 minutes ago the project guide told me that we could use "DMP 6050" and it would be a better to use as a library, I don't know the changes it might provide, and you seem to know what you talk about.

I have seen real time graphical simulations of the MPU6050 on YouTube, but never got how to make this happen myself. I have zero experience with Arduino and little with C coding and may have jumped into cold deep water, but it's still worth the try. Could you explain to me like I'm five how to make this work? or do you have some sort of a guide?
Thanks.

RoiMan:
I didn't find anything about the A0 or how it connects because the servos pretty much connect to 3 things - pin 9, VCC and GND.

The pot, (variable resistor), connects to analog pin 0, (A0), in the original code you tried.

That's what this means:-

int potpin = 0;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin

Then this reads the pot, converts it's value from 0-1023 to 0-180 and then writes that value to the servo via the Servo library:-

val = analogRead(potpin);         
  val = map(val, 0, 1023, 0, 180);
myservo.write(val);

You only the code aspect of your problem because you dropped the most important part out, the pot that controls the servo in the example.

OldSteve:
The pot, (variable resistor), connects to analog pin 0, (A0), in the original code you tried.

That's what this means:-

int potpin = 0;  // analog pin used to connect the potentiometer

int val;    // variable to read the value from the analog pin




Then this reads the pot, converts it's value from 0-1023 to 0-180 and then writes that value to the servo via the Servo library:-


val = analogRead(potpin);       
  val = map(val, 0, 1023, 0, 180);
myservo.write(val);




You only the code aspect of your problem because you dropped the most important part out, the pot that **controls** the servo in the example.

Ah! Our guide chose that servo code and I wasn't really sure what it was meant to, but now I see what you mean. We probably wont use any knobs or switches since our robot is suposed to be 100% motion controlled, but it's useful for testing. Thank you.

RoiMan:
Ah! Our guide chose that servo code and I wasn't really sure what it was meant to, but now I see what you mean. We probably wont use any knobs or switches since our robot is suposed to be 100% motion controlled, but it's useful for testing. Thank you.

No worries.
And while on the subject, in your latest code, you no longer need this:-

int potpin = 0;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin

It's only needed if a pot is connected. Since you no longer use it, it can go....