Components · 15 min read

MG996R Servo with Arduino: Torque, Current, Power Supply and Code

How to use the MG996R servo: 11 kg·cm torque and 2.5 A stall current, external 5–6 V supply, capacitor, 500–2500 µs range, fixing jitter, PCA9685 and SG90.

The MG996R servo is the go-to servo for heavy jobs in Arduino projects, thanks to its metal gears and up to 11 kg·cm of torque at 6 V. With a 55-gram body it can lift the shoulder of a robotic arm, open a heavy lid or swing a pan-tilt camera mount. That strength comes at a price, though: when it's loaded, the MG996R draws up to 2.5 A. So unlike an SG90, you can't just plug it into the Arduino's 5V pin; it needs an external 5–6 V supply, a common GND and a capacitor close to the servo. Ignore these rules and the servo jitters, the Arduino keeps resetting, and your computer may even shut down the USB port.

In this guide you'll learn to interpret the MG996R's torque and current figures with real numbers, choose the right power supply, use the 500–2500 µs range with the Servo library to find your own servo's limits, and prevent jitter and resets. Then we'll move on to ESP32 and Raspberry Pi Pico code, the PCA9685 module that drives 16 servos over two wires, choosing servos for a robotic arm, and a comparison with the SG90 and MG90S.

MG996R metal-gear servo motor
MG996R: 40.7 × 19.7 × 42.9 mm body, metal gears, a dual ball bearing and a 25-tooth output shaft. The brown wire is GND, red is positive and orange is the signal.

What is the MG996R servo and how does it work?

The MG996R is an upgraded version of TowerPro's older MG995: its redesigned control board and gears centre more reliably and leave less play. Inside the case there's a small DC motor, a metal gearbox that slows the motor down and multiplies its torque, a potentiometer that measures the angle of the output shaft, and a control board that manages them all. The board reads the width of the pulse arriving on the signal wire every 20 ms (50 Hz), compares the requested angle with the angle the potentiometer reports, and turns the motor until the difference disappears. A pulse of about 1500 µs means the centre position; shorter pulses turn the shaft one way, longer ones the other way. The 5 µs dead band in the datasheet means the servo ignores changes smaller than that. We explained how servo motors work in general in What Is a Servo Motor?.

FeatureValue
Operating voltage4.8–7.2 V (5–6 V in practice)
Stall torque9.4 kg·cm (4.8 V), 11 kg·cm (6 V) ≈ 0.92–1.08 N·m
Speed (per 60°)0.17 s (4.8 V), 0.14 s (6 V)
Idle currentAbout 10 mA (no load, shaft at rest)
Running current500–900 mA (6 V, while moving)
Stall current2.5 A (6 V)
Dead band5 µs
RotationAbout 120° with 1000–2000 µs, close to 180° with 500–2500 µs (varies from unit to unit)
Signal50 Hz (20 ms period), position set by pulse width
Gears and bearingMetal gears, dual ball bearing
Output shaft25 teeth (25T spline)
Weight and size55 g, 40.7 × 19.7 × 42.9 mm
CableAbout 30 cm; brown GND, red positive, orange signal
Operating temperature0–55 °C

What does torque mean? Reading the kg·cm rating correctly

Torque is the servo's ability to turn a load at a certain distance from its shaft, and it's measured as force × distance. 11 kg·cm means it can hold 11 kg at 1 cm from the shaft, or 1.1 kg at 10 cm; double the distance and the load it can carry is halved. To convert to newton metres, multiply by 0.098: 11 kg·cm ≈ 1.08 N·m. Here's the key detail: the datasheet value is the stall torque, the limit at which the shaft stops, the current peaks and the servo heats up. For continuous use, staying at no more than half of that value keeps the servo cool, reduces jitter and makes the gears last longer.

Arm length (shaft to load)Stall limit (6 V)Safe continuous load (50%)
2.5 cm (end of the horn)4.4 kg2.2 kg
5 cm2.2 kg1.1 kg
10 cm1.1 kg550 g
15 cmAbout 730 gAbout 365 g
20 cm550 g275 g

