ESP32-Projekt: Roboterarm mit Smartphone steuern

In diesem Projekt zeige ich dir, wie du einen einfachen 4-Achs-Roboterarm mit einem ESP32-Board und handelsüblichen Servos bauen und per Smartphone-App steuern kannst. Dank Bluetooth-Verbindung und der kostenlosen App „nRF Connect“ lassen sich die Bewegungen bequem vom Handy aus kontrollieren – ideal für erste Schritte mit Servoansteuerung, Bluetooth-Kommunikation und 3D-gedruckten Mechaniken.

Weiter unten eine Arduino Version, nur per Sketch steuerbar.

Hardware-Komponenten


Verdrahtung:

FunktionServo-NameGPIOBeschreibung
„Basis unten“sg90=servo_bD15Hebt/Senkt den Arm
„Mittelarm“sg90=servo_mD14Gelenk in der Mitte von 75 bis 140
„Greifer“mg90S=servo_gD13Greift/öffnet die Zange mit 90 und schließt locker mit 5
„Drehen“mg90S=servo_dD16Dreht den Sockel (Basis)

⚠️ Hinweis zur Stromversorgung

Unabhängig vom Typ:

  • Nicht direkt vom ESP32 speisen, wenn du mehrere Servos nutzt.
  • Nutze ein externes 5V-Netzteil mit gemeinsamer Masse (GND) zum ESP32 oder Arduino.

Lösung bei mir, ist diese Erweiterungsplatine. Sie nimmt den ESP32 auf und hat für jeden nach außen geführten GPIO PIN zusätzlich VCC und GND, das mit externen USB Anschluss, die das ESP32 mit Strom versorgt und zugleich entlastet. Das macht das Experimentieren erheblich leichter.
Auch Umschaltbar von 5 Volt auf 3,3 Volt. Netzteilanschluss ist USB-C.


Library:

Sofern noch nicht in der Arduino IDE vorhanden, installiere die ESP32Servo Bibliothek


Test Modus

Bevor der Roboterarm im Zusammenspiel aller Achsen betrieben wird, empfiehlt es sich, jeden Servo einzeln zu testen. So lässt sich gezielt prüfen, ob die Verdrahtung korrekt ist, der Servo stabil läuft und keine ungewöhnlichen Geräusche oder Ruckler auftreten. Gleichzeitig kann man sich schrittweise an die maximalen Winkelbereiche herantasten, ohne die Mechanik zu überlasten.
Anfangs habe ich zum Beispiel bei mir, mit vier SG90 Servos experimentiert, jedoch dann zwei zum heben und drehen, gegen die robusteren und belastbareren MG90S getauscht.

Der folgende Sketch bewegt alle Servos nacheinander zwischen Start- und Zielposition – ideal zum Beobachten, Justieren und Optimieren.

Quellcode:

#include <ESP32Servo.h>  // Nutze die ServoESP32-kompatible Bibliothek

Servo servo_g;  // Greifer
Servo servo_m;  // Mittelgelenk
Servo servo_b;  // Basis unten
Servo servo_d;  // Drehbewegung

int su = 0;      // Greifer Startposition
int tu = 90;     // Greifer Zielposition

int sm = 70;     // Mittelgelenk Startposition
int tm = 150;    // Mittelgelenk Zielposition

int sb = 60;     // Basis Startposition
int tb = 100;     // Basis Zielposition

int sd = 70;     // Drehservo Startposition
int td = 110;    // Drehservo Zielposition

void setup() {
  servo_g.attach(13);  // Greifer an GPIO 13
  servo_m.attach(14);  // Mittelgelenk an GPIO 14
  servo_b.attach(15);  // Basis unten an GPIO 15
  servo_d.attach(16);  // Drehservo an GPIO 16

  servo_g.write(su);
  servo_m.write(sm);
  servo_b.write(sb);
  servo_d.write(sd);
  delay(1000);
}

