Inverse Kinematic Arm | TGM Prototype

· ESP32 · Angular · 3D-Printing · Robotics

3-axis robotic arm with web-based inverse kinematic control

3-axis 3D printed robot arm
The 3D-printed prototype featuring a NEMA17 base and servo-driven joints

Project Overview

During my studies at TGM, I developed a 3-axis robotic arm prototype to explore the implementation of Inverse Kinematics (IK) in embedded systems.
The goal was to create a system where a user could interact with a modern web interface to define a target position, which the robot would then reach autonomously by calculating the required joint angles in real-time.


Realization

The project followed a full-stack approach, covering mechanical design, electronic integration, and software development.

Mechanical Design & Hardware

The robot’s structure was entirely designed for and produced via 3D printing. To handle the structural load while maintaining precision:

Software & Control Logic

The software architecture bridged a high-level frontend with low-level hardware execution:


Robotic Arm Controller Firmware

This documentation details the firmware logic for an ESP32-powered robotic arm. The system utilizes a hybrid actuation model, combining a high-torque stepper motor for the base with a PCA9685 PWM driver for the articulated arm segments and gripper.


Hardware Architecture

The controller is built to manage high-precision movements while maintaining a responsive web interface.


Networking & API Architecture

The ESP32 hosts a RESTful web server that accepts control commands via HTTP POST requests. This allows the arm to be controlled from any web browser or third-party application on the same network.

1. WiFi Connectivity

The device initializes a connection to the specified SSID. If the connection fails, the arm remains in a standby state until connectivity is established.

void connectToWiFi() {
  Serial.println("Connecting to WiFi...");
  WiFi.begin(ssid, pw);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.print("\nConnected. IP: ");
  Serial.println(WiFi.localIP());
}

2. JSON Payload Specification

The arm’s position is updated by sending a JSON object to the /update endpoint. The values represent angles in degrees (0-180 for servos, 0-360 for the base).

{
  "base": 180,
  "segment1": 90,
  "segment2": 45,
  "segment3": 120,
  "gripperRotation": 90,
  "gripper": 30
}

3. Coordinate Mapping

Since the PCA9685 driver works with pulse-width units (typically 0-430 for standard servos) rather than degrees, the firmware maps incoming JSON values dynamically:

targetSegment1 = map(jsonDocument["segment1"], 0, 180, 0, 430);
targetGripper = map(jsonDocument["gripper"], 0, 180, 0, 430);

Motion Control & Easing Logic

To protect the mechanical components from high-inertia “jerks” and to reduce peak current draw, the firmware implements Incremental Smoothing (Easing).

Non-Blocking Update Loop

Instead of moving a servo immediately to the target, the loop() function increments the current position toward the target by one unit per cycle. This creates a smooth “chase” effect.

void loop() {
  server.handleClient(); // Handle incoming API calls

  // Incremental Base (Stepper) Movement
  if (base < targetBase) { base++; step(true); }
  else if (base > targetBase) { base--; step(false); }

  // Incremental Servo Easing
  // Updates segment positions step-by-step toward the target
  if (easingCounter % 4 == 0) {
    servoController.Servo(0, (segment1 < targetSegment1) ? segment1++ : (segment1 > targetSegment1) ? segment1-- : segment1);
  }

  // Final cycle delay regulates overall arm speed
  delay((float)armSpeed / 2.4f); 
}

Stepper Pulse Generation

The stepper motor is driven manually via digital pulses. This ensures the base has maximum holding torque during static phases.

void step(bool direction) {
  digitalWrite(baseDirPin, direction);
  digitalWrite(baseStepPin, HIGH);
  delay(5); 
  digitalWrite(baseStepPin, LOW);
  delay(5);
}

Technical Specifications

ComponentInterfaceValues
MicrocontrollerESP32240MHz / 512KB RAM
PWM DriverPCA9685I2C (0x7F)
Stepper DriverDigital Pulse10ms Pulse Cycle
JSON BufferArduinoJson250 Bytes
Servo PWM RangeInternal0 - 430 Units

Usage Notes

  1. Ensure the PCA9685 is powered by an external 5V/3A supply; the ESP32 cannot provide enough current for 6 servos.
  2. The /update endpoint is CORS-enabled, allowing for integration with browser-based JS dashboards.
  3. The armSpeed can be adjusted via the /arm-speed endpoint to change the responsiveness of the easing logic.

Results

The prototype successfully demonstrated a seamless “Web-to-Motion” workflow.
By offloading the UI to a browser and the heavy lifting to the ESP32, the system achieved fluid motion sequences and proved the viability of using 3D-printed mechanics for educational robotic platforms. The integration of the NEMA17 stepper at the base provided the necessary stability to prevent oscillations during rapid coordinate shifts.


Technical Highlights

ComponentDescription
ControllerESP32 (Dual-core SoC)
FrontendAngular Web Interface
Actuators1x NEMA17 Stepper, 2x PWM Servos
MechanicsFully 3D-printed chassis
LogicReal-time Inverse Kinematics (IK)
DriverDedicated PWM/Stepper driver interface

Skills & Competencies Gained

Developing this prototype allowed me to refine my skills in mechatronic system design and complex software-hardware interaction:


Reflection

This project was a pivotal experience during my TGM studies. It required more than just coding; it required a deep understanding of how geometry, mechanics, and software must align to turn a mathematical point on a screen into a physical movement in 3D space.