Zbotic Logo Zbotic Logo
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

  • Shop
  • About Us
  • Contact Us
  • Reseller
  • Blogs
020 69134444
1800 209 0998
[email protected]
Help Desk
Facebook Twitter Instagram Linkedin YouTube
Zbotic Logo Zbotic Logo
0 0

View Wishlist Add all to cart

0 0
0 Shopping Cart
Shopping cart (0)
Subtotal: ₹0.00

View cartCheckout

All departments
  • 3D Print Service
  • 3D Printer
  • Batteries & Chargers
  • Development Boards
  • Drone Parts
  • EBike parts
  • Sensor Modules
  • Electronic Components
  • Electronic Modules
  • IoT and Wireless
  • Mechanical Parts and Workbench Tools
  • Motors & Drivers & Pumps & Actuators
  • DIY and Robot Kits
  • Show more
  • Home
  • Shop
  • Sale
  • 3D Print Service
  • PCB Service
  • B2B
  • Blogs
  • Contact Us
Return to previous page
Home Electronics Basics

DIY Acrylic Robot Manipulator Mechanical Arm

DIY Acrylic Robot Manipulator Mechanical Arm

March 10, 2026 /Posted byShubham S / 0

DIY Acrylic Robot Manipulator Mechanical Arm  

Introduction:

Robotics and automation are becoming essential in industries, education, and research. Understanding how robotic arms work helps students and hobbyists learn about mechanical design, motion control, and real-world automation systems.

Traditional robotic systems can be expensive and complex for beginners. 

DIY Acrylic Robot Manipulator Mechanical Arm  

 

In this project, we build a DIY Acrylic Robot Manipulator Mechanical Arm (4-DOF) that: 

  • Provides 4 Degrees of Freedom (4-DOF) for flexible movement. 
  • Uses precision laser-cut acrylic parts for accurate assembly. 
  • Supports servo motor integration  
  • Allows hands-on experience in mechanical design and motion control. 
  • Can control through webserver. 

 

 

 

 

 


Hardware Required: 

  • DIY Acrylic Robot Manipulator Mechanical Arm Kit 
  • ESP 32 development borad
  • SG 90 9G Mini Micro Servo plastic gear 180 degrees
  • PCA9685 16-Channel 12-Bit PWM/Servo Driver I2C Interface
  • Power supply (6 volt) 

 

Note: PWM servo motor driver library — Download 


 Code:

#include <Wire.h>

#include <Adafruit_PWMServoDriver.h>

#include <WiFi.h>

#include <WebServer.h>

 

// ─── WiFi Credentials ───────────────────────────────────────────────

const char* ssid     = “Robot”;

const char* password = “12345678”;

 

// ─── PCA9685 Setup ──────────────────────────────────────────────────

Adafruit_PWMServoDriver pca = Adafruit_PWMServoDriver(0x40);

 

#define SERVO_FREQ  50

#define SERVO_MIN   102

#define SERVO_MAX   512

 

// ─── PCA9685 Channel Mapping ────────────────────────────────────────

#define BASE_CH      0

#define SHOULDER_CH  1

#define ELBOW_CH     2

#define GRIPPER_CH   3

 

// ─── Default Angles ─────────────────────────────────────────────────

int baseAngle     = 90;

int shoulderAngle = 90;

int elbowAngle    = 120;

int gripperAngle  = 100;

 

WebServer server(80);

 

// ─── Angle to PCA9685 Pulse ─────────────────────────────────────────

int angleToPulse(int angle) {

return map(angle, 0, 180, SERVO_MIN, SERVO_MAX);

}

 

void setServo(uint8_t channel, int angle) {

pca.setPWM(channel, 0, angleToPulse(angle));

}

 

// ─── Build & Send HTML Page ─────────────────────────────────────────