The table only accounts for the load at the tip. In a real mechanism, the weight of the arm itself, the other servos mounted on it and the gripper all add to the torque; you have to multiply each part's mass by its distance from the shaft and add them up. For example, if a 15 cm arm carries a 150 g gripper and a 100 g object at its end, those two alone come to 0.25 × 15 = 3.75 kg·cm; with the arm's own weight the total can reach 5 kg·cm. That's just under half of the MG996R's stall torque at 6 V, so it's the right choice. You'll find a part-by-part torque calculation with an example in the Arduino robotic arm guide.

Current: why can't the MG996R run from the Arduino's 5V pin?

At rest with no load the MG996R draws only about 10 mA (holding a load raises this with the load), but while moving the current rises to 0.5–0.9 A, and when the shaft is loaded and during the first milliseconds of every start it approaches 2.5 A. When an Arduino Uno runs from USB, the total current you can take from its 5V pin is limited by the board's 500 mA fuse, and the board itself uses part of that. The moment the servo starts, the 5 V rail sags noticeably for a few milliseconds, the processor becomes unstable and the board restarts. The computer may also shut down a USB port that sees too much current for a while.

The wires are part of the problem too. The thin jumper wires and breadboard contacts used on a breadboard easily add up to 0.2 Ω. Work it out with Ohm's law: at a 2.5 A peak, 2.5 × 0.2 = 0.5 V is lost in the wiring alone, so a 5 V supply reaches the servo as 4.5 V, and the servo gets weaker and jitters. Breadboard contacts are also designed for about 1 A. Connect the MG996R's power wires straight to a screw terminal or a soldered distribution rail instead of the breadboard, and use 20–22 AWG wire.

Number of servosWhile movingWorst case (all stalled)Recommended supply
1 MG996R0.5–0.9 A2.5 A5–6 V, at least 3 A
2 servos1–1.8 A5 A5–6 V, 5 A
4 servos2–3.6 A10 A5–6 V, 6–10 A switching adapter
6 servos (robotic arm)3–5.4 A15 A6 V, 10 A plus code that moves the servos in turn
16 servos (PCA9685)8–14 A40 ASeveral separate 6 V rails or a 20 A+ supply

Powering it right: external 5–6 V, common GND and a capacitor

  1. Choose the supply: Use a 5 V or 6 V switching adapter that can deliver the current in the table above for your number of servos. For portable projects, 4 AA NiMH cells (4.8 V) or a 2S LiPo with a step-down regulator (UBEC) set to 6 V work well.
  2. Feed the positive only to the servo: Connect the supply's positive to the MG996R's red wire; don't connect it to the Arduino's 5V pin.
  3. Join the grounds: Connect the supply's negative to both the servo's brown wire and the Arduino's GND pin. The signal is a voltage measured relative to GND, so without a common GND the servo can't understand the pulses.
  4. Connect the signal: Connect the orange wire to pin D9 on the Arduino Uno (GPIO 18 on the ESP32, GP15 on the Pico).
  5. Add a capacitor: Place a 470–1000 µF / 16 V electrolytic capacitor across the servo's power leads, as close to the servo as possible; the leg marked with the stripe goes to negative. With several servos, allow about 100 µF per servo.
  6. Power the Arduino separately: Run the board from USB or the DC jack. That way, the voltage dips caused by the servo don't reach the processor.
Don't connect a 2S LiPo (8.4 V when fully charged) directly to the MG996R; it exceeds the 7.2 V maximum and can burn the control board. A 9 V battery, on the other hand, can't supply the current at all. Connecting an electrolytic capacitor backwards can make it heat up and burst; its voltage rating should be at least twice the rail voltage (16 V for 6 V). We explained why a common GND is essential in What Is GND? and how to choose capacitors in What Is a Capacitor?.
ConnectionArduino UnoESP32Raspberry Pi Pico
Orange wire (signal)D9GPIO 18GP15
Red wire (positive)External 5–6 V positiveExternal 5–6 V positiveExternal 5–6 V positive
Brown wire (GND)Supply negative + Arduino GNDSupply negative + ESP32 GNDSupply negative + Pico GND
Capacitor (470–1000 µF)Across the servo's positive and negativeAcross the servo's positive and negativeAcross the servo's positive and negative
Potentiometer (ESP32 example)—Wiper to GPIO 34, outer legs to 3V3 and GND—
Electrolytic capacitors
An electrolytic capacitor supplies the sudden current the servo demands at start-up from its own charge, before the supply can respond. The stripe on the body marks the negative leg; 470–1000 µF / 16 V is a good starting point for the MG996R.
If you have a 12 V adapter, you can set its output to 6 V with an LM2596 module. However, the LM2596 delivers at most 3 A and gets hot at around 2 A without a heatsink, so it suits a single MG996R, whose 2.5 A stall current already reaches that limit. For more servos, choose a converter rated 5 A or more, or a powerful 5–6 V adapter directly. For battery-powered projects, you can estimate the run time with the battery life calculator.

