DIY 6-DOF Robotic Arm – 3D Print, Wire & Program Step by Step

In this tutorial, you will learn, step by step, how to build a DIY 6-DOF robotic arm entirely from scratch. Specifically, the project covers every stage of the build — from designing each part in Autodesk Inventor and 3D printing them, to wiring the electronics with an Arduino and programming real-time servo control with potentiometers.

This DIY 6-DOF robotic arm uses three MG996R high-torque servos for the heavy-lift base, shoulder, and elbow joints, and three SG90 micro servos for the lighter wrist and gripper. For example, for a primer on how these motors work, see our servo motor control guide. In turn, each servo is controlled in real time by a dedicated 10 kΩ potentiometer, and all six PWM signals are handled by a PCA9685 servo driver board over I²C — keeping the wiring clean and freeing up Arduino pins for future upgrades.

Whether you are a hobbyist building your first robot or an engineering student looking for a hands-on mechatronics project, this guide walks you through every detail with a full bill of materials, print settings, wiring diagrams, and source code. Once you are ready, you can watch the full build video below or continue reading the written tutorial.

Project Overview

Overall, the build is organized into four major phases: CAD design, 3D printing, mechanical assembly, and electronics wiring with programming. Furthermore, every 3D-printable STL file is modeled in Autodesk Inventor with precise tolerances for the servo mounts and bearing seats, so the parts fit together without modification.

On the electronics side, similarly, an Arduino Uno reads analog values from six 10 kΩ potentiometers and sends I²C commands to a PCA9685 16-channel PWM driver. In turn, the driver outputs the correct pulse widths. Consequently to each servo. As a result, this architecture keeps high servo current completely separate from the Arduino and leaves room for adding sensors or wireless modules later.

Complete Bill of Materials

Before you start, gather every component listed in the table below. As a result, having all parts on hand will prevent frustrating mid-build pauses.

6-DOF Robotic Arm Parts and Components

ItemQuantityPartDescription
11Base_1Essentially, base platform
21base_link_upper1Similarly, upper base section
31arm_link_1Specifically, first arm link
41arm_link_2Similarly, second arm link
51arm_link_3Likewise, third arm link
61gripper_baseBasically, gripper base
71Gripper_2Similarly, gripper finger
81Gear_rightGripper gear (right)
91Gear_leftGripper gear (left)
101GripperGripper assembly
114LinkGripper link parts
122SpacerGripper joint spacers
133MG996R Servo MotorEssentially, high-torque servo (base, shoulder, elbow)
143SG90 Micro Servo MotorSimilarly, micro servo (wrist, gripper)
1514ANSI B18.6.4 No.2-32 3/8″Specifically, truss head screw, No.2-32
162ANSI B18.6.4 No.2-32 1/4″Truss head screw, No.2-32
173DIN 7985 M1.6×2-ZM1.6×2 cross-recess screw
187ISO 4762 M3x16 (AS 1420)Essentially, M3×16 hex socket screw
1912ISO 4032 M3 (AS 1112)Similarly, M3 hex nut
202ANSI B18.6.4 No.2-32 1/2″Truss head screw, No.2-32
213MG955 HornHorn for MG996R
223DIN 7985 M3x6-ZM3×6 cross-recess screw
233SG90 Servo HornHorn for SG90
242ANSI B18.6.4 No.2-32 3/8″Truss head screw, No.2-32
2512ANSI B18.6.4 No.3-28 1/2″Truss head screw, No.3-28
261Ball Bearing 6806ZZ (30x42x7)Specifically, deep-groove bearing (30×42×7)
271Arduino Uno or MegaEssentially, main controller
281PCA9685 Servo Driver BoardSpecifically, 16-ch PWM driver (I²C)
29610kΩ PotentiometerCorrespondingly, analog control knob per servo
301BreadboardBasically, wiring base for potentiometers
3115V 10A Power SupplyImportantly, servo power source
321Jumper Wires (male-male)Specifically, Arduino ↔ PCA9685 connections
331Jumper Wires (male-female)Similarly, potentiometer ↔ Arduino connections
341Wooden BoardEssentially, arm mounting platform

Designing the Parts in Autodesk Inventor

The first phase is modeling every component in Autodesk Inventor. Specifically, this parametric CAD software lets you define exact dimensions, fillet edges for added strength, and verify fit before a single gram of filament is extruded. If you are new to Inventor or 3D printing, check out our Introduction to 3D Printing and 3D Design with Inventor before starting.

Essentially, two servo types drive the design constraints. The SG90 micro servos handle the lighter upper joints and gripper due to their compact footprint, while the MG996R servos power the base rotation and the two heavy-lift shoulder and elbow joints, providing the torque needed to move the full arm. The technical drawing below shows all part dimensions, sectional views, and assembly relationships — use it as your reference when checking print accuracy.

