Siddhant Kumar
Project 093 · Robotics

4-DOF Robotic Arm.

A four-jointed arm with a gripper that reaches to a point in space and picks things up — an accessible introduction to manipulation and kinematics.

Advanced 14–22 hours 29 min read RobotServosControl
Jump to source Bill of materials
4-DOF Robotic Arm — reference build illustration MCU VCC · GND · SIG · NC
Difficulty
Advanced
Build time
14–22 hours
Indicative cost
₹2,800 – ₹5,000
Platform
Arduino Uno R3 (ATmega328P)
Category
Robotics
Last updated
28 July 2026
Contents — 26 sections

Project Overview

A four-jointed arm with a gripper that reaches to a point in space and picks things up — an accessible introduction to manipulation and kinematics.

A mobile robot moves itself through space; a robotic arm moves the world — reaching out to a chosen point, orienting a gripper, and picking, placing or manipulating an object. That is a fundamentally different and richer problem, and its core is kinematics: the relationship between the arm's joint angles and where its gripper ends up in space. This project builds a 4-degree-of-freedom (4-DOF) arm — base rotation, shoulder, elbow, and a gripper — and the control to make it reach and grasp, an accessible but genuine introduction to robotic manipulation.

The arm is a chain of links driven by servo motors at each joint: the base servo swings the arm left/right, the shoulder and elbow servos raise and extend it, and the gripper servo opens and closes to grasp. Controlling it has two directions. Forward kinematics answers "given these joint angles, where is the gripper?" — a matter of chaining the link geometry. Inverse kinematics answers the more useful and harder question "to put the gripper here, what joint angles do I need?" — which for a simple arm can be solved with geometry and trigonometry, and is what lets you command a position rather than fiddling each joint by hand.

On top of the kinematics sit the practicalities of a real arm: smooth motion (moving joints gradually and in coordination, not snapping, to avoid jerking the arm and its load), reach and workspace (the arm can only reach points its geometry allows — the envelope matters), payload and torque (a servo has limited torque, and a load far from a joint demands more — the shoulder works hardest), and safe, stable operation. It is honest that hobby servos have limited precision, repeatability and payload, and that industrial arms use far more capable actuators and 6+ DOF for full position and orientation control. But as a 4-DOF servo arm with forward and inverse kinematics, coordinated motion and a working gripper, it teaches the real substance of manipulation — kinematics, workspace, torque and control — in a build you can hold in your hand.

A multi-axis robotic arm
A 4-DOF servo arm reaches to a point and grasps — an accessible introduction to robotic manipulation and kinematics. Photograph sourced from Wikimedia Commons — Robot arm.jpg. Reused under the licence stated on that page; please check it before republishing.

What this project does

  • Reaches its gripper to a chosen point in space
  • Drives 4 joints (base, shoulder, elbow, gripper) with servos
  • Computes forward kinematics (angles → position)
  • Computes inverse kinematics (position → angles)
  • Moves joints smoothly and in coordination
  • Opens/closes a gripper to pick and place
  • Respects its reachable workspace, torque and payload limits

Real-World Applications

SettingHow it is used
Manipulation educationKinematics, workspace and torque in a hands-on arm.
Pick-and-place demosSimple sorting/placing of light objects.
Automation prototypingA base for feeders, sorters and desktop automation.
Robotics research learningForward/inverse kinematics and coordinated control.

Deployment contexts where a build of this kind earns its keep.

Features & Capabilities

  • Servo-driven 4-DOF arm + gripper
  • Forward and inverse kinematics
  • Coordinated, smooth (eased) joint motion
  • Workspace/reach awareness
  • Torque/payload-conscious design
  • Pick-and-place sequencing
  • Honest about hobby-servo precision and DOF limits

Difficulty, Time & Required Skills

AttributeValue
Difficulty levelAdvanced
Estimated completion time14–22 hours
Indicative build cost₹2,800 – ₹5,000
Primary disciplineRobotics
Reference platformArduino Uno R3 (ATmega328P)

Skills you should have (or will pick up)

  • Servo control and coordinated multi-joint motion
  • Forward kinematics (link geometry chaining)
  • Inverse kinematics (geometric/trigonometric solution)
  • Workspace, reach and torque/payload reasoning
  • Pick-and-place sequencing and gripping

Bill of Materials

