Sep 6, 2026

Build a 6-DOF Robotic Arm: A Complete Arduino Parts List and Working Code Guide

5 min readIntermediate

A robotic arm is still one of the best entry points into robotics if you already have some scripting or automation background, since it combines mechanical assembly, motor control, and code in a project small enough to finish in a weekend. This is a real, current parts list and working build, not a theoretical overview: everything below is off-the-shelf hardware and code you can run as written.

What you actually need

  • A 6-DOF (six degree of freedom) acrylic or aluminum robotic arm kit. These ship as a bare mechanical frame with mounting hardware, no electronics, and are widely sold under names like “6DOF robotic arm kit” on Amazon or AliExpress, typically $30 to $60.
  • 5x MG996R metal-gear servo motors (base rotation, shoulder, elbow, wrist rotation, wrist tilt) plus 1x SG90 micro servo for the gripper. MG996R servos draw real current under load, which is why the next item matters.
  • A PCA9685 16-channel PWM servo driver board (the Adafruit version or any of the widely available clones). This offloads servo timing from the Arduino and, more importantly, lets you power the servos from a separate supply.
  • An Arduino Uno R3 (or clone) as the controller.
  • A dedicated 5V to 6V, 5A+ external power supply for the servos. Do not power MG996R servos from the Arduino’s 5V pin: they can draw enough current under stall to brown out the board.
  • Breadboard, jumper wires, and a small screwdriver set for assembly.

Assembly order

  1. Build the mechanical frame following the kit’s included diagram, but don’t attach the servo horns yet.
  2. Power each servo individually (briefly, via the PCA9685 with nothing attached) and center it at 90 degrees before mounting its horn. Mounting a servo horn at the wrong starting position is the single most common assembly mistake, since it silently limits your usable range of motion in one direction.
  3. Attach horns at the centered position, then assemble the arm around them.

Wiring

The PCA9685 talks to the Arduino over I2C, which only needs four wires total regardless of how many servos you’re driving:

PCA9685 VCC  -> Arduino 5V   (logic power, small draw)
PCA9685 GND  -> Arduino GND
PCA9685 SDA  -> Arduino A4
PCA9685 SCL  -> Arduino A5

PCA9685 V+   -> External 6V supply positive
PCA9685 GND  -> External 6V supply negative (shared/common ground with Arduino GND)

Servo 1 (base)   -> PCA9685 channel 0
Servo 2 (shoulder) -> PCA9685 channel 1
Servo 3 (elbow)    -> PCA9685 channel 2
Servo 4 (wrist rot) -> PCA9685 channel 3
Servo 5 (wrist tilt) -> PCA9685 channel 4
Servo 6 (gripper)   -> PCA9685 channel 5

The shared ground between the external supply and the Arduino is not optional. Without a common ground reference, the PWM signal from the Arduino has no consistent voltage baseline the servos can read, and movement becomes erratic or stops entirely.

Real working code

Install the Adafruit PWM Servo Driver library through the Arduino IDE Library Manager, then upload this:

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);

#define SERVOMIN  102   // pulse length for 0 degrees, tune per servo
#define SERVOMAX  512   // pulse length for 180 degrees, tune per servo

int baseCh = 0, shoulderCh = 1, elbowCh = 2, wristRotCh = 3, wristTiltCh = 4, gripperCh = 5;

void setup() {
  pwm.begin();
  pwm.setPWMFreq(50); // standard analog servo frequency
  delay(10);
  moveTo(baseCh, 90);
  moveTo(shoulderCh, 90);
  moveTo(elbowCh, 90);
  moveTo(wristRotCh, 90);
  moveTo(wristTiltCh, 90);
  moveTo(gripperCh, 30); // gripper open
}

void moveTo(int channel, int angle) {
  int pulse = map(angle, 0, 180, SERVOMIN, SERVOMAX);
  pwm.setPWM(channel, 0, pulse);
}

void pickAndPlace() {
  moveTo(shoulderCh, 60);
  moveTo(elbowCh, 120);
  delay(800);
  moveTo(gripperCh, 80);   // close gripper
  delay(500);
  moveTo(shoulderCh, 90);
  moveTo(elbowCh, 90);
  moveTo(baseCh, 150);     // rotate to drop-off point
  delay(800);
  moveTo(gripperCh, 30);   // open gripper, release object
  delay(500);
  moveTo(baseCh, 90);      // return to start
}

void loop() {
  pickAndPlace();
  delay(3000);
}

The SERVOMIN and SERVOMAX values are a starting point, not a guarantee. Every servo has slightly different endpoints, so calibrate each one individually with a short test sketch before trusting the full sequence, or you risk driving a joint past its mechanical limit and stripping a gear.

Getting from “it moves” to “it’s actually useful”

Once the basic sequence works, the natural next step is driving the arm from a computer instead of a hardcoded loop. Send angle commands over serial from a Python script on a Raspberry Pi or laptop, and you can trigger movements from a webcam-based object detector, a voice command, or a simple web UI, turning the fixed pick-and-place demo above into something that responds to real input.

Frequently asked questions

Do I need the PCA9685, or can I wire servos directly to the Arduino?
For one or two small servos, direct wiring works. For five or six MG996R servos, you’ll run out of Arduino pins capable of clean PWM output, and more importantly you’ll overload the board’s onboard 5V regulator. The PCA9685 solves both problems and is worth the roughly $5 to $10 it costs.

Is this still a relevant project to learn from, or has it been replaced by pre-built robot arms?
It’s still one of the most commonly recommended starting projects in hobbyist robotics communities, precisely because it teaches PWM control, power budgeting, and inverse kinematics concepts at a small, affordable scale before you’d apply the same ideas to a larger or commercial platform.