Technical drawing of a DIY 6-DOF robotic arm showing all mechanical parts, servos, and assembly dimensions

3D Printing the 6-DOF Robotic Arm Components

Once your STL files are exported from Inventor, it is time to fire up the 3D printer. For this project, PLA filament is recommended because of its ease of printing and good detail reproduction. For best results, therefore, use a layer height of 0.2 mm and at least 40% infill for structural parts like the base and arm links.

In particular, pay special attention to the servo mount pockets — they need to be dimensionally accurate so that the motors press-fit snugly. After printing, therefore, perform light post-processing: remove support material, sand mating surfaces, and test-fit each servo before moving on to assembly.

3D printed PLA components of the 6-DOF robotic arm laid out before assembly
Overview of all 3D printed robotic arm parts ready for assembly

Assembling Your DIY 6-DOF Robotic Arm

Once every part is printed and test-fitted, you can begin the hands-on assembly. Therefore, work through each step in order — the arm is built from the base up. Additionally, test each joint for smooth rotation before proceeding to the next step.

Installing the MG996R servo motor into the 3D printed base mount

Step 1: Assembling the Base

Above all, the base is the foundation of the entire arm, so accuracy here is critical.

  • Securing the Servo Motor — Install the first MG996R servo into the base mount using the included screws (or M3×12 cross-head self-tapping screws). Essentially, this servo provides the rotational base movement for the arm.
  • Adding the Ball Bearing (6806ZZ, 30×42×7 mm) — Press-fit the deep-groove ball bearing into its seat on the base. Specifically, the bearing sits between the fixed base plate and the rotating upper platform, reducing friction and extending the life of the joint.
  • Connecting the Servo Horn — Attach the servo horn to the rotating upper platform using M2×12 self-tapping screws. Above all, make sure the connection is tight — this horn transmits all rotational force from the servo to the rest of the arm above it.
Installing ball bearing 6806ZZ into the robotic arm base for smooth rotation
Attaching the servo horn to the rotating upper section of the robotic arm base

Step 2: Mounting Servo Horns to Arm Links

Next, align each servo horn with its corresponding arm link attachment point, then secure with two screws per horn. In particular, make sure the holes line up perfectly — a misaligned horn will cause binding and uneven movement, so double-check every connection before tightening fully.

Mounting servo horns to the robot arm links using alignment screws

Step 3: Mounting Servo Motors to Arm Links

Then, seat each servo motor into its 3D-printed pocket on the arm link, ensuring the correct orientation. Then, fasten with two screws per motor and test stability by applying gentle pressure — the servo should not shift or rock at all. Indeed, a solid motor mount is essential for precise, repeatable arm movements.

Servo motors mounted securely to the 3D printed arm links

Step 4: Connecting the Arm Links

Subsequently, join the individual link-and-servo assemblies together. First, position the horn on one link so it slots into the attachment point of the next link, then secure with screws. Finally, tighten evenly to maintain structural continuity and fluid joint articulation across the entire arm.

Connecting the robot arm links together to form the articulated joint structure

Step 5: Assembling the Gripper

Next, attach the gripper sub-assembly to the arm’s end link. Specifically, the gripper uses an SG90 micro servo with a pair of 3D-printed gears to open and close the fingers. Additionally, use M3×20 screws for the gripper joints and verify that the fingers move freely without binding.

Assembling the gripper mechanism with gears and SG90 micro servo

Step 6: Securing the Arm to a Wooden Base

Lastly, mount the fully assembled arm onto a flat wooden board using M3×12 self-tapping screws. As a result, a solid base prevents the arm from tipping during fast movements and provides a convenient platform for attaching the breadboard and power supply later.

Fully assembled 6-DOF robotic arm mounted on a wooden base platform
Securing the robotic arm to the wooden base with mounting screws

Wiring the 6-DOF Robotic Arm: Arduino and Servo Driver

Once the mechanical build of your DIY 6-DOF robotic arm is complete, it is time to wire the electronics. Essentially, the control system has three main elements: the Arduino Uno (or Mega) as the microcontroller, the PCA9685 servo driver board for generating PWM signals, and six 10 kΩ potentiometers for user input.