The Servo library and the 500–2500 µs range

Arduino's Servo library comes with the IDE. When you write servo.attach(9), the library uses a default range of 544–2400 µs and maps write(0) and write(180) to those two ends; many MG996Rs fall a little short of 180 degrees in this range. To widen it, write servo.attach(9, 500, 2500). This detail matters because writeMicroseconds() can't go beyond the limits given to attach either: if you write writeMicroseconds(2500) without setting the limits, the library silently clamps it to 2400. Also, write() treats numbers below 544 as an angle and larger numbers as microseconds.

On the Arduino Uno, the Servo library supports up to 12 servos, and because it uses Timer1, analogWrite doesn't work on pins 9 and 10 while a servo is attached. Each MG996R's mechanical limit is also slightly different: the manufacturer's datasheet gives about 120 degrees of rotation with standard 1000–2000 µs pulses, while with the wider range most servos get close to 180 degrees. A servo pushed past its limit runs into its internal end stop, draws stall current, buzzes and heats up. So the first job is to find your own servo's safe pulse range with the sketch below.

C++ (Arduino IDE)
1#include <Servo.h>
2
3const byte SERVO_PIN = 9;          // turuncu sinyal kablosu / orange signal wire
4Servo servo;
5int pulseUs = 1500;                // orta konum / center position
6
7void setup() {
8  Serial.begin(115200);
9  servo.writeMicroseconds(pulseUs);      // önce darbe, sonra attach / pulse first, then attach
10  servo.attach(SERVO_PIN, 500, 2500);    // aralığı genişlet / widen the range
11  Serial.println(F("500-2500 arasi bir deger yaz / type a value between 500 and 2500"));
12}
13
14void loop() {
15  if (Serial.available()) {
16    long value = Serial.parseInt();             // yazılan sayıyı oku / read the typed number
17    while (Serial.available()) Serial.read();   // satır sonunu temizle / clear the line ending
18    if (value >= 500 && value <= 2500) {
19      int step = (value > pulseUs) ? 10 : -10;  // 10 µs adımlarla yavaşça git / move slowly in 10 µs steps
20      while (abs(value - pulseUs) >= 10) {
21        pulseUs += step;
22        servo.writeMicroseconds(pulseUs);
23        delay(5);
24      }
25      pulseUs = value;
26      servo.writeMicroseconds(pulseUs);
27      Serial.print(F("Darbe / pulse: "));
28      Serial.print(pulseUs);
29      Serial.println(F(" us"));
30    }
31  }
32}
  1. Upload the sketch, open the Serial Monitor at 115200 baud and set the line ending to New Line.
  2. Type 1500; the servo moves to the centre. Fit the horn at this moment so that it points to the centre position of your mechanism.
  3. Work towards the lower limit in 50 µs steps with values like 1000, 800 and 700. If the servo no longer moves or starts buzzing, go back 30–50 µs from the last value and note that number as MIN_US.
  4. Do the same for the upper limit with values like 2000, 2200 and 2300 to find MAX_US. You'll use these two numbers in the next sketches.

Smooth motion: code that reduces current surges and jerks

A single command like servo.write(160) throws the servo to its target at full speed, covering 60 degrees in 0.14 seconds at 6 V. Meanwhile the motor draws close to its stall current, the mechanism jerks and the object being held can fall. Splitting the movement into small steps reduces both the current peaks and the mechanical shock. The sketch below advances the servo 1 degree every 15 ms (about 67°/s), and because it uses millis(), you can do other things at the same time.

