MG995 servo rotates only 90 degrees

I am trying to work with MG995 servo after previous projects with SG90.
After writing servo.write(0) & (180) I was expecting 180 degrees rotation, yet I get only 90.

I measured on scope and the freq is 50 as needed. The active signal width moves from 1 to 2ms.

I doubled checked with another servo, got the same result.

Any idea what could it be?

Please read the forum posting rules.


Show us a good schematic of your proposed circuit.
Show us a good image of your ‘actual’ wiring.
Give links to components.


In the Arduino IDE, use Ctrl T or CMD T to format your code then copy the complete sketch.
Use the </> icon from the ‘reply menu’ to attach the copied sketch.

Tower's site remarks that the MG995 is widely counterfeited. Do you trust your supplier?

Using Servo.h? What does the servo.attach() look like?

Post your code. We're not good at guessing what you might have done.

Steve

The Servo library defaults are 0° = 544µs and 180° = 2400µs. Give this test sketch a shot. (servo on pin 9)

/*
 Try this test sketch with the Servo library to see how your
 servo responds to different settings, type a position
 (0 to 180) or if you type a number greater than 180 it will be
 interpreted as microseconds(544 to 2400), in the top of serial
 monitor and hit [ENTER], start at 90 (or 1472) and work your
 way toward zero (544) 5 degrees (or 50 micros) at a time, then
 toward 180 (2400). 
*/
#include <Servo.h>
Servo servo;

void setup() {
  // initialize serial:
  Serial.begin(9600); //set serial monitor baud rate to match
                                   // and line ending to newline
  servo.write(90);
  servo.attach(9);
  prntIt();
}

void loop() {
  // if there's any serial available, read it:
  while (Serial.available() > 0) {

    // look for the next valid integer in the incoming serial stream:
    int pos = Serial.parseInt();
    // look for the newline. That's the end of your input:
    if (Serial.read() == '\n') {}
    pos = constrain(pos, 0, 2400);
    servo.write(pos);
    prntIt();
  }
}
void prntIt()
{
  Serial.print("  degrees = "); 
  Serial.print(servo.read());
  Serial.print("\t");
  Serial.print("microseconds =  ");
  Serial.println(servo.readMicroseconds());
}  

Hi,

Did you have a delay or time period between those two commands?

We need to see your code?

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

Are you sure the servo does rotate to 180 deg? Out of curiosity, I looked up MG995 servo, and found several sellers, with titles stating "180 " deg. , but with "specs" stating, "60 in each direction". Must be using a rotational geometry way beyond Euclidian.

The servo (MG995) wont go 180. It moves only 90 degrees.
The control is wemos D1 mini.
The IDE is VsCode with PlatformIO. The include is servo.h, yet without the platformIO servo.h lib.

It moves nicely when I tried servo.write(0) to servo.write(180), yet only in 90 degrees span.
I also tried servo.writemicroseconds between 1000 and 2000.
I tried to lower the 1000, and higher the 2000 - no change.
When I read the servo.readmicroseconds command, I see that the write command was lower than 1000, I still read 1000. Same with higher values than 2000, so I assume that the servo.h is limiting the numbers. Is it true? should I overwrite it somehow?
I assume that the readmicorseconds command doesn't really read from the servo itself.

One more thing that bothers me: the Wemos is 3.3V, so the control signal to the servo is also 3.3V. The power for the servo is 5V. Could it be this is the source of the problem?
Should I feed the servo with 3.3V power or add voltage shifter to raise the voltage the PWM signal?

BTW - same results on SG90 servo.

If you have the same problem , it could be a programming error... If you load the example sketch you got the same result?

I can see the signal in a scope: the freq is 50hz and width is between 1-2 ms, so the programming is ok.

Correct... as far as I can recall from experimenting a few years ago, it's actually just the value of the last write, not a read as such.

It can be handy though, if the writes are the result of calculations, like adding steps of 5 say. The write could include something like say (oldpos + 5) and the read would tell you that the resulting position is 65 or whatever.

As far as I know, to do an actual read from the servo you need an extra wire, and read that on an analog pin. adafruit sell some with that extra wire.

1 Like

@yigalb

TOPIC MERGED.

Could you take a few moments to Learn How To Use The Forum.

Other general help and troubleshooting advice can be found here.
It will help you get the best out of the forum.