Components and Wiring Guide

  • Arduino Uno / Mega — Essentially, the main controller. Essentially, it reads potentiometer values and sends I²C commands to the PCA9685.
  • PCA9685 Servo Driver Board — An I²C-controlled, 16-channel PWM driver. Furthermore, it handles all six servo signals, leaving room for expansion later.
  • 5 V 10 A Power Supply — Importantly, provides dedicated power to the servos through the PCA9685 V+ terminal. Importantly, never power six servos from the Arduino’s 5 V pin — it cannot supply enough current.
  • 6 × 10 kΩ Potentiometers — Correspondingly, connected to Arduino analog pins A0–A5. Essentially, turning a knob changes the voltage, which the Arduino reads as a value from 0 to 1023.
  • Breadboard and Jumper Wires — Essentially, used to organize potentiometer connections cleanly.

Wiring Steps

  1. PCA9685 → Arduino: First, connect VCC to 5 V, GND to GND, SDA to A4, and SCL to A5. Similarly, on the Mega, SDA and SCL use pins 20 and 21 respectively.
  2. Servos → PCA9685: Next, plug each servo’s 3-pin connector into channels 0–5 on the PCA9685. Also, make sure the ground wire (brown or black) aligns with the bottom row of headers.
  3. Potentiometers → Arduino: Then, wire the outer legs of each pot to 5 V and GND on the breadboard, and connect the center (wiper) pin to A0 through A5.
  4. Servo Power Supply: Finally, connect the 5 V 10 A supply to the PCA9685 V+ and GND screw terminals. As a result, this keeps high servo current completely separate from the Arduino.
Complete wiring diagram for the 6-DOF robotic arm with Arduino and PCA9685 servo driver

Why the 6-DOF Robotic Arm Needs a PCA9685 Servo Driver

So, why not just drive servos straight from the Arduino? You can — however, it quickly becomes limiting. After all, the Arduino Uno has only six PWM-capable pins, and the built-in Servo library can conflict with other timer-dependent features like tone() or certain communication protocols.

Instead, the PCA9685 solves this by offloading all PWM generation to a dedicated chip. Specifically, it communicates over the I²C bus using just two wires (SDA and SCL) regardless of how many servos you control. Moreover, a single board handles 16 channels, and you can daisy-chain up to 62 boards for a theoretical maximum of 992 servos.

PCA9685 Pinout Reference

  • GND — Essentially, common ground shared with the Arduino.
  • OE (Output Enable) — By default, active low. Therefore, leave unconnected to keep all outputs enabled by default.
  • SCL — Specifically, I²C clock line for synchronization.
  • SDA — Similarly, I²C data line for communication.
  • VCC — Specifically, logic power at 3.3–5 V. Notably, powers only the PCA9685 chip, not the servos.
  • V+ — Importantly, servo power rail (up to 6 V). Then, connect your external supply here via the polarized screw terminal.

Consequently, each channel on the board has a 3-pin header that accepts a standard servo connector directly, making wiring quick and error-proof.

PCA9685 servo driver board pinout and connection diagram for Arduino

Programming the 6-DOF Robotic Arm for Servo Control

Ultimately, the Arduino sketch ties everything together. Essentially, it reads the voltage on each analog pin, converts it into a servo pulse width, and sends the result to the PCA9685. Below is how the key logic works, step by step.

How the Code Works

  1. Library Initialization — First, the sketch includes Wire.h for I²C and Adafruit_PWMServoDriver.h for the PCA9685. In setup(), it calls pwm.begin() and sets the PWM frequency to 60 Hz — the standard refresh rate for hobby servos.
  2. Reading the Potentiometers — Inside loop(), Next, analogRead(A0) through analogRead(A5) returns a value between 0 and 1023, corresponding to the knob position.
  3. Subsequently, mapping to Servo Pulse — The map() function converts the 0–1023 range into a 125–575 tick range. These tick values represent the minimum and maximum pulse widths the PCA9685 outputs at 60 Hz (roughly 1 ms to 2.3 ms), which correspond to the servo’s full rotation range.
  4. Then, setting the PWM Outputpwm.setPWM(channel, 0, ticks) In turn, sends the computed pulse to the correct PCA9685 channel. The second parameter (0) is the “on” tick, and the third is the “off” tick within the 4096-step PWM cycle.
  5. Loop Delay — Finally, a 20 ms delay at the end of each loop keeps the refresh rate smooth and prevents flooding the I²C bus.

Finally, upload the following sketch to your Arduino Uno (or Mega). Make sure the Adafruit PWM Servo Driver Library is installed via the Arduino Library Manager before compiling.

Arduino Sketch: Full Source Code