Every part below is commonly available from Indian and international hobby-electronics suppliers. Prices are indicative 2026 retail figures in Indian rupees and will drift — treat them as a budgeting guide, not a quotation.

ComponentKey specificationQtyApprox. cost
Arduino Uno R3 (ATmega328P)
2 KB of SRAM is the real constraint — keep strings in PROGMEM.
16 MHz AVR, 32 KB flash, 2 KB SRAM, 1 KB EEPROM, 14 digital I/O (6 PWM), 6× 10-bit ADC1₹700
MG996R metal-gear servo
Draws up to 2.5 A stalled — a 6 V 5 A supply per 4–6 servos is realistic.
11 kg·cm at 6 V, 0.17 s/60°, metal gears, dual ball bearings1₹380
SG90 9 g micro servo
Stall current hits 700 mA — never power servos from the board 5 V rail.
1.8 kg·cm at 4.8 V, 0.1 s/60°, 180° travel, plastic gears, 50 Hz PWM1₹130
5 V 3 A regulated SMPS adapter
Measure the real output — many "3 A" adapters sag below 4.7 V at 2 A.
100–240 VAC in, 5 V ±5 % out, 3 A, short-circuit and over-voltage protection1₹350
830-point solderless breadboard + jumper set
Fine for prototyping; move to perfboard before anything permanent.
830 tie points, 2 power rails, 0.1″ pitch; 65 male-male jumpers1₹180
Servos (joints)
Shoulder needs the most torque
3× higher-torque servos (base/shoulder/elbow) + 1 gripper servo4₹4,800
Arm structure + gripperLaser-cut/3D-printed links, brackets and a gripper1₹900
Servo power supply
Servos draw far more than an MCU pin can give
5–6 V supply able to drive all servos (amps)1₹400
Heavy baseWeighted/clamped base for stability1₹300

Estimated total: ₹8,140, excluding tools, shipping and consumables.

Tools and consumables

  • Soldering iron (temperature controlled, 350 °C) with 0.8 mm 60/40 or lead-free solder
  • Digital multimeter — continuity, DC volts and current ranges
  • Wire strippers, flush cutters and a small set of precision screwdrivers
  • Heat-shrink tubing and a heat gun (or a lighter, carefully)
  • A laptop with a USB port and the toolchain listed above

Hardware Specifications

PartSpecificationSupplyInterfaceReference
Arduino Uno R3 (ATmega328P)16 MHz AVR, 32 KB flash, 2 KB SRAM, 1 KB EEPROM, 14 digital I/O (6 PWM), 6× 10-bit ADC5 V logic, 7–12 V barrel inUART, SPI, I²CDatasheet
MG996R metal-gear servo11 kg·cm at 6 V, 0.17 s/60°, metal gears, dual ball bearings4.8–7.2 VPWM 50 HzDatasheet
SG90 9 g micro servo1.8 kg·cm at 4.8 V, 0.1 s/60°, 180° travel, plastic gears, 50 Hz PWM4.8–6 VPWM 500–2400 µsDatasheet
5 V 3 A regulated SMPS adapter100–240 VAC in, 5 V ±5 % out, 3 A, short-circuit and over-voltage protection5 VDC barrel / USBDatasheet
830-point solderless breadboard + jumper set830 tie points, 2 power rails, 0.1″ pitch; 65 male-male jumpersDatasheet

Consolidated electrical and interface specifications for every active part in the build.

Power Budget & Supply Sizing

Add up the typical active current of every part, then size the supply with at least 50 % headroom so transmit bursts and motor inrush never brown out the controller.

LoadSupply railTypical current (mA)Notes
Arduino Uno R3 (ATmega328P)5 V logic, 7–12 V barrel in452 KB of SRAM is the real constraint — keep strings in PROGMEM.
MG996R metal-gear servo4.8–7.2 V500Draws up to 2.5 A stalled — a 6 V 5 A supply per 4–6 servos is realistic.
SG90 9 g micro servo4.8–6 V200Stall current hits 700 mA — never power servos from the board 5 V rail.
5 V 3 A regulated SMPS adapter5 V3000Measure the real output — many "3 A" adapters sag below 4.7 V at 2 A.

Summed typical draw is 3745 mA. With a 1.5× design margin the supply should deliver at least 5700 mA continuously at the stated rail voltage.

Software Requirements & Development Environment