void handleRoot() {

String html = “”;

 

html += “<!DOCTYPE html><html lang=’en’><head>”;

html += “<meta charset=’UTF-8’/>”;

html += “<meta name=’viewport’ content=’width=device-width, initial-scale=1.0’/>”;

html += “<title>ESP32 Based 4DOF Robotic Arm</title>”;

html += “<link href=’https://fonts.googleapis.com/css2?family=Orbitron:wght@400;600;800&family=Rajdhani:wght@300;400;500… rel=’stylesheet’/>”;

html += “<style>”;

html += “:root{–c1:#B8E3E9;–c2:#93B1B5;–c3:#4F7C82;–c4:#0B2E33;}”;

html += “*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}”;

html += “body{background:var(–c4);color:var(–c1);font-family:’Rajdhani’,sans-serif;min-height:100vh;padding:20px;”;

html += “background-image:radial-gradient(ellipse at 20% 10%,rgba(79,124,130,0.3) 0%,transparent 50%),”;

html += “radial-gradient(ellipse at 80% 90%,rgba(147,177,181,0.15) 0%,transparent 50%),”;

html += “repeating-linear-gradient(0deg,transparent,transparent 40px,rgba(184,227,233,0.02) 40px,rgba(184,227,233,0.02) 41px),”;

html += “repeating-linear-gradient(90deg,transparent,transparent 40px,rgba(184,227,233,0.02) 40px,rgba(184,227,233,0.02) 41px);}”;

html += “.wrapper{max-width:620px;margin:0 auto;}”;

html += “header{text-align:center;padding:36px 0 28px;position:relative;}”;

html += “header::after{content:”;display:block;width:80px;height:2px;background:linear-gradient(90deg,transparent,var(–c3),transparent);margin:16px auto 0;}”;

html += “h1{font-family:’Orbitron’,monospace;font-size:clamp(1.1rem,4vw,1.6rem);font-weight:800;letter-spacing:0.05em;color:var(–c1);text-shadow:0 0 30px rgba(184,227,233,0.4);line-height:1.3;}”;

html += “.subtitle{font-size:0.85rem;color:var(–c3);letter-spacing:0.2em;text-transform:uppercase;margin-top:6px;font-weight:500;}”;

html += “.joint-card{background:linear-gradient(135deg,rgba(79,124,130,0.15),rgba(11,46,51,0.6));border:1px solid rgba(147,177,181,0.25);border-radius:12px;padding:22px 24px 20px;margin-bottom:16px;position:relative;overflow:hidden;backdrop-filter:blur(4px);transition:border-color 0.3s,box-shadow 0.3s;animation:slideUp 0.5s ease both;}”;

html += “.joint-card::before{content:”;position:absolute;top:0;left:0;width:4px;height:100%;background:linear-gradient(180deg,var(–c1),var(–c3));border-radius:12px 0 0 12px;opacity:0.7;}”;

html += “.joint-card:hover{border-color:rgba(184,227,233,0.45);box-shadow:0 8px 32px rgba(0,0,0,0.3);}”;

html += “.joint-card:nth-child(1){animation-delay:0.05s;}.joint-card:nth-child(2){animation-delay:0.15s;}.joint-card:nth-child(3){animation-delay:0.25s;}.joint-card:nth-child(4){animation-delay:0.35s;}”;

html += “.joint-title{font-family:’Orbitron’,monospace;font-size:0.9rem;font-weight:600;letter-spacing:0.12em;text-align:center;color:var(–c1);margin-bottom:18px;text-transform:uppercase;}”;

html += “.slider-row{display:grid;grid-template-columns:70px 1fr 70px;align-items:center;gap:10px;margin-bottom:12px;}”;

html += “.label{font-size:0.75rem;font-weight:600;letter-spacing:0.1em;text-transform:uppercase;color:var(–c2);}”;

html += “.label.left{text-align:right;}.label.right{text-align:left;}”;

html += “input[type=range]{-webkit-appearance:none;appearance:none;width:100%;height:6px;border-radius:3px;background:linear-gradient(90deg,var(–c3) var(–fill,50%),rgba(147,177,181,0.2) var(–fill,50%));outline:none;cursor:pointer;}”;

html += “input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:20px;height:20px;border-radius:50%;background:var(–c1);border:3px solid var(–c4);box-shadow:0 0 10px rgba(184,227,233,0.5),0 0 0 2px var(–c3);cursor:pointer;transition:transform 0.15s;}”;

html += “input[type=range]::-webkit-slider-thumb:hover{transform:scale(1.2);}”;

html += “.angle-display{display:flex;align-items:center;justify-content:center;gap:8px;}”;

html += “.angle-label{font-size:0.72rem;color:var(–c3);letter-spacing:0.08em;text-transform:uppercase;}”;