C++ (Arduino IDE)
1#include <Servo.h>
2
3const byte SERVO_PIN = 9;
4const int MIN_US = 550;            // kalibrasyonda bulduğun alt sınır / lower limit from calibration
5const int MAX_US = 2450;           // kalibrasyonda bulduğun üst sınır / upper limit from calibration
6const byte STEP_MS = 15;           // derece başına süre: 15 ms ≈ 67°/sn / time per degree: 15 ms ≈ 67°/s
7
8const int POSES[] = {20, 160, 90, 45, 135};    // sırayla gidilecek açılar / angles to visit in order
9const byte POSE_COUNT = sizeof(POSES) / sizeof(POSES[0]);
10
11Servo servo;
12int current = 90;                  // şu anki açı / current angle
13int target = 90;                   // hedef açı / target angle
14byte poseIndex = 0;
15unsigned long lastStep = 0;
16unsigned long arrivedAt = 0;
17
18int angleToUs(int angle) {
19  return map(angle, 0, 180, MIN_US, MAX_US);   // açıyı darbeye çevir / angle to pulse width
20}
21
22void setup() {
23  servo.writeMicroseconds(angleToUs(current)); // önce konum, sonra attach / position first, then attach
24  servo.attach(SERVO_PIN, MIN_US, MAX_US);
25  arrivedAt = millis();
26}
27
28void loop() {
29  unsigned long now = millis();
30
31  // Hedefe 1 derecelik adımlarla yaklaş / approach the target in 1-degree steps
32  if (current != target && now - lastStep >= STEP_MS) {
33    lastStep = now;
34    current += (target > current) ? 1 : -1;
35    servo.writeMicroseconds(angleToUs(current));
36    if (current == target) arrivedAt = now;
37  }
38
39  // Hedefte 1 sn bekle, sonra sıradaki poza geç / wait 1 s at the target, then take the next pose
40  if (current == target && now - arrivedAt >= 1000) {
41    target = POSES[poseIndex];
42    poseIndex = (poseIndex + 1) % POSE_COUNT;
43  }
44
45  // Burada başka işler de yapılabilir / other tasks can run here too
46}

The angleToUs() function maps the angle between the MIN_US and MAX_US values you found during calibration, so 0 and 180 degrees become the servo's real, safe end points. A servo doesn't remember its position while powered off, and it moves to the commanded angle at full speed as soon as it receives the first pulse. Calling writeMicroseconds() before attach() makes the library skip its default 1500 µs pulse and send your starting angle straight away; if you bring the mechanism back to the same starting pose before switching off, the jump at power-up almost disappears. Set the speed with STEP_MS: 30 ms gives a slow, smooth movement, 5 ms a fast but jerky one. If you want to drive the servo with a potentiometer, just convert the reading to an angle and write it to the target variable.

Jitter and Arduino resets: causes and fixes

SymptomLikely causeFix
The Arduino resets and the USB connection drops when the servo movesThe servo is powered from the Arduino's 5V pin and its start-up current pulls the voltage downExternal 5–6 V supply, common GND and a 470–1000 µF capacitor
The servo jitters or buzzes while standing stillWeak supply, thin wires or a load close to the stall torqueUse thick wires and a capacitor, shorten the arm or reduce the load
It keeps twitching when controlled with a potentiometerNoise of a few counts in the analog readingAdd a smoothing filter and a 2-degree dead band
The servo moves randomly or doesn't respond at allThe external supply's GND isn't connected to the ArduinoConnect the supply's negative to the Arduino's GND pin
It buzzes and heats up at the endsThe pulse range exceeds the servo's mechanical limitNarrow MIN_US and MAX_US through calibration
It twitches when used with NeoPixel, SoftwareSerial or IR librariesThese libraries briefly disable interrupts, so the pulse length driftsMove the servo to a PCA9685 or use a board with hardware PWM
The ESP32 prints "Brownout detector was triggered" and restartsThe servo and the ESP32 share the same weak supplyPower the servo from a separate supply and join the grounds
Clicking and slipping under loadA gear tooth is broken or the plastic horn is strippedReplace the gear set, use a metal 25T horn and the centre screw
Torque far below the rated valueA poor-quality copy or a low supply voltageTry 6 V, buy from a reliable seller and keep a 50% margin
If the servo doesn't need to hold a load, you can cut the signal with servo.detach() once it reaches the target; the servo goes quiet and draws almost no current. But without a signal it also loses its holding torque, so don't use detach on load-bearing joints like a robotic arm's shoulder. You'll find all the causes of resets and a diagnostic sketch in Arduino keeps resetting, and the ESP32 equivalent in ESP32 brownout error.