/**
 * Author: Omar Draidrya
 * Date: 2024/05/05
 * Controls 6 servos via PCA9685 with potentiometer input.
 */
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); // Default address 0x40
void setup() {
    Serial.begin(9600);           // First, init serial.
    pwm.begin();                  // Then, init PCA9685.
    pwm.setPWMFreq(60);           // Specifically, 60 Hz for servos.
}
void loop() {
    // Servo 0
    int potValue0 = analogRead(A0);           // First, read A0
    int servoPos0 = map(potValue0, 0, 1023, 125, 575); // Map to pulse range
    pwm.setPWM(0, 0, servoPos0);              // Set servo 0
    // Servo 1
    int potValue1 = analogRead(A1);           // Then, read A1
    int servoPos1 = map(potValue1, 0, 1023, 125, 575); // Map to pulse range
    pwm.setPWM(1, 0, servoPos1);              // Set servo 1
    // Servo 2
    int potValue2 = analogRead(A2);           // Similarly, read A2
    int servoPos2 = map(potValue2, 0, 1023, 125, 575); // Map to pulse range
    pwm.setPWM(2, 0, servoPos2);              // Set servo 2
    // Servo 3
    int potValue3 = analogRead(A3);           // Next, read A3
    int servoPos3 = map(potValue3, 0, 1023, 125, 575); // Map to pulse range
    pwm.setPWM(3, 0, servoPos3);              // Set servo 3
    // Servo 4
    int potValue4 = analogRead(A4);           // Likewise, read A4
    int servoPos4 = map(potValue4, 0, 1023, 125, 575); // Map to pulse range
    pwm.setPWM(4, 0, servoPos4);              // Set servo 4
    // Servo 5
    int potValue5 = analogRead(A5);           // Finally, read A5
    int servoPos5 = map(potValue5, 0, 1023, 125, 575); // Map to pulse range
    pwm.setPWM(5, 0, servoPos5);              // Set servo 5
    delay(20);   // Finally, loop delay
}

Required Libraries

Before compiling, first install the following libraries through the Arduino IDE Library Manager: Adafruit PWM Servo Driver Library and Wire (included by default). After that, then select your board (Arduino Uno or Mega), choose the correct COM port, and click Upload.

Calibrating and Testing Your 6-DOF Robotic Arm

Once your DIY 6-DOF robotic arm is fully wired, power on the servo supply and slowly turn each potentiometer. As a result, you should see the corresponding joint move in real time. If a joint moves in the wrong direction, swap the outer wires on that potentiometer to reverse it.

Fine-tune the map() range values (125 and 575) for each servo individually. For example, some servos may need slightly different minimum and maximum tick values to avoid mechanical end-stop buzzing. Lastly, test the arm under load by picking up small objects with the gripper to confirm torque and stability.

6-DOF Robotic Arm: Conclusion and Next Steps

Congratulations — you now have, indeed, a fully functional DIY 6-DOF robotic arm built entirely from scratch. Indeed, this project covers every core discipline of mechatronics: CAD design, additive manufacturing, electronic wiring, and embedded programming.

From here, consequently, the possibilities are wide open. You could add inverse kinematics for automated positioning, integrate a Bluetooth module for wireless control (we did exactly that in our Bluetooth-controlled robotic arm upgrade), or train the arm to record and replay movement sequences. Regardless of which direction you take, this six-axis platform gives you a solid foundation for deeper exploration into robotics and automation.

7 thoughts on “DIY 6-DOF Robotic Arm – 3D Print, Wire & Program Step by Step”

  1. I am building an AI Robot and want to use your robotic arm in the build. I want to mount it on the front side vertically. I noticed on past photos there was a tension spring attached to the rotating base to the first arm piece but not listed in the parts list or build instructions. I wish to implement the spring back into the build because of its vertical placement on my robot. Can you provide me with the specifications for the spring? This robotic arm is in my opinion is one of the better designed and documented arms of its type out on the web.

    Reply
    • Thanks a lot! I’m glad you liked the design
      Yes, that tension spring connects the rotating base to the first arm segment to help support the shoulder joint, especially when the arm is mounted vertically.
      The spring is about 2 cm long (at rest) and 9 mm in diameter.
      I actually reused it from an old desk lamp stand, but you can find similar extension springs easily online or in hardware stores.
      It’s optional but really helps balance the arm and reduce servo stress.

      Spring

      Reply
  2. Hello! I wanted to ask the function of the atachment points on the base and the first link, are they for a spring? it is modelled but the pictures of the assembly don’t have this feature, nor is it referenced on the post. Thank you! this is a nice design

    Reply
    • Yes, those points are for a spring. The spring is optional — it helps the shoulder joint carry part of the arm’s weight.
      This feature was added in a later version of the design.
      You can also use a rubber band, but I personally prefer a spring.
      The one I used is about 2 cm long (at rest) and 9 mm in diameter.
      I actually took it from an old desk lamp stand, but you can easily find similar springs online or in hardware stores.
      Spring

      Reply

Leave a Comment