html += “.angle-value{font-family:’Orbitron’,monospace;font-size:1.05rem;font-weight:600;color:var(–c1);min-width:48px;text-align:center;background:rgba(79,124,130,0.2);border:1px solid rgba(147,177,181,0.3);border-radius:6px;padding:3px 10px;}”;

html += “.angle-unit{font-size:0.72rem;color:var(–c3);}”;

html += “.status-bar{text-align:center;padding:10px;margin-top:6px;font-size:0.72rem;letter-spacing:0.15em;text-transform:uppercase;color:var(–c3);}”;

html += “.dot{display:inline-block;width:6px;height:6px;border-radius:50%;background:#4CAF50;margin-right:6px;animation:blink 2s infinite;vertical-align:middle;}”;

html += “@keyframes blink{0%,100%{opacity:1;}50%{opacity:0.4;}}”;

html += “@keyframes slideUp{from{opacity:0;transform:translateY(20px);}to{opacity:1;transform:translateY(0);}}”;

html += “</style></head><body>”;

html += “<div class=’wrapper’>”;

html += “<header><h1>ESP32 Based 4DOF<br/>Robotic Arm</h1>”;

html += “<p class=’subtitle’>PCA9685 &nbsp;|&nbsp; Servo Control</p></header>”;

 

// Base card

html += “<div class=’joint-card’><div class=’joint-title’>Base</div>”;

html += “<div class=’slider-row’><span class=’label left’>Left</span>”;

html += “<input type=’range’ id=’base’ min=’0′ max=’180′ value='” + String(baseAngle) + “‘ oninput=’sendAngle(\”base\”,this.value)’ onchange=’sendAngle(\”base\”,this.value)’/>”;

html += “<span class=’label right’>Right</span></div>”;

html += “<div class=’angle-display’><span class=’angle-label’>Current Angle</span>”;

html += “<span class=’angle-value’ id=’baseVal’>” + String(baseAngle) + “</span><span class=’angle-unit’>deg</span></div></div>”;

 

// Shoulder card

html += “<div class=’joint-card’><div class=’joint-title’>Shoulder</div>”;

html += “<div class=’slider-row’><span class=’label left’>Backward</span>”;

html += “<input type=’range’ id=’shoulder’ min=’45’ max=’165′ value='” + String(shoulderAngle) + “‘ oninput=’sendAngle(\”shoulder\”,this.value)’ onchange=’sendAngle(\”shoulder\”,this.value)’/>”;

html += “<span class=’label right’>Forward</span></div>”;

html += “<div class=’angle-display’><span class=’angle-label’>Current Angle</span>”;

html += “<span class=’angle-value’ id=’shoulderVal’>” + String(shoulderAngle) + “</span><span class=’angle-unit’>deg</span></div></div>”;

 

// Elbow card

html += “<div class=’joint-card’><div class=’joint-title’>Elbow</div>”;

html += “<div class=’slider-row’><span class=’label left’>Down</span>”;

html += “<input type=’range’ id=’elbow’ min=’80’ max=’160′ value='” + String(elbowAngle) + “‘ oninput=’sendAngle(\”elbow\”,this.value)’ onchange=’sendAngle(\”elbow\”,this.value)’/>”;

html += “<span class=’label right’>Up</span></div>”;

html += “<div class=’angle-display’><span class=’angle-label’>Current Angle</span>”;

html += “<span class=’angle-value’ id=’elbowVal’>” + String(elbowAngle) + “</span><span class=’angle-unit’>deg</span></div></div>”;

 

// Gripper card

html += “<div class=’joint-card’><div class=’joint-title’>Gripper</div>”;

html += “<div class=’slider-row’><span class=’label left’>Close</span>”;

html += “<input type=’range’ id=’gripper’ min=’85’ max=’120′ value='” + String(gripperAngle) + “‘ oninput=’sendAngle(\”gripper\”,this.value)’ onchange=’sendAngle(\”gripper\”,this.value)’/>”;

html += “<span class=’label right’>Open</span></div>”;

html += “<div class=’angle-display’><span class=’angle-label’>Current Angle</span>”;

html += “<span class=’angle-value’ id=’gripperVal’>” + String(gripperAngle) + “</span><span class=’angle-unit’>deg</span></div></div>”;

 

html += “<div class=’status-bar’><span class=’dot’></span>Connected to ESP32</div>”;

html += “</div>”;

 

// JavaScript — no ‘function’ keyword issue since it’s inside a String

html += “<script>”;

html += “var mins={base:0,shoulder:45,elbow:80,gripper:85};”;

html += “var maxs={base:180,shoulder:165,elbow:160,gripper:120};”;

html += “var updateSlider=function(id,val){“;

html += ”  var mn=mins[id],mx=maxs[id];”;

html += ”  var pct=((val-mn)/(mx-mn))*100;”;

html += ”  document.getElementById(id).style.setProperty(‘–fill’,pct+’%’);”;

html += ”  document.getElementById(id+’Val’).textContent=val;”;

html += “};”;

html += “var sendAngle=function(joint,val){“;

html += ”  val=parseInt(val);”;

html += ”  updateSlider(joint,val);”;

html += ”  var xhr=new XMLHttpRequest();”;

html += ”  xhr.open(‘GET’,’/set?joint=’+joint+’&angle=’+val,true);”;

html += ”  xhr.send();”;

html += “};”;

html += “window.onload=function(){“;

html += ”  updateSlider(‘base’,” + String(baseAngle) + “);”;

html += ”  updateSlider(‘shoulder’,” + String(shoulderAngle) + “);”;

html += ”  updateSlider(‘elbow’,” + String(elbowAngle) + “);”;

html += ”  updateSlider(‘gripper’,” + String(gripperAngle) + “);”;

html += “};”;

html += “</script></body></html>”;

 

server.send(200, “text/html”, html);

}

 