Controlling the MG996R with an ESP32

The standard Arduino Servo library doesn't work on the ESP32; install the ESP32Servo library from the Library Manager. It's used almost the same way: you set the period with setPeriodHertz(50), and the library doesn't accept limits outside 500–2500 µs. The ESP32's signal output is 3.3 V, and the vast majority of MG996Rs read it without trouble; if your servo doesn't respond or behaves erratically, add a logic level converter to the signal line. In the example below, a potentiometer connected to GPIO 34 turns the servo. Because the ESP32's ADC is 12-bit, readings range from 0 to 4095 and are a little noisy, which is why the code uses filtering and a dead band.

C++ (Arduino IDE)
1#include <ESP32Servo.h>
2
3const int SERVO_PIN = 18;          // servo sinyali / servo signal
4const int POT_PIN = 34;            // pot orta bacağı (ADC1) / pot wiper (ADC1)
5const int MIN_US = 500;            // ESP32Servo bu aralığın dışına çıkmaz / ESP32Servo stays within 500–2500
6const int MAX_US = 2500;
7
8Servo servo;
9float smooth = 0;                  // süzülmüş pot değeri / filtered pot value
10int lastAngle = -1;
11
12void setup() {
13  Serial.begin(115200);
14  ESP32PWM::allocateTimer(0);              // servo için zamanlayıcı ayır / reserve a timer for the servo
15  servo.setPeriodHertz(50);                // 50 Hz = 20 ms periyot / 20 ms period
16  servo.attach(SERVO_PIN, MIN_US, MAX_US);
17  smooth = analogRead(POT_PIN);
18}
19
20void loop() {
21  smooth += (analogRead(POT_PIN) - smooth) * 0.1;   // ADC gürültüsünü süz / filter ADC noise
22  int angle = map((int)smooth, 0, 4095, 0, 180);    // 12 bit ADC: 0–4095
23  if (abs(angle - lastAngle) >= 2) {                // ölü bant: titremeyi keser / deadband stops jitter
24    servo.write(angle);
25    lastAngle = angle;
26    Serial.println(angle);
27  }
28  delay(20);
29}

MG996R with the Raspberry Pi Pico (MicroPython)

On the Raspberry Pi Pico you don't need an extra library: set the PWM to 50 Hz and give the pulse width in nanoseconds with duty_ns(); 500 µs means 500000 ns. The Pico's signal is 3.3 V as well. Don't power the servo from the Pico's VBUS or VSYS pin; the current on these pins comes from the computer's USB port, and the MG996R's peak current will restart the Pico. Power the servo from an external supply and join the grounds. The code below moves the servo smoothly, degree by degree, between three positions.

