I recently bought a couple of cheap MG996R high-torque servos on ebay, and I want to use them with my Arduino.

Arduino + MG996 + Dusty Breadboard

These have the "JR" servo pinout, so orange = signal, red = V+, brown = V-.

You control these servos by sending a 50Hz pulse width modulated signal. The pulse width determines the position of the servo. Arduino wraps this in a nice Servo library. So you can just use servo.write(<angle>) to set the servo to a certain angle. Cool!

The servo library defaults to pulsing 544ms to 2400ms for angles zero to 180. This is too wide for the MG996R, the servo only moves when you write angles through 20-150 or so. Setting the value outside this range stresses the servo and can wear it out!

I wrote a quick sketch to interactively find the real minimum and maximum values: . You just watch the serial port and follow simple prompts:

Download the sketch here.

Servo Range Sketch (running)

Using that sketch, I found my MG996R servos to have minimum pulse width around 771 and maximum around 2193 when running off 5v ((While the servo is unloaded I'm powering it from the Arduino via USB, but this won't supply enough current for a loaded servo.)). The full sweep is approximately 0-130 degrees.

So, to use the servo library with correct angles the sweep will be 771 to 2740 ((The adjusted max of 2740 is calculated as ( (MaxPW - MinPW) * (180 / MaxAngle) ) + MinPW, ie ( (2193 - 771) * (180 / 130) ) + 771)). So I can call:

servo.attach(servopin, 771, 2740);  
servo.write(0); // Min  
delay(2000);  
servo.write(65); // Midpoint  
delay(2000);  
servo.write(130); // Max

Note: If setting up the Servo range like this, it's important not to drive the servo past 130 degrees - which corresponds to pulse width 2193 and the maximum position of the servo.

EDIT 2018: Fixed a nine year old bug in the formula above, thanks Dillon and Stavros for pointing it out.

Yay Arduino!

Thoughts on “Servo pulse width range with Arduino