// ─── /set Handler ───────────────────────────────────────────────────

void handleSet() {

if (!server.hasArg(“joint”) || !server.hasArg(“angle”)) {

server.send(400, “text/plain”, “Missing parameters”);

return;

}

 

String joint = server.arg(“joint”);

int    angle = server.arg(“angle”).toInt();

 

if (joint == “base”) {

angle = constrain(angle, 0, 180);

baseAngle = angle;

setServo(BASE_CH, angle);

} else if (joint == “shoulder”) {

angle = constrain(angle, 45, 165);

shoulderAngle = angle;

setServo(SHOULDER_CH, angle);

} else if (joint == “elbow”) {

angle = constrain(angle, 80, 160);

elbowAngle = angle;

setServo(ELBOW_CH, angle);

} else if (joint == “gripper”) {

angle = constrain(angle, 85, 120);

gripperAngle = angle;

setServo(GRIPPER_CH, angle);

} else {

server.send(400, “text/plain”, “Unknown joint”);

return;

}

 

server.send(200, “text/plain”, “OK”);

Serial.printf(“[SET] %s -> %d deg\n”, joint.c_str(), angle);

}

 

// ─── Setup ──────────────────────────────────────────────────────────

void setup() {

Serial.begin(115200);

 

// PCA9685 init — SDA=GPIO21, SCL=GPIO22 by default on ESP32

Wire.begin();

pca.begin();

pca.setOscillatorFrequency(27000000);

pca.setPWMFreq(SERVO_FREQ);

delay(10);

 

// Move servos to default positions

setServo(BASE_CH,     baseAngle);

setServo(SHOULDER_CH, shoulderAngle);

setServo(ELBOW_CH,    elbowAngle);

setServo(GRIPPER_CH,  gripperAngle);

Serial.println(“[PCA9685] Servos initialised”);

 

// WiFi connect

Serial.printf(“[WiFi] Connecting to %s”, ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {

delay(500);

Serial.print(“.”);

}

Serial.printf(“\n[WiFi] Connected! Open browser: http://%s\n”, WiFi.localIP().toString().c_str());

 

// Register routes

server.on(“/”,    handleRoot);

server.on(“/set”, handleSet);

server.begin();

Serial.println(“[HTTP] Web server started”);

}

 

// ─── Loop ───────────────────────────────────────────────────────────

void loop() {

server.handleClient();

}

 


Frequently Asked Questions (FAQs):

  • What does 4 DOF mean in this robotic arm?
    Four Degrees of Freedom (DOF) means the arm can move in four independent directions or joints. 
  • How are the servo motors controlled in this project?
    Servo motors are controlled when the ESP32 receives commands from the web server and sends them via I2C to the PCA9685, which generates the PWM signals to move the servos. 
  • How does the web server control the robotic arm?
    The ESP32 hosts a web server that sends servo angle values through HTTP requests to control each joint. 
  • Why is the servo driver used instead of connecting servos directly to ESP32?
    PCA9685 16Channel 12Bit PWM/Servo Driver allows precise PWM control and supports multiple servos without overloading the ESP32 pin.  
  • Is this suitable for engineering projects?

Yes. It demonstrates: 

  • Embedded Systems (ESP32 based control) 
  • IoT & Web-Based Wireless Control 
  • PWM-Based Servo Motor Control 
  • Robotics and Mechanical Manipulation 
  • I2C interface 

Applications of the Project: 

DIY Acrylic Robot Manipulator Mechanical Arm  

  • Educational Robotics Learning Platform 
  • Remote Robot Control using IoT 
  • Prototype for Automated Assembly Systems 
  • Motion Control learning  

 

 

At Zbotic, we support makers, students, and innovators with practical robotics kits, electronic modules, and DIY learning products designed for hands-on experimentation. This DIY Acrylic Robot Manipulator Mechanical Arm is ideal for understanding motion control, servo integration, and basic robotic mechanisms in a simple build format.

You can also explore related components such as servo motors, controller boards, jumper wires, robotic grippers, power modules, and DIY electronics accessories to expand your project further.

👉 Explore more robotics kits, electronic components, and DIY parts at zbotic.in

Tags: DIY, DIY Acrylic Robot Manipulator Mechanical Arm
Share Post
  • Facebook
  • Linkedin
  • Whatsapp
Smart Agriculture Monitoring S...
Smart Agriculture Monitoring System Using Waveshare E-Paper Display & LoRa Module
Line Following Robot with Arduino - Complete Guide
Line Following Robot with Ardu...

Related posts

Svg%3E
Read more

Coffee Roaster: Temperature Profile Controller Build

April 1, 2026 0
Table of Contents Why Build a Coffee Roaster? Roasting Temperature Profiles Components for the Build Thermocouple Placement PID Profile Controller... Continue reading
Svg%3E
Read more

Sous Vide Cooker: Precision Temperature Water Bath

April 1, 2026 0
Table of Contents What Is Sous Vide Cooking? Precision Temperature Requirements Components for the Build PID Temperature Controller Water Circulation... Continue reading
Svg%3E
Read more

Kiln Controller: High-Temperature Pottery Automation

April 1, 2026 0
Table of Contents What Is a Kiln Controller? Temperature Requirements for Ceramics Components for High-Temperature Control K-Type Thermocouple and MAX6675... Continue reading
Svg%3E
Read more

Heat Gun Controller: Temperature and Airflow Regulation

April 1, 2026 0
Table of Contents What Is a Heat Gun Controller? Temperature and Airflow Regulation Components for the Build PID Temperature Control... Continue reading
Svg%3E
Read more

Soldering Iron Station: PID Temperature Controller Build

April 1, 2026 0
Table of Contents Why Build a Soldering Station? PID Temperature Control for Soldering Components Required Thermocouple Sensing at the Tip... Continue reading

Add comment Cancel reply

Your email address will not be published. Required fields are marked

Facebook Twitter Instagram Pinterest Linkedin Youtube

Get the latest deals and more.

Download on Google Play Download on the App Store

Call us: 020 69134444 / 1800 209 0998

Monday - Saturday 09:30 AM - 06:00 PM
For Technical Supports Email: [email protected]
For Sales / Enquiries Email: [email protected]

  • My Account

    • Cart

    • Wishlist

    • Checkout

    • My Orders

    • Track Order

    • My Account

  • Information

    • FAQs

    • Blogs

    • Career

    • About Us

    • Contact Us

    • Payment Options

  • Policies

    • Privacy Policy

    • Terms & Conditions

    • GST Input Tax Credit

    • Shipping Return Policy

    • E-Waste Collection Points

    • Our Sitemap

© Zbotic.in is registered trademark of Moxie Supply Pvt Ltd – All Rights Reserved
Login
Use Phone Number
Use Email Address
Not a member yet? Register Now
Reset Password
Use Phone Number
Use Email Address
Register
Already a member? Login Now