MicroPython
1from machine import Pin, PWM
2import time
3
4MIN_NS = 500000                   # 500 µs = 0 derece / 0 degrees
5MAX_NS = 2500000                  # 2500 µs = 180 derece / 180 degrees
6
7servo = PWM(Pin(15))              # turuncu kablo GP15'e / orange wire to GP15
8servo.freq(50)                    # 50 Hz servo sinyali / 50 Hz servo signal
9
10def write_angle(angle):
11    angle = max(0, min(180, angle))                           # 0–180 ile sınırla / clamp to 0–180
12    servo.duty_ns(MIN_NS + (MAX_NS - MIN_NS) * angle // 180)  # açıyı darbeye çevir / angle to pulse
13
14def move_slow(start, end, ms_per_degree=15):
15    step = 1 if end > start else -1
16    for a in range(start, end + step, step):  # 1 derecelik adımlar / 1-degree steps
17        write_angle(a)
18        time.sleep_ms(ms_per_degree)
19
20write_angle(90)                   # ortadan başla / start at the center
21time.sleep(1)
22
23while True:
24    move_slow(90, 170)
25    time.sleep(1)
26    move_slow(170, 10)
27    time.sleep(1)
28    move_slow(10, 90)
29    time.sleep(1)

16 servos with a PCA9685: lots of MG996Rs over two wires

When the number of servos grows, or when you work with libraries that disable interrupts, the PCA9685 module makes life easier. This board is a 16-channel, 12-bit PWM generator that talks to the Arduino over I2C using only the SDA and SCL wires. Because it generates the pulses with its own clock, the signal stays steady even while the processor is busy with other work. Its default address is 0x40; by changing the address with the A0–A5 solder jumpers on the board, you can connect 62 boards to the same bus, which means 992 servos in theory. At 50 Hz, the 20 ms period is divided into 4096 steps, and one step is about 4.9 µs: 500 µs is about 102 steps and 2500 µs about 512.

PCA9685 pinArduino UnoESP32Raspberry Pi Pico
GNDGNDGNDGND
VCC (chip power only)5V3V33V3
SDAA4GPIO 21GP4
SCLA5GPIO 22GP5
V+ terminal (servo power)External 5–6 VExternal 5–6 VExternal 5–6 V
OELeave unconnectedLeave unconnectedLeave unconnected
C++ (Arduino IDE)
1#include <Wire.h>
2#include <Adafruit_PWMServoDriver.h>
3
4Adafruit_PWMServoDriver pca = Adafruit_PWMServoDriver(0x40);   // varsayılan adres / default address
5
6const byte SERVO_COUNT = 16;
7const uint16_t MIN_US = 500;       // kalibrasyonla daralt / narrow it after calibration
8const uint16_t MAX_US = 2500;
9
10uint16_t angleToUs(float angle) {
11  return MIN_US + (uint16_t)(angle * (MAX_US - MIN_US) / 180.0);
12}
13
14void setup() {
15  pca.begin();
16  pca.setOscillatorFrequency(27000000);   // kartın gerçek saatine yakın / close to the real board clock
17  pca.setPWMFreq(50);                     // servolar için 50 Hz / 50 Hz for servos
18  delay(10);
19  for (byte ch = 0; ch < SERVO_COUNT; ch++) {
20    pca.writeMicroseconds(ch, angleToUs(90));   // hepsini ortala / center them all
21    delay(200);                                 // sırayla başlat: akım darbesini dağıt / one by one: spread the current surge
22  }
23}
24
25void loop() {
26  // Dalga: her servo komşusundan biraz geride / wave: each servo slightly behind its neighbour
27  float t = millis() / 1000.0;
28  for (byte ch = 0; ch < SERVO_COUNT; ch++) {
29    float angle = 90 + 40 * sin(t * 2.0 - ch * 0.4);   // 50–130° arası / between 50° and 130°
30    pca.writeMicroseconds(ch, angleToUs(angle));
31  }
32  delay(20);
33}

To run the sketch, install the Adafruit PWM Servo Driver library from the Library Manager. The setOscillatorFrequency(27000000) line matters: on paper the PCA9685's internal clock is 25 MHz, but in reality it varies between about 23 and 27 MHz, and Adafruit's examples use 27 MHz. Without this setting, the pulses you set with writeMicroseconds() can be off by a few percent. Starting the servos one by one, 200 ms apart, during setup stops all 16 from drawing start-up current at once. If each servo has different limits, turn MIN_US and MAX_US into 16-element arrays and calibrate each channel. The sketch also runs unchanged on the ESP32, because there the Wire library uses GPIO 21 and 22 by default.

The PCA9685 has two separate power inputs: VCC only powers the chip, while the servos are powered from the V+ input on the screw terminal. If V+ is left empty, the board shows up on I2C but the servos don't move; never feed V+ from the Arduino's 5V pin. The thin PCB traces on cheap modules aren't designed to carry tens of amps: if you use more than 4–6 MG996Rs, connect the servos' positive and negative wires to a thick distribution rail and take only the signal from the board. Also add about 100 µF of capacitance per servo on the V+ line.

MG996R vs SG90 vs MG90S

FeatureSG90MG90SMG996R
Stall torque1.8 kg·cm (4.8 V)1.8 kg·cm (4.8 V), 2.2 kg·cm (6 V)9.4 kg·cm (4.8 V), 11 kg·cm (6 V)
Speed (per 60°)0.10 s (4.8 V)0.10 s (4.8 V), 0.08 s (6 V)0.17 s (4.8 V), 0.14 s (6 V)
Weight9 g13.4 g55 g
Size22.2 × 11.8 × 31 mm22.8 × 12.2 × 28.5 mm40.7 × 19.7 × 42.9 mm
GearsPlasticMetalMetal, dual bearing
Operating voltage4.8–6 V4.8–6 V4.8–7.2 V
Stall currentAbout 0.6–0.75 AAbout 0.7–1 A2.5 A (6 V)
From the Arduino's 5V pinOne servo, light loadOne servo, light loadNo, always an external supply
Typical useFirst experiments, pan-tilt, gripperWrist, gripper, small robotsRobotic arm shoulder, heavy lid, steering

The load and the arm length decide. If you're turning a part that weighs a few grams or just experimenting, the SG90 is enough. If you want the same size with shock-resistant metal gears, pick the MG90S. If the torque you need exceeds 1 kg·cm, for example carrying 100 g at the end of a 10 cm arm, move up to the MG996R. The MG996R has about five times the torque of the SG90, but it's slower, six times heavier and draws three to four times more current, so plan the power supply and the mechanical mounting accordingly. If 11 kg·cm still isn't enough, look at bigger servos in the 20 kg·cm class such as the DS3218.

SG90
SG90
MG90S
MG90S
MG996R
MG996R

Choosing servos for a robotic arm

  • Base: MG996R. Don't put the whole weight of the arm on the servo shaft; add a bearing to the base so the servo only has to rotate it.
  • Shoulder: This is the joint under the most strain. Use an MG996R; if the arm is longer than 20 cm, add a 20 kg·cm class servo or a counterweight.
  • Elbow: MG996R. Moving the heavy servo to shoulder level and driving the elbow with a push rod reduces the load on the shoulder.
  • Wrist and wrist rotation: An MG90S is enough; using an MG996R here just adds weight for the shoulder to carry.
  • Gripper: SG90 or MG90S. Set the closing angle to the point where the fingers just touch the object; a servo that keeps trying to squeeze draws stall current.
  • Mounting: Fit a metal horn on the MG996R's 25-tooth shaft and secure it with the centre screw; plastic horns strip quickly at this torque.

MG996R project ideas

  • Robotic arm: A 6-servo arm with MG996Rs at the base, shoulder and elbow and MG90S servos at the wrist and gripper; see the robotic arm guide for the build.
  • Pan-tilt camera: Rotate an ESP32-CAM module horizontally and vertically with two MG996Rs.
  • Solar tracker: Find the direction of the light with four LDRs and turn a small panel towards the sun with an MG996R; details in the solar tracker article.
  • Smart trash can: A smart trash can that opens a heavy lid when a hand approaches.
  • Card door lock: Pull a bolt with an MG996R when the right card is scanned on an RFID RC522.
  • Joystick-controlled crane: A small crane or digger that moves on two axes with a joystick.
  • Continuous drive: A slow but powerful wheel using the 360-degree version of the MG996R; the difference is explained in the 360-degree servo article.

When it's powered properly, the MG996R is a tough, inexpensive motor that easily takes on jobs small servos can't handle. Remember the rules: an external 5–6 V supply, a common GND, a capacitor close to the servo, a calibrated pulse range and smooth motion, and a PCA9685 once the servo count grows. In the BlueGrays app you'll find projects such as servo control with a potentiometer and a joystick, an ESP32 RFID door lock with a servo and a 32-servo choreography, each with a step-by-step circuit diagram and ready-to-use code.

Frequently asked questions

How much weight can an MG996R lift?

The MG996R's torque is 11 kg·cm at 6 V, which means 11 kg at 1 cm from the shaft or 1.1 kg at 10 cm. That's the stall limit where the servo stops, so plan on half of it for continuous use. In other words, it comfortably holds about 500 g at the end of a 10 cm arm.

What voltage does the MG996R need, and can I use 12 V?

According to the datasheet, the operating range is 4.8–7.2 V; in practice 5 V or 6 V is used, and 6 V gives more torque and speed. 12 V, or a 2S LiPo at 8.4 V when fully charged, will burn the servo's control board. If you have a higher-voltage source, bring it down to 6 V with a step-down converter such as the LM2596.

How many amps does the MG996R draw, and what power supply do I need?

It draws about 10 mA at rest with no load, 0.5–0.9 A while moving and up to 2.5 A when loaded and at start-up. Choose a 5–6 V adapter that delivers at least 3 A for one servo and 6–10 A for four servos. Don't forget to connect the supply's negative to the Arduino's GND pin.

Does the MG996R rotate 180 degrees, and is there a 360-degree version?

The standard MG996R is a positional servo: the manufacturer specifies about 120 degrees with standard pulses, and with a 500–2500 µs range most units get close to 180 degrees. The 360-degree version sold under the same name doesn't go to an angle; it spins continuously, changing speed and direction according to the signal. When buying, check whether the listing says 180° or 360°.

Why does my MG996R servo jitter or reset the Arduino?

The cause is almost always the power supply: when the servo is powered from the Arduino's 5V pin, its peak current pulls the voltage down and the board restarts. Use an external 5–6 V supply, a common GND and a 470–1000 µF capacitor close to the servo. For jitter while standing still, use thick wires, smooth the potentiometer readings and keep the pulse range within the servo's mechanical limits.

What's the difference between the MG996R and the MG995?

Both servos are the same size and are wired the same way; the MG996R is an improved version of the MG995. Thanks to its redesigned control board and gears, it offers a narrower dead band, steadier centring and slightly more torque. Choose the MG996R for new projects; it's a direct replacement for an old MG995.

See all projects
Using a Servo Motor
#35Beginner
Premium

Using a Servo Motor

The arm of a small servo motor turns to three positions in turn: all the way to the start, right to the middle and all the way to the end, waiting two seconds at each stop. The Arduino tells the motor

4.7(48)
67
Servo Motor Operation with Potentiometer
#36Beginner
Premium

Servo Motor Operation with Potentiometer

As you turn the potentiometer knob, the servo motor's arm turns right along with it: one end of the knob means zero degrees, the other end means half a turn. The Arduino keeps reading the knob's posit

4.6(37)
52
Servo Control with Joystick
#60Intermediate
Premium

Servo Control with Joystick

Steer two motors with a joystick, just like turning a security camera. Push the stick left or right and the bottom servo motor slowly turns, push it up or down and the top servo tilts up and down; let

4.7(42)
58
ESP32 Servo Motor (Potentiometer Control)
#118Intermediate
Premium

ESP32 Servo Motor (Potentiometer Control)

In this project, we control an SG90 servo motor using a potentiometer. We adjust the servo angle by mapping the analog value read from the potentiometer to the 0–180-degree range. The ESP32Servo library generates servo signals on suitable output-capable GPIO pins of the ESP32; this project uses GPIO 18. This is a fundamental control method for robotic arms, camera gimbals, and automatic door mechanisms.

4.3(29)
42
ESP32 RFID Door Lock (RC522 + Servo + OLED + Buzzer + LED)
#137Advanced
Premium

ESP32 RFID Door Lock (RC522 + Servo + OLED + Buzzer + LED)

We’re building a smart door lock using an ESP32, an RC522 RFID module, an SG90 servo motor, an SSD1306 OLED display, an active buzzer, and 2 LEDs. When a card is scanned, its UID is compared to the list of authorized cards stored in the code—if authorized, the servo motor rotates to unlock the door (green LED + 2 short beeps), and the door automatically locks again after 5 seconds. For an unauthorized card, the red LED lights up, a warning is given with 3 rapid beeps, and the captured UID is dis

4.8(9)
15
Servo Circle Choreography - Animated Patterns with 32 Servos
#102Advanced
Premium

Servo Circle Choreography - Animated Patterns with 32 Servos

A visual animation project using 32 servo motors arranged in a circle on an Arduino Mega. The servos are managed in a single array, connected to Mega's pins 22-53, and exhibit four different motion sequences: a chaotic vibration where all servos move at random angles, a synchronous sweep where they all move at the same time, a smoothly rotating wave around a circle, and finally a compass needle swinging left and right. The swirling wave effect is created by the rotation of each servo relative to

4.5(40)
62
Obstacle Avoidance Robot
#81Advanced
Premium

Obstacle Avoidance Robot

How about building a smart vehicle that finds its own way? The Obstacle Avoidance Robot constantly scans its surroundings thanks to the ultrasonic sensor in front of it. When it encounters an obstacle

5.0(38)
49