void loop() {
  // Greifer bewegen
  if (su != tu) {
    su += (su < tu) ? 1 : -1;
    servo_g.write(su);
  }

  // Mittelgelenk bewegen
  if (sm != tm) {
    sm += (sm < tm) ? 1 : -1;
    servo_m.write(sm);
  }

  // Basis unten bewegen
  if (sb != tb) {
    sb += (sb < tb) ? 1 : -1;
    servo_b.write(sb);
  }

  // Drehservo bewegen
  if (sd != td) {
    sd += (sd < td) ? 1 : -1;
    servo_d.write(sd);
  }

  delay(50);  // Bewegungsgeschwindigkeit 50ms pro Schritt

  // Bewegungstest - Wenn alle Ziele erreicht sind → Richtungswechsel zur Startposition
  if (su == tu && sm == tm && sb == tb && sd == td) {
    delay(1000);
    tu = (tu == 90) ? 0 : 90;
    tm = (tm == 150) ? 70 : 150;
    tb = (tb == 100) ? 60 : 100;
    td = (td == 110) ? 70 : 110;
  }
}

Wenn dann der Arm wie gewünscht im Test-Mode läuft, ist es nicht mehr weit, um kleine Funktionen zu erstellen, wie zB. etwas von A nach B übergeben.
Späteres Ziel –> Aufräumen, Abwaschen usw. 😉


App nun auf Smartphone installieren

nRF Connect für Mobile – iOS gibt es hier:

Und nRF Connect für Mobile – Android hier:


Quellcode für Smartphonesteuerung:

Dieser Sketch erzeugt einen auffindbaren ESP32 der per Bluetooth Kommandos empfangen kann.

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <ESP32Servo.h>

// === Servo-Objekte ===
Servo servo1, servo2, servo3, servo4;

// === Aktuelle Positionen der Servos ===
int pos1 = 90, pos2 = 90, pos3 = 90, pos4 = 90;

// === BLE UUIDs für Service und Charakteristik ===
#define SERVICE_UUID        "12345678-1234-1234-1234-1234567890ab"
#define CHARACTERISTIC_UUID "abcd1234-abcd-1234-abcd-1234567890ab"

// === Funktion für sanfte Bewegung eines Servos ===
void smoothMove(Servo &servo, int ¤tAngle, int targetAngle) {
  int step = (targetAngle > currentAngle) ? 1 : -1;
  for (int pos = currentAngle; pos != targetAngle; pos += step) {
    servo.write(pos);
    delay(10); // Geschwindigkeit: 10 ms pro Schritt
  }
  servo.write(targetAngle);       // Endposition setzen
  currentAngle = targetAngle;     // Neue Position merken
}

// === Einzelnen Befehl auswerten und Servo bewegen ===
void processCommand(String cmd) {
  if (cmd.startsWith("servo1:")) {
    int angle = cmd.substring(7).toInt();
    smoothMove(servo1, pos1, angle);
  } else if (cmd.startsWith("servo2:")) {
    int angle = cmd.substring(7).toInt();
    smoothMove(servo2, pos2, angle);
  } else if (cmd.startsWith("servo3:")) {
    int angle = cmd.substring(7).toInt();
    smoothMove(servo3, pos3, angle);
  } else if (cmd.startsWith("servo4:")) {
    int angle = cmd.substring(7).toInt();
    smoothMove(servo4, pos4, angle);
  }
}

// === BLE Callback: empfängt Daten von App ===
class MyCallbacks : public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) {
    String value = String(pCharacteristic->getValue().c_str());
    Serial.println("Empfangen: " + value);

    // Nachricht in einzelne Befehle aufteilen (Trennung per Leerzeichen)
    int start = 0;
    while (start < value.length()) {
      int end = value.indexOf(' ', start);
      if (end == -1) end = value.length();
      String cmd = value.substring(start, end);
      processCommand(cmd); // Einzelbefehl verarbeiten
      start = end + 1;
    }
  }
};

void setup() {
  Serial.begin(115200);

  // === Servos initialisieren ===
  servo1.setPeriodHertz(100);
  servo2.setPeriodHertz(100);
  servo3.setPeriodHertz(100);
  servo4.setPeriodHertz(100);

  servo1.attach(13); // GPIO 13
  servo2.attach(14); // GPIO 14
  servo3.attach(15); // GPIO 15
  servo4.attach(16); // GPIO 16

  // === BLE initialisieren ===
  BLEDevice::init("ESP32-4Servo");
  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
    CHARACTERISTIC_UUID,
    BLECharacteristic::PROPERTY_WRITE
  );

  pCharacteristic->setCallbacks(new MyCallbacks());
  pService->start();
  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();

  Serial.println("Bluetooth gestartet – bereit für Befehle über nRF Connect");
}