Reference toolchain: Arduino IDE 2.3.x (AVR core 1.8.6). Anything newer normally works; anything older may lack the board definitions used here.

  • Install the Arduino IDE 2.3.x (or PlatformIO if you prefer a real editor and dependency locking).
  • Select Tools → Board → Arduino AVR Boards and the matching board. Clone boards with a CH340 USB bridge need the CH340 driver on Windows and macOS.
  • Set the correct port under Tools → Port. On Linux add yourself to the dialout group: sudo usermod -aG dialout $USER and log out and back in.
  • Open the Serial Monitor at 115200 baud — every sketch here logs its state there.
  • Keep File → Preferences → Show verbose output during: compilation switched on while you are debugging build errors.

Required libraries

LibraryWhy it is neededInstall
ESP32Servo / Servo 3.0.x50 Hz PWM generation with correct pulse widths for hobby servos.Library Manager → "ESP32Servo" by Kevin Harrington
Preferences (NVS) bundledWear-levelled key/value storage in ESP32 flash for settings.Bundled with the ESP32 core

Block Diagram

The block diagram shows the functional decomposition of the system — what senses, what decides, what acts, and where the data ends up.

4-DOF Robotic Arm — system block diagramFunctional block diagram of the 4-DOF Robotic Arm system. CommandTarget (x,y,z)or pick/placePlanInverse kin.pos → anglesReachable?workspaceMoveEase jointscoordinated4 servosbase/sh/el/gripGraspGripperopen/closePlacesequencerightrightnone
4-DOF Robotic Arm — system block diagram

Circuit Diagram & Wiring

Every signal line in the build is shown below, followed by a pin-by-pin connection table you can work through with a multimeter in hand.

4-DOF Robotic Arm — wiring schematicConnection schematic showing which controller pin drives each peripheral. Sensors / InputsControllerActuators / OutputsArduino Uno R3(ATmega328P)5 V logic, 7–12 V barrel inBase servoD3Rotate (θ0)Shoulder servoD5Lift (θ1)Elbow servoD6Extend (θ2)Gripper servoD9Open/closeServo supply 5–6VextPower (amps)Common groundGNDShared
4-DOF Robotic Arm — wiring schematic
PeripheralPeripheral pinController pinSignal
Base servoPWMD3Rotate (θ0)
Shoulder servoPWMD5Lift (θ1)
Elbow servoPWMD6Extend (θ2)
Gripper servoPWMD9Open/close
Servo supply 5–6VV+extPower (amps)
Common groundGNDGNDShared

Wire one row at a time and tick it off — most "it does not work" reports trace back to a single swapped pair.

Wiring explanation

  • Power the servos from a dedicated 5–6 V supply able to source several amps — not the MCU's 5 V pin.
  • Tie the servo-supply ground to the MCU ground (common ground) so the PWM signals are referenced correctly.
  • Give the base a heavy or clamped mount — the arm will tip a light base when it reaches out.
  • Route servo wires so they do not bind the joints through their range of motion.
  • Add capacitance across the servo supply to absorb current surges.
An SG90 hobby micro servo with its horn attached
Inverse kinematics turns a target position into base, shoulder and elbow angles, revealing the reachable workspace. Photograph sourced from Wikimedia Commons — Servo motor sg90.jpg. Reused under the licence stated on that page; please check it before republishing.

System Architecture

Read the stack from the bottom up: physical hardware, the firmware that drives it, the transport that moves data off the device, and the software a human actually looks at.

4-DOF Robotic Arm — architecture stackLayered architecture from hardware to user interface. Hardware layerArduino Uno R3 (ATmega328P) · sensors and actuatorsDriver layerservo · preferencesApplication logicsampling loop · filtering · thresholds · state machinePresentation layerlocal display · serial console · logged output
4-DOF Robotic Arm — architecture stack

Working Principle

A manipulator's defining question is kinematics: how the angles of its joints determine where its end-effector — the gripper — sits and points in space. Everything about controlling an arm flows from this relationship. A 4-DOF arm has four controllable joints; here, base rotation places the arm's working plane, the shoulder and elbow set the reach and height within that plane, and the gripper grasps. Four degrees of freedom is enough to command a position (and one orientation) — enough to pick things up — while remaining simple enough to understand fully, which is exactly why it is the right teaching arm.

Forward kinematics is the direct calculation: given the joint angles, chain the fixed link lengths and joint rotations to find the gripper's position. It is unambiguous — a set of angles yields exactly one gripper pose — and it is how you predict where the arm will be. But it answers the wrong question for actual use: nobody wants to hand-pick four angles and hope the gripper lands where they want. The useful question is the inverse.

Inverse kinematics asks: to put the gripper at a target point, what joint angles are required? This is harder — there can be multiple solutions (elbow-up vs elbow-down), or none if the point is out of reach — but for a simple arm it yields to geometry and trigonometry: the base angle comes from the target's direction, and the shoulder/elbow angles come from solving the two-link reach triangle to the target (the law of cosines). Solving inverse kinematics is what turns the arm from a set of fiddly joints into a device you command by position — "go here" — which is the whole point of manipulation control. It also naturally reveals the workspace: the set of points the arm can actually reach, bounded by its link lengths and joint ranges. A target outside the workspace has no solution, and the controller must recognise and reject it rather than straining the servos.

Around the kinematics sit the physical realities that make an arm behave — or misbehave. Motion must be smooth and coordinated: snapping servos to new angles jerks the arm, overshoots, and can fling a grasped object, so joints are eased to their targets together over a short time. Torque and payload govern what the arm can do: a servo produces limited torque, and a load or link mass acting at a distance from a joint imposes a torque that grows with that distance — the shoulder, carrying the whole outstretched arm, works hardest and sets the payload limit, which is why it needs the strongest servo and a stable, heavy base (or the arm tips itself over). The design is honest about the ceiling on all this: hobby servos have limited precision and repeatability (they will not hit a point to the millimetre reliably), limited payload, and no force feedback, and industrial arms use precision actuators and 6+ DOF to control full position and orientation. But within those honest limits, a 4-DOF servo arm with real forward and inverse kinematics, coordinated smooth motion, and a working gripper delivers the genuine substance of robotic manipulation — the part that transfers directly to serious robotics.

The maths behind it

Forward kinematics (planar 2-link + base)

plainForward kinematics (planar 2-link + base)
Base rotates by θ0; shoulder θ1, elbow θ2; links L1, L2:

  r = L1·cos θ1 + L2·cos(θ1+θ2)     (reach in the plane)
  z = L1·sin θ1 + L2·sin(θ1+θ2)     (height)
  x = r·cos θ0,   y = r·sin θ0       (rotate into 3-D)

Angles → a single, definite gripper position.

Inverse kinematics (position → angles)

plainInverse kinematics (position → angles)
Target (x,y,z): θ0 = atan2(y, x)
  r = √(x²+y²),  reach D = √(r² + z²)

Elbow (law of cosines):
  θ2 = ± acos( (D² − L1² − L2²) / (2·L1·L2) )
Shoulder:
  θ1 = atan2(z, r) − atan2(L2·sin θ2, L1 + L2·cos θ2)

No solution if D > L1+L2 → OUT OF REACH (reject).

Torque / payload (why the shoulder works hardest)

plainTorque / payload (why the shoulder works hardest)
Joint torque ≈ Σ (weight_i × horizontal_distance_i)

A load m at reach R needs torque ~ m·g·R at the shoulder.
Farther out → more torque. Shoulder carries the whole arm
→ strongest servo + heavy/stable base (or it tips).

Program Flowchart

The firmware is a single cooperative loop. Nothing blocks for long, so networking, sensing and the user interface all stay responsive.

4-DOF Robotic Arm — firmware flowchartControl flow through the main program loop. Command a target (x,y,z) /pickInverse kinematics → jointanglesWithin workspace / torque?Ease joints to target (coordinated)Reject: out of reachReject: out of reachEase joints to target(coordinated)Close gripper (grasp)Move to place point + openReturn to rest
4-DOF Robotic Arm — firmware flowchart

Assembly Instructions

Build on a breadboard first and only commit to solder once the whole system has run for an hour without a fault.

  1. Build the arm and power the servos properly

    Assemble the base, shoulder, elbow and gripper with the strongest servo at the shoulder, on a heavy/clamped base. Power all servos from a dedicated multi-amp 5–6 V supply with a common ground to the MCU.

  2. Calibrate joints and implement kinematics

    Calibrate each servo's angle range and zero, measure the link lengths, and implement forward and inverse kinematics.

  3. Add coordinated motion and gripping

    Ease joints to IK targets in coordination, add workspace checks, and sequence pick-and-place with the gripper.

