Servo motor mg996R

I have a problem with a servo motor mg996R. I want to turn it to 90 degrees, stay one second and after this turn back to initial position, but it doesn't make a perfect rotation. I can do a rotation of 90 degrees(not perfect), but I can't turn it back.

Can you show us the Code?

The "degrees" of a servo rotation depend on the make and model of the actual servo, and may need some tweaking.

Better to use Servo.writeMicroseconds

This make a rotation of 90 degrees:
servo.write(0);
delay(500);
servo.write(180);
delay(1000);

I tried with this, but I can't make a perfect rotation. I tried with random number until I make this rotation.
servo.writeMicroseconds(1000);
delay(500);
servo.writeMicroseconds(1500);
delay(800);
servo.writeMicroseconds(2000);
delay(600);

Do you have a protractor?

You could try an iterative approach to calibration

For a simple test:

#include <Servo.h>

Servo MG996R;

const int middle = 90;

void setup() {
MG996R.attach(10); //Arduino Pin 10
}

void loop() {
for(int pos = 0; pos <= middle; pos++){
MG996R.write(pos);
delay(10);
}
delay(1000);
for(int pos = middle; pos >= 0; pos--){
MG996R.write(pos);
delay(10);
}
}

I tried. It makes a 180 rotation(not perfect), but turn to 180, make a short pause and go to 180. It doesn't turn back.

That's weird.
If you can, try an other servo or add an extra 5V voltage source to increase the current.

Please post the COMPLETE working code that you are using and describe EXACTLY what it does. You started saying you want to move 90 degrees then back but most of your code snippets go to 180. Which is it?

You're not trying to power that powerful servo from the Arduino 5V pin are you? Or through a breadboard? Either of those can cause problems.

Steve

I power the servo from Arduino 5V pin. In my project I have an arduino UNO, a servo motor mg996R(360 degrees) and an ultrasonic sensor.I want to turn it to 90 degrees, stay one second and after this turn back to initial position. This code make a 90 rotation and turn back, but not perfectly. For first 3-4 rotations it's ok, after it there is an angle deviation.

#include <Servo.h>

const int TRIG_PIN = 6;
const int ECHO_PIN = 7;
const int SERVO_PIN = 9;
const int DISTANCE_THRESHOLD = 10;

Servo servo;
float duration;
float distance;
int pos = 0;
const int middle = 90; 

float calculateDistance(){
  
  digitalWrite(TRIG_PIN, LOW); 
  delayMicroseconds(5);
  
  digitalWrite(TRIG_PIN, HIGH); 
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  
  duration = pulseIn(ECHO_PIN, HIGH); 
  distance= 0.017 * duration;
  return distance;
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(TRIG_PIN, OUTPUT); 
  pinMode(ECHO_PIN, INPUT);
  //pinMode(SERVO_PIN, OUTPUT); 
  servo.attach(SERVO_PIN);
 // servo.write(90);
}

void loop() {
  // put your main code here, to run repeatedly:
  distance = calculateDistance();
  if(distance <  DISTANCE_THRESHOLD){
  servo.attach(SERVO_PIN);

  servo.writeMicroseconds(1000);
  delay(500);
  servo.writeMicroseconds(1500);
  delay(800);
  servo.writeMicroseconds(3500);
  delay(450);

}
  else
    servo.detach();
  Serial.print("distance: ");
  Serial.print(distance);
  Serial.println(" cm");
}

Why the detach?

Please remember to use code tags when posting code.

float calculateDistance(){

Why bother returning a global variable?

If I don't use detach() the servo rotate continuous without stopping.

There's your problem then. You need a proper servo for the task, not a continuously rotating one.

You can never get accurate positional control with a continuous rotation/360 degree servo. The feed back mechanism that enables control of position has been removed to allow it to keep rotating. The write() command just changes the direction and speed of rotation. 0 full speed one way, 90 stop, 180 full speed the other way.

Get a normal MG996R (NOT a 360) and it will do what you want.

Steve

Ok, I got it. Thanks a lot! :slight_smile: