A delta robot is the fastest pick-and-place robot architecture in existence, capable of over 200 picks per minute in industrial settings. Unlike serial arm robots, a delta robot’s three parallel arms keep the end-effector platform in a fixed orientation, allowing only translational (XYZ) motion—which is exactly what’s needed for high-speed sorting, packaging, and dispensing. This guide covers the mechanical design, parallel kinematics theory, delta robot inverse kinematics, and servo control code for a DIY 3-arm delta build.
Table of Contents
- Delta Robot Design & Geometry
- Components for a DIY Delta
- Delta Robot Inverse Kinematics
- Workspace Calculation
- Servo Control & Trajectory Planning
- Pick & Place Sequence
- Recommended Products
- FAQ
Delta Robot Design & Geometry
A delta robot has three main assemblies:
- Base platform: Fixed frame mounted above the workspace. Contains three servo motors at 120° intervals.
- Upper arms (biceps): Rigid links from each servo shaft, all equal length (L1). These are the driven links.
- Forearms (parallelogram links): Two parallel rods per arm, connected with ball-and-socket joints (rod ends). Equal length (L2). These maintain the end-effector’s orientation.
- End-effector platform: Smaller triangle connected to all three forearms. Carries the gripper/suction cup/tool.
Key geometric parameters for a medium-size DIY delta:
- Base radius (R_base): 150 mm (distance from centre to servo pivot)
- End-effector radius (R_ee): 50 mm
- Upper arm length (L1): 120 mm
- Forearm length (L2): 240 mm
- This gives a roughly cylindrical workspace ~180 mm diameter × 100 mm tall
Components for a DIY Delta
- 3× high-speed digital servo motors (MG90D or DS3225 for stiffer response)
- 3× 3D-printed or aluminium upper arms (120 mm)
- 6× carbon fibre rods (4 mm OD, 240 mm length) — 2 per arm
- 12× M4 ball-and-socket rod end joints (stainless steel, FK series)
- 3D-printed base platform and end-effector (PLA or PETG, 3mm wall thickness)
- Arduino Mega or ESP32 as controller
- PCA9685 16-channel PWM driver (for precise servo control)
- 5V 5A power supply for servos
- Optional: mini pneumatic suction cup + vacuum pump for soft pick-and-place
Carbon fibre rods are essential — any flex introduces position error. The ball-end joints must be zero-lash (adjust the retaining nut until all play is eliminated without excessive friction).
Delta Robot Inverse Kinematics
Delta IK solves: given desired end-effector position (x, y, z), find the three servo angles (θ₁, θ₂, θ₃).
import numpy as np
# Delta geometry constants (mm)
R_BASE = 150.0 # Base triangle circumradius
R_EE = 50.0 # End-effector triangle circumradius
L1 = 120.0 # Upper arm length
L2 = 240.0 # Forearm length
# Effective offset
R_eff = R_BASE - R_EE
def arm_ik(x, y, z):
"""
Compute servo angle for ONE arm (arm 0, along -Y axis).
Other arms: rotate (x,y) by 120° and 240° before calling.
Returns servo angle in degrees (0 = horizontal, positive = up).
"""
# Point to solve for (relative to arm's pivot)
# Effective target: offset by R_eff along the arm's reference axis
y_eff = y - R_eff # For arm 0, offset in -Y direction
# The elbow must reach (x, y_eff, z)
# Use intersection of circle (radius L2 in XZ plane from elbow)
# Elbow traces a circle of radius L1 in the YZ plane
# Simplify: arm in YZ plane (x component contributes to effective distance)
h = np.sqrt(x**2 + y_eff**2) # horizontal distance from arm pivot
d = np.sqrt(h**2 + z**2) # 3D distance from arm pivot to EE
if d > L1 + L2:
raise ValueError(f"Position out of reach: d={d:.1f} > {L1+L2:.1f}")
# Elbow angle calculation
cos_theta = (L1**2 + d**2 - L2**2) / (2 * L1 * d)
cos_theta = np.clip(cos_theta, -1, 1)
angle_to_target = np.arctan2(-z, h) # Angle from horizontal to target
angle_to_elbow = np.arccos(cos_theta)
servo_angle = angle_to_target + angle_to_elbow
return np.degrees(servo_angle)
def delta_ik(x, y, z):
"""Compute all three servo angles for position (x, y, z)."""
angles = []
for i in range(3):
# Rotate coordinate system by 0°, 120°, 240°
rot = i * 2 * np.pi / 3
x_r = x * np.cos(rot) + y * np.sin(rot)
y_r = -x * np.sin(rot) + y * np.cos(rot)
angles.append(arm_ik(x_r, y_r, z))
return angles
# Test: move to centre of workspace, 150mm below base
angles = delta_ik(0, 0, -150)
print(f"Servo angles: {[f'{a:.1f}°' for a in angles]}")
# All three should be equal (symmetric position)
# Test: move 50mm to the right
angles = delta_ik(50, 0, -150)
print(f"Angles at +50mm X: {[f'{a:.1f}°' for a in angles]}")
Workspace Calculation
The workspace of a delta robot is the set of all reachable (x, y, z) points. For our geometry:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
reachable = []
for x in range(-150, 151, 10):
for y in range(-150, 151, 10):
for z in range(-280, -50, 10):
try:
angles = delta_ik(x, y, z)
if all(-90 <= a <= 90 for a in angles):
reachable.append((x, y, z))
except ValueError:
pass
xs, ys, zs = zip(*reachable)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(xs, ys, zs, s=1, alpha=0.3)
ax.set_xlabel('X (mm)'); ax.set_ylabel('Y (mm)'); ax.set_zlabel('Z (mm)')
plt.title('Delta Robot Workspace')
plt.savefig('delta_workspace.png', dpi=150)
Servo Control & Trajectory Planning
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40);
// Servo calibration: map angle to PCA9685 pulse count
// 0° = 1000µs (pulse 204), 180° = 2000µs (pulse 409)
// Adjust per servo calibration
int angleToPulse(float angle) {
return (int)map((long)(angle * 100), -9000, 9000, 150, 600);
}
float servoAngles[3] = {0, 0, 0}; // Current angles
void setServos(float a0, float a1, float a2) {
pwm.setPWM(0, 0, angleToPulse(a0));
pwm.setPWM(1, 0, angleToPulse(a1));
pwm.setPWM(2, 0, angleToPulse(a2));
servoAngles[0] = a0;
servoAngles[1] = a1;
servoAngles[2] = a2;
}
// Linear interpolation trajectory (smooth motion)
void moveToXYZ(float tx, float ty, float tz, int steps = 50) {
// Compute target angles
float targetAngles[3];
computeDeltaIK(tx, ty, tz, targetAngles); // Call Python IK via serial or C++ equivalent
for (int s = 1; s <= steps; s++) {
float t = (float)s / steps;
float a0 = servoAngles[0] + t * (targetAngles[0] - servoAngles[0]);
float a1 = servoAngles[1] + t * (targetAngles[1] - servoAngles[1]);
float a2 = servoAngles[2] + t * (targetAngles[2] - servoAngles[2]);
setServos(a0, a1, a2);
delay(5); // 50 steps × 5ms = 250ms total move time
}
}
void setup() {
Wire.begin();
pwm.begin();
pwm.setOscillatorFrequency(27000000);
pwm.setPWMFreq(50); // 50 Hz for servos
moveToXYZ(0, 0, -150); // Home position
}
void loop() {
// Pick and place cycle
moveToXYZ(0, 80, -200); // Move above pick position
moveToXYZ(0, 80, -240); // Lower to pick
// activateSuction(true);
delay(100);
moveToXYZ(0, 80, -200); // Lift up
moveToXYZ(-80, 0, -200); // Move to place position
moveToXYZ(-80, 0, -240); // Lower to place
// activateSuction(false);
delay(100);
moveToXYZ(-80, 0, -200); // Lift
delay(200);
}
Pick & Place Sequence
A complete pick-and-place cycle using a suction cup:
- Approach: Move end-effector to 20 mm above the pick location
- Descend: Lower at reduced speed (increase step delay) to avoid impact
- Grip: Activate suction pump (relay on GPIO) — 50–100 ms settling time
- Retract: Lift quickly to clearance height
- Transport: Fast linear move to place position at high speed
- Place: Lower slowly, deactivate suction, linger 50 ms
- Return: Quick retract and return to ready position
ESP32 with 16-channel PWM, Wi-Fi and Bluetooth. Control all three delta arm servos with precise timing and run the IK over Wi-Fi for remote programming.
View Servo Driver on Zbotic →
For high-load delta robots handling parts over 500g, upgrade to these powerful bus servos with feedback for precise, repeatable pick positions.
View RSBL45 Servo on Zbotic →
FAQ
What payload can a DIY delta robot handle?
With DS3225 servos (25 kg·cm) and 120 mm arms, expect 200–400g payload at full speed. Reduce speed (increase trajectory steps) for heavier objects. Industrial delta robots use AC servo motors and handle 1–3 kg routinely.
Why does my delta robot shake at high speed?
Primarily caused by: (1) loose ball-end joints (adjust preload), (2) servo speed overshoot (add trajectory smoothing with S-curve or cosine interpolation instead of linear), (3) resonant frequency of the carbon fibre rods — try shorter or stiffer rods.
Can I use 3D-printed upper arms instead of aluminium?
Yes for low-speed, low-payload applications. Use PETG with 60% infill and 3+ perimeters. Carbon fibre reinforced PLA (CFPLA) gives better stiffness. At higher speeds, the arm flex introduces positioning error — measure this with a dial indicator and factor it into calibration.
How do I calibrate the delta robot home position?
Use a dial indicator or digital height gauge to set the end-effector to a known reference height when all three servos are at 0°. Adjust the mechanical attachment point on each upper arm until all three servos read 0° at the same end-effector height. Then calibrate servo zero in software.
Add comment