Step-by-Step Implementation Guide

Work through these in order. Each step ends in something you can observe, so a failure is always localised to the step you just finished.

  1. Solve inverse kinematics and check reach

    From a target point compute the joint angles with geometry, and reject targets outside the reachable workspace.

    cppik.ino
    const float L1 = 105.0, L2 = 98.0;   // link lengths (mm)
    
    struct Angles { float base, shoulder, elbow; bool reachable; };
    
    Angles inverseKinematics(float x, float y, float z){
      Angles a; a.reachable = true;
      a.base = atan2(y, x);                          // base points at target
      float r = sqrt(x*x + y*y);                     // horizontal reach
      float D = sqrt(r*r + z*z);                      // distance to target
    
      if (D > (L1 + L2) || D < fabs(L1 - L2)){        // outside the workspace
        a.reachable = false; return a;                // reject: don't strain servos
      }
      float c2 = (D*D - L1*L1 - L2*L2) / (2*L1*L2);
      a.elbow = acos(constrain(c2, -1.0, 1.0));       // law of cosines
      a.shoulder = atan2(z, r)
                 - atan2(L2*sin(a.elbow), L1 + L2*cos(a.elbow));
      return a;
    }
    a.base = atan2(y, x); // base points at targetThe base angle simply aims the arm's working plane at the target's horizontal direction.
    if (D > (L1 + L2) || D < fabs(L1 - L2)){ // outside the workspaceA target farther than the arm can stretch (or nearer than it can fold) has no solution — the controller rejects it instead of straining the servos into a pose they cannot reach.
    a.elbow = acos(constrain(c2, -1.0, 1.0)); // law of cosinesThe elbow angle comes from the law of cosines on the two-link reach triangle — the heart of the inverse-kinematics solution.
    a.shoulder = atan2(z, r)The shoulder angle combines the direction to the target with the elbow geometry so the gripper lands on the point.
  2. Ease joints to the target and grasp

    Move all joints from their current angles to the IK targets together over a short time (easing), then operate the gripper — smooth, coordinated motion that does not jerk or fling the load.

Complete Source Code

The listing below is complete and compiles as written — there are no elided sections. Read the annotations under each block before you upload it.

cpprobot_arm.ino
/* ═══════════════════════════════════════════════════════════════
   4-DOF Robotic Arm — reach + pick-and-place

   Inverse kinematics turns a target point into joint angles (with a
   workspace check), coordinated easing moves all joints smoothly, and
   a gripper picks and places. Servos on a dedicated supply, common
   ground, heavy base. Honest about hobby-servo precision/payload.
   ══════════════════════════════════════════════════════════════════ */

#include <Servo.h>
Servo base, shoulder, elbow, gripper;
const float L1=105, L2=98;                 // mm

struct Angles { float base, shoulder, elbow; bool reachable; };

Angles ik(float x,float y,float z){
  Angles a; a.reachable=true;
  a.base = atan2(y,x);
  float r=sqrt(x*x+y*y), D=sqrt(r*r+z*z);
  if (D > L1+L2 || D < fabs(L1-L2)){ a.reachable=false; return a; }
  float c2=(D*D-L1*L1-L2*L2)/(2*L1*L2);
  a.elbow = acos(constrain(c2,-1.0,1.0));
  a.shoulder = atan2(z,r) - atan2(L2*sin(a.elbow), L1+L2*cos(a.elbow));
  return a;
}
int deg(float rad){ return constrain((int)(rad*180.0/PI), 0, 180); }

// Ease ALL joints together from current to target (smooth, coordinated).
void moveTo(int b,int s,int e,int steps=40){
  int b0=base.read(), s0=shoulder.read(), e0=elbow.read();
  for (int i=1;i<=steps;i++){
    float t=(float)i/steps;                // 0..1
    base.write(b0+(b-b0)*t);
    shoulder.write(s0+(s-s0)*t);
    elbow.write(e0+(e-e0)*t);
    delay(15);
  }
}
void grip(bool close){ gripper.write(close?60:120); delay(400); }

void reachAndPick(float x,float y,float z){
  Angles a = ik(x,y,z);
  if (!a.reachable){ Serial.println("OUT OF REACH"); return; }  // honest reject
  grip(false);                              // open
  moveTo(deg(a.base), deg(a.shoulder), deg(a.elbow));
  grip(true);                               // grasp
}

void setup(){
  base.attach(3); shoulder.attach(5); elbow.attach(6); gripper.attach(9);
  moveTo(90,90,90); grip(false);            // rest pose
  reachAndPick(120, 40, 20);                // pick at a point
  moveTo(30, 90, 90); grip(false);          // move to place point + release
  moveTo(90,90,90);                         // return to rest
}
void loop(){}
if (D > L1+L2 || D < fabs(L1-L2)){ a.reachable=false; return a; }The workspace check rejects unreachable targets — the arm never strains servos toward a point its geometry cannot reach.
void moveTo(int b,int s,int e,int steps=40){Every joint is eased from its current to its target angle over the same steps, so the arm moves as one smooth, coordinated motion instead of snapping.
if (!a.reachable){ Serial.println("OUT OF REACH"); return; } // honest rejectCommanding a position out of the workspace is reported and refused — honest handling rather than a servo strain or a wild pose.
grip(true); // graspWith the gripper positioned by inverse kinematics, closing it picks the object — the payoff of commanding by position.

Configuration & Calibration

Configuration steps

  • Configure servo pins, per-joint angle ranges/zeros, and the link lengths.
  • Configure the easing steps/speed for smooth coordinated motion.
  • Configure gripper open/close angles and pick/place points.
  • Configure workspace limits and out-of-reach handling.

Calibration procedure

An uncalibrated sensor produces confident, precise, wrong numbers. Do this once per physical unit and record the constants.

  1. Joint zeros/ranges

    Calibrate each servo's angle so the arm's geometric zero matches the model, and set safe joint limits.

  2. Link lengths

    Measure L1/L2 accurately — kinematic accuracy depends on them.

  3. Reach accuracy

    Command known points and measure where the gripper lands; note hobby-servo repeatability limits.

Mechanical Assembly & Motion

Mechanical assembly

  • A serial chain: a rotating base, a shoulder joint, an elbow joint, and a gripper at the end — four servos in all.
  • Links sized for the desired reach; the shoulder joint bears the most load, so it uses the strongest servo.
  • A heavy or clamped base for stability — an outstretched arm will tip a light base.
  • Servo wiring routed so it does not bind the joints anywhere in their range.

Motion logic

Motion is coordinated multi-joint servo control: to reach a point, inverse kinematics gives the four target angles, and all joints are eased to them together over a short time rather than snapped.

Easing (interpolating each joint from its current to its target angle) keeps the motion smooth, avoids overshoot, and stops the arm from flinging a grasped object — coordination matters as much as the endpoints.

StateLeft motorRight motorResult
Reach to point(base + shoulder)(elbow + gripper)Gripper arrives via IK
Elbow-up vs elbow-downShoulder highElbow bent upChoose reachable/safe solution
GraspArm holds poseGripper closesPick object
CarryEase slowlyEase slowlySmooth, no fling
Out of workspaceReject (no IK solution)
RestFoldedGripper openStable park pose

Sensor integration

  • Servo positions are commanded open-loop (hobby servos have internal position control but no external feedback to the MCU).
  • Optional: a gripper force/limit sensor or a camera for closed-loop pick accuracy.
  • Optional: current sensing on the servo supply to detect stall/overload.

Actuator explanation

Four servos: base (rotate), shoulder (lift, highest torque), elbow (extend), and gripper (grasp).

All powered from a dedicated multi-amp 5–6 V supply with common ground to the MCU; the controller eases each servo from its current to its target angle in coordination.

Kinematics

Forward kinematics chains the link geometry to find the gripper from the angles; inverse kinematics solves the reach triangle with trigonometry to find the angles for a target point, and reveals the reachable workspace.

plainkinematics
Forward:  r = L1·cosθ1 + L2·cos(θ1+θ2);  z = L1·sinθ1 + L2·sin(θ1+θ2)
          x = r·cosθ0;  y = r·sinθ0

Inverse:  θ0 = atan2(y,x);  D = √(x²+y²+z²)
          θ2 = acos((D²−L1²−L2²)/(2 L1 L2))    # elbow (law of cosines)
          θ1 = atan2(z,√(x²+y²)) − atan2(L2 sinθ2, L1+L2 cosθ2)
          if D > L1+L2:  OUT OF REACH

Testing Procedure & Expected Output

Test from the bottom up. Confirm power, then each sensor in isolation, then the integrated loop — the first failing step tells you exactly where to look.

TestWhat you should see
Command a reachable pointGripper arrives near the point (IK works)
Command an out-of-reach point"OUT OF REACH" — rejected, servos not strained
Move between two pointsSmooth, coordinated (eased) motion
Pick a light objectGripper grasps and carries without flinging
Reach fully outstretched with a loadShoulder works hardest; base stable (no tip)
Repeat a target several timesSome spread — note servo repeatability

Bench-test checklist. If a row fails, stop and fix it before moving on.

Expected output

An arm that reaches commanded points, respects its workspace, moves smoothly, and picks and places light objects.

plainik-result.txt
target: (120, 40, 20) mm
base: 18 deg   shoulder: 62 deg   elbow: 74 deg
reachable: yes
motion: eased over 40 steps -> gripper at ~(119, 41, 21) mm
grip: closed (object picked)

Inverse kinematics turned the target point into joint angles, the arm eased smoothly to it, and the gripper picked the object — manipulation commanded by position, not by fiddling joints.

A brushed DC gear motor
The shoulder joint carries the whole outstretched arm, so it works hardest and needs the most torque and a stable base. Photograph sourced from Wikimedia Commons — DC motor.jpg. Reused under the licence stated on that page; please check it before republishing.

Troubleshooting: Common Errors & Fixes

MCU resets when arm moves

Likely cause. Servos on MCU power

Fix. Dedicated multi-amp servo supply; common ground; add capacitance

Arm tips over

Likely cause. Light base / long reach

Fix. Heavy or clamped base; keep loads within payload

Gripper misses the point

Likely cause. Wrong link lengths / servo zeros

Fix. Re-measure L1/L2; recalibrate joint zeros

Jerky motion / flings load

Likely cause. Snapping servos

Fix. Ease all joints together over time

Shoulder struggles/stalls

Likely cause. Torque/payload exceeded

Fix. Stronger shoulder servo; lighter load; shorter reach

Unreachable points attempted

Likely cause. No workspace check

Fix. Reject targets with no IK solution

The sketch will not upload — "Failed to connect" or "avrdude: stk500_recv()"

Likely cause. The bootloader is not being reached: wrong port, wrong board, a serial monitor holding the port open, or a USB cable that only carries power.

Fix. Close every serial monitor, confirm Tools → Board and Port, and swap to a known data-capable USB cable. On an ESP32 hold BOOT while the IDE prints "Connecting…", then release. If a peripheral is wired to the UART pins (GPIO 1/3 on ESP32, D0/D1 on Uno) unplug it — it fights the programmer.

The board resets in a loop, or the serial monitor prints "Brownout detector was triggered"

Likely cause. The supply cannot deliver peak current. Wi-Fi transmit bursts, relay coils and servos all pull far more than their average draw.

Fix. Power peripherals from a separate regulated supply with a common ground rather than from the board 5 V pin. Add a 470–1000 µF electrolytic capacitor across the supply near the load, and use a real power adapter rather than a laptop USB port.

Serial monitor shows garbage characters

Likely cause. Baud rate mismatch between Serial.begin() and the monitor, or a floating/shared UART line.

Fix. Set the monitor to 115200 to match the sketch. If it still garbles, the crystal or the USB bridge is being confused by noise — shorten the cable and keep motor wiring away from the USB lead.

Performance Optimisation

  • Solve inverse kinematics to command position, not joints.
  • Reject out-of-workspace targets rather than straining servos.
  • Ease all joints together for smooth, coordinated motion.
  • Design for torque/payload — strongest servo at the shoulder, stable base.
  • Replace every delay() with a millis() comparison — blocking delays are the single most common cause of dropped readings.
  • Sample sensors on a fixed cadence and publish on a slower one; you almost never need to transmit at the sampling rate.
  • Wrap constant strings in F("...") so they stay in flash — an Uno only has 2 KB of SRAM.
  • Use uint8_t / uint16_t where the range allows; on an 8-bit AVR a 32-bit add costs four times as much.
  • Profile before optimising — print micros() deltas around each stage and fix the slowest one first.

Safety Precautions

  • Keep hands and objects clear of the arm's workspace while it moves — even a small servo arm can pinch.
  • Power servos from a proper supply; brownouts cause uncommanded motion.
  • Use a stable, heavy base so the arm cannot tip and fall.
  • Stay within the servos' torque/payload; a stalled servo overheats and can be damaged.
  • Hobby servos lack force feedback and precise repeatability — do not rely on them for anything safety-critical.
  • Moving parts pinch. Keep fingers, cables and hair out of gear trains and wheels, and always test motion with the drivetrain unloaded and the robot on blocks first.
  • Motors are inductive — always fit a flyback diode across a DC coil, or use a driver that already has one, or the back-EMF spike will destroy your GPIO.
  • Wear eye protection when soldering or cutting, and solder in a ventilated space — rosin flux fumes are a respiratory irritant.
  • Power the circuit through a bench supply with a current limit while you are testing. A 300 mA limit turns a wiring mistake into a beep instead of a dead board.
  • Disconnect power before changing any wiring. Hot-plugging a sensor onto a live bus is the fastest way to lose a controller.

Maintenance

  • Re-check joint zeros and link measurements periodically.
  • Watch for servo wear/backlash that degrades accuracy.
  • Keep the base fixings tight and the wiring free of the joints.
  • Verify the servo supply holds voltage under load.
  • Re-check every screw terminal and header after the first week — thermal cycling loosens connections that felt tight on day one.
  • Listen for gear chatter. A servo that buzzes at rest is either stripped or fighting a mechanical bind — fix it before it burns out.
  • Recalibrate at the interval given in the calibration section, and keep the constants in a text file next to the firmware — not only in flash.
  • Keep a short logbook of firmware versions and what changed. Six months later you will not remember why that constant is 1.083.

Future Improvements & Upgrades

A working v1 is a platform, not a finish line. These are the upgrades that add the most capability for the least rework.

  • Add a 5th/6th DOF (wrist) for full orientation control.
  • Add a camera for visual servoing / closed-loop picking.
  • Add trajectory planning (via-points, speed profiles).
  • Add force/current sensing for compliant, safer grasping.
  • Design a proper PCB. Once the breadboard version has run for a month, moving to a two-layer board removes the intermittent-contact failures that dominate prototype faults.
  • Add connectivity — an ESP32 and an MQTT publish turn a local gadget into something you can graph, alert on and analyse over months.
  • Add persistent local storage (microSD or the on-chip flash) so a network outage does not create a hole in your data.
  • Move configuration out of the source: a captive-portal setup page or a JSON config file makes the build reusable without a recompile.
  • Add a battery and solar option so the unit survives a power cut and can be sited away from a socket.
  • Write a small test harness that feeds synthetic sensor values through the decision logic, so you can validate thresholds without physically triggering the event.

Frequently Asked Questions

What is the difference between forward and inverse kinematics?

Forward kinematics computes where the gripper is from the joint angles (one definite answer). Inverse kinematics computes the joint angles needed to put the gripper at a target point — harder (multiple or no solutions) but far more useful, because it lets you command a position.

Why only 4 degrees of freedom?

4-DOF is enough to command a position (and one orientation) — enough to pick things up — while staying simple to understand fully. Controlling full position and orientation needs 6+ DOF, which is what industrial arms use.

Why does the shoulder need the strongest servo?

Because torque grows with load times distance from the joint, and the shoulder carries the entire outstretched arm and its load. It works hardest and sets the payload limit, so it needs the most torque — and a stable base, or the arm tips itself over.

Why ease the joints instead of snapping to the angles?

Snapping jerks the arm, overshoots, and can fling a grasped object. Easing every joint from its current to its target angle together produces smooth, coordinated motion — coordination matters as much as the endpoints.

How accurate is it?

Usefully but not precisely. Hobby servos have limited resolution, repeatability and no external feedback, so it will reach near a point rather than to the millimetre reliably. That honest limit is exactly why serious arms use precision actuators and closed-loop control.

References & Learning Resources

These are the primary sources worth reading in full. Manufacturer datasheets always outrank forum posts when the two disagree.

  1. Robot arm / manipulatorReference
  2. Forward kinematicsReference
  3. Inverse kinematicsReference
  4. Degrees of freedom (mechanics)Reference
  5. Servo motor controlReference