Hi, @yigalb
PLEASE POST THE CODE YOU ARE USING..

Tom... :smiley: :+1: :coffee::australia:
PS, Sorry but its post #13 and the OP has been asked for his/her code before.

If the OP won't post their code then we'll just have to assume they don't really want any help.

Steve

1 Like

The code is below.
Some data that may be useful:

  • IDE: VScode & PlatformIO
  • No lib from PlatformIO was included
  • The controller is WEMOS D1 Mini, so 3.3V device
  • I use scope to see the output PWM signal. It looks I think it should: freq=50Hz, width between 1-2ms depends on the servo.write() parameter.
  • The power to servo is from external power source, not from the Wemos. Only the PWM signal goes to the servo. Common ground of course.
  • Still the servo moves 90 degrees only.
  • Option 1: Servo is damaged - other servos act the same.
  • Option 2: The servo should be fed with 5V PWM signal. I added a voltage shifter. Still the same.
  • Option 3: The PWM width should be bigger than 2ms or smaller than 1. As can be seen in the code, I try that. But when reading back from the driver, it seems the driver is trimming the width to be only between 1 to 2ms. So perhaps I should stop using this driver?

Here is the code:

#include <Arduino.h>
#include <servo.h>

uint8_t const SERVO_INC   = 10;
uint8_t const SERVO_MIN   = 0;
uint8_t const SERVO_MAX   = 180;
uint8_t const SERVO_DELAY = 200;

uint8_t const SERVO1_PIN   = 4; // was0;

const int analogInPin = A0;  // ESP8266 Analog Pin ADC0 = A0
int sensorValue = 0;  // value read from the pot

bool run_endless = false;
Servo MyServo1;

int servo_jump;
int servo_angle;

void my_wait(int ms_period);

void setup(){
  Serial.begin(9600);
  Serial.println("starting  setup()");
  Serial.println(ESP.getChipId());

  pinMode(LED_BUILTIN, OUTPUT);
  MyServo1.attach(SERVO1_PIN);

  Serial.print("  ON  ");
  digitalWrite(LED_BUILTIN, LOW);
  MyServo1.write(SERVO_MAX);
  delay(1000);
  //yig_wait(1000);

  Serial.print("  OFF  ");
  digitalWrite(LED_BUILTIN, HIGH);
  MyServo1.write(SERVO_MIN);
  delay(1000);
  //yig_wait(1000);   

  servo_jump = int((SERVO_MAX-SERVO_MIN)/SERVO_INC);
  Serial.print("servo_jump: ");
  Serial.println(servo_jump);

} // of setup


int tmp_1;
int tmp_2;
bool led_tmp = false;

void loop(){
  
    sensorValue = analogRead(analogInPin);
    // tmp_1 = map(sensorValue, 0, 1023, 1000, 2000);
    for (int i=800;i<=2200;i+=200) {
      MyServo1.writeMicroseconds(i);
      Serial.print("i: ");
      Serial.print(i);
      tmp_2 = MyServo1.readMicroseconds();
      Serial.print("   uS: ");
      Serial.println(tmp_2);
      delay(400);
    }
    delay(1000);
    if (led_tmp) {
      digitalWrite(LED_BUILTIN, LOW); // turn led on
      led_tmp = false;
    } // of if()
    else {
      digitalWrite(LED_BUILTIN, HIGH); // turn led off
      led_tmp = true;
    }
    
    return;
    

    
    //Serial.print(" ");
    Serial.print(sensorValue);
    Serial.print(" ");

    servo_angle = map(sensorValue, 0, 1023, SERVO_MIN, SERVO_MAX);
    Serial.print(servo_angle);

    MyServo1.write(servo_angle);
    tmp_1 = MyServo1.read();
    tmp_2 = MyServo1.readMicroseconds();
    Serial.print(" ");
    Serial.print(tmp_1);
    Serial.print(" ");
    Serial.println(tmp_2);


    delay(100);
    //yig_wait(5000);
  

} // of loop()



void my_wait(int ms_period) {
  unsigned long time_now = millis();
  while(millis() < time_now + ms_period){        
  } // of while()
} // of my_wait()



At least as a test of the servo yes I'd say so, and for testing use known-good code like the servo sweep example.

I just did as you suggested - same result.

Which would point to a limitation in the servo...

Hi,

What code did you use?

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

My suggestion was servo sweep, so sounds like they used that?