void loop() {
  // Hauptloop bleibt leer – alles läuft über BLE-Callback
}

Smartphone-App nRF Connect:

So sendest du Befehle

Du kannst nun in einer Zeile an alle 4 Servos einen Winkel Kommando zwischen 0 und 180 senden
Zum Beispiel wie „servo1:0, servo2:180 servo3:50, servo4:110

  1. App öffnen → Nach Geräte scannen → ESP32-4Servo auswählen → „Connect“

Charakteristik finden → Auswahl: UUID abcd1234-abcd-1234-abcd-1234567890ab

„UTF8“ auswählen → z. B. servo1:90 eingeben

Mit Write Absenden → Servo bewegt sich auf 90° oder bis zu 4 gleichzeitig. Bewegungsgeschwindigkeit kann im Sketch angepasst werden.

Jetzt lassen sich die Bewegungen bequem vom Handy aus kontrollieren.


Arduino-Alternative:
Roboterarm mit Arduino ohne manuelle Steuerung

Wer nur den Roboterarm mit Arduino Uno erstellen möchte, um zum Beispiel automatisierte Abläufe im Sketch zu erstellen, sollte die GPIO 3, 5, 6 und 9 verwenden. Und eventuell noch die Servo Bibliothek installieren.

Beispiel-Sketch für Arduino:

#include <Servo.h>

Servo servo_g;  // Greifer an Pin 6
Servo servo_m;  // Mittelgelenk an Pin 5
Servo servo_b;  // Basis unten an Pin 3
Servo servo_d;  // Drehservo an Pin 9

int su = 0;      // Greifer Startposition (zu)
int tu = 90;     // Greifer Zielposition (auf)

int sm = 70;     // Mittelgelenk Startposition (gestreckt)
int tm = 150;    // Mittelgelenk Zielposition (90grad)

int sb = 30;     // Basis Startposition (170grad)
int tb = 110;     // Basis Zielposition (190grad)

int sd = 40;     // Drehservo Startposition
int td = 140;    // Drehservo Zielposition

void setup() {
  servo_g.attach(6);  // Greifer
  servo_m.attach(5);  // Mittelgelenk
  servo_b.attach(3);  // Basis unten
  servo_d.attach(9);  // Drehservo

  servo_g.write(su);
  servo_m.write(sm);
  servo_b.write(sb);
  servo_d.write(sd);
  delay(1000);
}

void loop() {
  // Greifer bewegen
  if (su != tu) {
    su += (su < tu) ? 1 : -1;
    servo_g.write(su);
  }

  // Mittelgelenk bewegen
  if (sm != tm) {
    sm += (sm < tm) ? 1 : -1;
    servo_m.write(sm);
  }

  // Basis unten bewegen
  if (sb != tb) {
    sb += (sb < tb) ? 1 : -1;
    servo_b.write(sb);
  }

  // Drehservo bewegen
  if (sd != td) {
    sd += (sd < td) ? 1 : -1;
    servo_d.write(sd);
  }

  delay(30);  // Bewegungsgeschwindigkeit

  // Wenn alle Ziele erreicht sind → Richtungswechsel
  if (su == tu && sm == tm && sb == tb && sd == td) {
    delay(1000);
    tu = (tu == 90) ? 0 : 90;         // Greifer umkehren
    tm = (tm == 150) ? 70 : 150;      // Mittelgelenk umkehren
    tb = (tb == 110) ? 30 : 110;        // Basis umkehren
    td = (td == 140) ? 40 : 140;      // Drehservo umkehren
  }
}

, , ,
Datenschutz-Übersicht

Diese Website verwendet Cookies, damit wir dir die bestmögliche Benutzerkomfort bieten können. Cookie-Informationen werden in deinem Browser gespeichert und führen Funktionen aus, wie das Wiedererkennen von dir, wenn du auf unsere Website zurückkehrst und hilft uns zu verstehen, welche Abschnitte der Website für dich am interessantesten und nützlichsten sind.