Dobot Magician – Deutsche Python-API-Dokumentation

Praxisorientierte Dokumentation der bisher verwendeten Funktionen aus DobotDllType.py – erweitert um DLL-Suchpfad, erzwungenen Queue-Stopp und robuste Alarmbehandlung.

Grundlage

from sdk64 import DobotDllType as dType

DobotDllType.py kapselt die C/C++-API der DobotDll.dll und stellt deren Funktionen für Python bereit.

Python-Programm ↓ DobotDllType.py ↓ DobotDll.dll ↓ USB / serielle Verbindung ↓ Dobot Magician

Diese Dokumentation konzentriert sich auf Funktionen, die im Dobot-Projekt praktisch verwendet wurden oder für die aktuelle Fehlersuche und Robotersteuerung wichtig sind.

Neu in dieser Fassung: Windows-DLL-Suchpfad mit os.add_dll_directory(), SetQueuedCmdForceStopExec(), Alarm-ID-Dekodierung und ein sicherer Wiederanlauf nach einem Alarm.

1. Verbindung

dType.load()

Aufgabe

Lädt die Dobot-Bibliothek DobotDll.dll und liefert ein API-Objekt zurück.

Aufruf

api = dType.load()

Beispiel

from sdk64 import DobotDllType as dType

api = dType.load()

Das Objekt api wird anschließend bei fast allen Dobot-Funktionen als erstes Argument benötigt.

Wichtig unter Windows: Ist DobotDll.dll in einem separaten Ordner wie sdk64, kann dType.load() trotz vorhandener DLL mit FileNotFoundError scheitern. Dann muss das DLL-Verzeichnis vor dem Aufruf registriert werden.

os.add_dll_directory() neuPython/Windows

Aufgabe

Registriert unter Windows ein zusätzliches Verzeichnis für die Suche nach nativen DLLs. Dies ist keine Dobot-API-Funktion, aber für unsere Projektstruktur mit sdk64/DobotDll.dll praktisch notwendig.

Aufruf

dll_verzeichnis_handle = os.add_dll_directory(
    str(sdk_verzeichnis)
)

Komplettes Beispiel

from pathlib import Path
import os
import sys

PROJEKTORDNER = Path(__file__).resolve().parent.parent
sdk_verzeichnis = PROJEKTORDNER / "sdk64"

if str(PROJEKTORDNER) not in sys.path:
    sys.path.insert(0, str(PROJEKTORDNER))

dll_verzeichnis_handle = os.add_dll_directory(
    str(sdk_verzeichnis)
)

from sdk64 import DobotDllType as dType

api = dType.load()
Warum das Handle gespeichert wird: Das von os.add_dll_directory() zurückgegebene Objekt sollte während des DLL-Ladens bestehen bleiben.
Typischer Fehler: DLL vorhanden: True bedeutet nur, dass die Datei am geprüften Pfad existiert. Es bedeutet nicht automatisch, dass Windows sie über den DLL-Suchpfad laden kann.

ConnectDobot()

Aufgabe

Stellt die Verbindung zwischen dem Python-Programm und dem Dobot Magician her.

Aufruf

dType.ConnectDobot(api, portName, baudrate)
ParameterBedeutung
apiAPI-Objekt aus dType.load()
portNameCOM-Port, zum Beispiel "COM13"
baudrateÜbertragungsgeschwindigkeit, gewöhnlich 115200

Beispiel

result = dType.ConnectDobot(api, "COM13", 115200)

Typischer Rückgabewert

[0, 'DobotSerial', '0.0.0']
if result[0] == dType.DobotConnect.DobotConnect_NoError:
    print("Dobot verbunden.")
Der COM-Port kann sich unter Windows ändern. Deshalb sollte vor dem Verbindungsaufbau geprüft werden, welcher Port tatsächlich vorhanden ist.

DisconnectDobot()

Aufgabe

Trennt die Verbindung zum Dobot.

dType.DisconnectDobot(api)

Empfohlenes Muster

try:
    # Dobot-Programm
    pass
finally:
    dType.DisconnectDobot(api)

2. Status und Position

GetPose()

Aufgabe

Liest die aktuelle Position und die Gelenkwinkel des Dobot aus.

pose = dType.GetPose(api)
[x, y, z, r, jointAngle1, jointAngle2, jointAngle3, jointAngle4]
pose = dType.GetPose(api)

print("X =", pose[0])
print("Y =", pose[1])
print("Z =", pose[2])
print("R =", pose[3])
print("J1 =", pose[4])
print("J2 =", pose[5])
print("J3 =", pose[6])
print("J4 =", pose[7])
IndexWert
0X-Koordinate
1Y-Koordinate
2Z-Koordinate
3Rotation R
4Gelenkwinkel J1
5Gelenkwinkel J2
6Gelenkwinkel J3
7Gelenkwinkel J4
Wichtig: Eine ausgelesene Position kann geometrisch problematisch oder außerhalb eines zulässigen Bewegungsbereichs liegen. Eine Statusabfrage bewegt den Roboter nicht.

3. Befehlswarteschlange

SetQueuedCmdClear()

Aufgabe

Löscht die gespeicherte Befehlswarteschlange des Dobot.

dType.SetQueuedCmdStopExec(api)
dType.SetQueuedCmdClear(api)
Achtung: SetQueuedCmdClear() ersetzt nicht automatisch einen erzwungenen Stopp eines aktuell laufenden Befehls. Für eine sofortige Unterbrechung ist SetQueuedCmdForceStopExec() vorgesehen.

SetQueuedCmdStartExec()

Aufgabe

Startet die Ausführung der in der Queue gespeicherten Befehle.

dType.SetQueuedCmdStartExec(api)

SetQueuedCmdStopExec()

Aufgabe

Stoppt die weitere Abarbeitung der Befehlswarteschlange.

dType.SetQueuedCmdStopExec(api)
Wichtig: Ein Befehl, der beim Aufruf bereits ausgeführt wird, kann weiterlaufen. Für einen unmittelbaren Stopp ist SetQueuedCmdForceStopExec() vorgesehen.

SetQueuedCmdForceStopExec() neu

Aufgabe

Stoppt die Ausführung der Befehlswarteschlange zwangsweise. Auch ein aktuell ausgeführter Queue-Befehl wird gestoppt.

Aufruf

dType.SetQueuedCmdForceStopExec(api)

Typischer Einsatz

# Aktuelle Bewegung sofort unterbrechen
dType.SetQueuedCmdForceStopExec(api)

# Kurz warten, damit der Controller den Zustand verarbeitet
dType.dSleep(300)

# Alte Queue vollständig löschen
dType.SetQueuedCmdClear(api)
FunktionVerhalten
SetQueuedCmdStopExec()Stoppt die weitere Queue-Abarbeitung; ein bereits laufender Befehl kann weiterlaufen.
SetQueuedCmdForceStopExec()Erzwingt den Stopp auch eines aktuell laufenden Queue-Befehls.
Sicherheitsrelevant: Ein erzwungener Stopp ist für Ausnahme- und Fehlerzustände gedacht. Danach sollten Queue und Alarmstatus kontrolliert werden, bevor neue Bewegungsbefehle gestartet werden.

GetQueuedCmdCurrentIndex()

Aufgabe

Liest den Index des zuletzt ausgeführten Queue-Befehls.

ziel_index = dType.SetPTPCmd(
    api,
    dType.PTPMode.PTPMOVLXYZMode,
    200, 0, 50, 0,
    isQueued=1
)[0]

dType.SetQueuedCmdStartExec(api)

while dType.GetQueuedCmdCurrentIndex(api)[0] < ziel_index:
    dType.dSleep(100)

dType.SetQueuedCmdStopExec(api)
Der Queue-Index zeigt den Fortschritt der Befehlsabarbeitung. Er beweist nicht automatisch, dass der Roboter die gewünschte Zielposition ohne Alarm erreicht hat. Bei sicherheitskritischen Abläufen zusätzlich Alarmstatus und Endposition prüfen.

Hilfsfunktion warten_bis_fertig() Hilfsfunktion

Diese Funktion stammt nicht direkt aus der Dobot-API, ist aber für eigene Programme nützlich.

def warten_bis_fertig(api, dType, ziel_index):
    dType.SetQueuedCmdStartExec(api)

    while dType.GetQueuedCmdCurrentIndex(api)[0] < ziel_index:
        dType.dSleep(100)

    dType.SetQueuedCmdStopExec(api)

dSleep()

Aufgabe

Wartet eine bestimmte Anzahl Millisekunden.

dType.dSleep(500)

500 ms = 0,5 Sekunden

4. HOME und Alarme

SetHOMEParams()

Aufgabe

Legt eine benutzerdefinierte HOME-Position fest.

dType.SetHOMEParams(api, x, y, z, r, isQueued)
dType.SetHOMEParams(api, 200, 0, 80, 0, isQueued=0)
Achtung: Vor einer HOME-Fahrt prüfen, ob die gewählte Position mit dem montierten Werkzeug kollisionsfrei erreichbar ist.

GetHOMEParams()

Aufgabe

Liest die aktuell gespeicherten HOME-Parameter.

home = dType.GetHOMEParams(api)

print("HOME X:", home[0])
print("HOME Y:", home[1])
print("HOME Z:", home[2])
print("HOME R:", home[3])

SetHOMECmd()

Aufgabe

Startet die HOME-Funktion.

home_index = dType.SetHOMECmd(api, 0, 1)[0]
Achtung: HOME ist eine reale Roboterbewegung. Arbeitsbereich freihalten und auf ausreichende Z-Höhe achten.

GetAlarmsState()

Aufgabe

Liest den aktuellen Alarmstatus des Dobot aus.

alarm_result = dType.GetAlarmsState(api)
alarm_bytes = alarm_result[0]

if any(alarm_bytes):
    print("Alarm aktiv.")
else:
    print("Kein Alarm aktiv.")

Die Rückgabe enthält Alarmbytes. Jedes gesetzte Bit entspricht einer Alarm-ID. Für die praktische Diagnose ist deshalb eine Dekodierung sinnvoll.

Die genaue Bedeutung einer Alarm-ID sollte anhand der zur eingesetzten Firmware passenden Alarmtabelle geprüft werden.

Hilfsfunktion alarm_ids_lesen() neuHilfsfunktion

Aufgabe

Dekodiert die von GetAlarmsState() gelieferten Alarmbytes in eine Liste aktiver Alarm-IDs.

def alarm_ids_lesen(api, dType):
    alarm_result = dType.GetAlarmsState(api)

    alarm_bytes = alarm_result[0]
    alarm_laenge = alarm_result[1]

    alarm_ids = []

    for byte_index, byte_wert in enumerate(
        alarm_bytes[:alarm_laenge]
    ):
        for bit_index in range(8):
            if byte_wert & (1 << bit_index):
                alarm_id = byte_index * 8 + bit_index
                alarm_ids.append(alarm_id)

    return alarm_ids

Ausgabe der Alarm-IDs

aktive_alarme = alarm_ids_lesen(api, dType)

if aktive_alarme:
    for alarm_id in aktive_alarme:
        print(
            f"Alarm-ID {alarm_id} "
            f"(0x{alarm_id:02X})"
        )
else:
    print("Keine Alarme aktiv.")

ClearAllAlarmsState()

Aufgabe

Versucht, gespeicherte Alarmzustände zu löschen.

dType.ClearAllAlarmsState(api)
dType.dSleep(500)

alarm_result = dType.GetAlarmsState(api)

if any(alarm_result[0]):
    print("Es ist weiterhin ein Alarm aktiv.")
else:
    print("Kein Alarm aktiv.")
Wichtig: Das Löschen des Alarmstatus beseitigt nicht automatisch die physische oder geometrische Ursache des Alarms. Ein Alarm kann unmittelbar erneut auftreten.

Robustes Muster

# 1. Laufende Queue-Bewegung sofort stoppen
dType.SetQueuedCmdForceStopExec(api)
dType.dSleep(300)

# 2. Alte Befehle löschen
dType.SetQueuedCmdClear(api)
dType.dSleep(300)

# 3. Alarm löschen
dType.ClearAllAlarmsState(api)
dType.dSleep(500)

# 4. Danach erneut prüfen
aktive_alarme = alarm_ids_lesen(api, dType)

if aktive_alarme:
    print("Alarm weiterhin aktiv:", aktive_alarme)
else:
    print("Alarmstatus gelöscht.")

Sicherer Wiederanlauf nach einem Alarm neu

Bei einem Alarm sollte nicht unmittelbar wiederholt derselbe Bewegungsbefehl gesendet werden. Zuerst muss der Zustand bereinigt und anschließend geprüft werden, ob der Alarm wirklich verschwunden ist.

1. Laufenden Queue-Befehl zwangsweise stoppen ↓ 2. Queue löschen ↓ 3. Alarm-IDs lesen und protokollieren ↓ 4. Alarme löschen ↓ 5. Alarmstatus erneut prüfen ↓ 6. Nur bei alarmfreiem Zustand neue Bewegung vorbereiten ↓ 7. Bewegung starten und Alarmstatus weiter überwachen
# Laufende Bewegung sofort stoppen
dType.SetQueuedCmdForceStopExec(api)
dType.dSleep(300)

# Alte Queue löschen
dType.SetQueuedCmdClear(api)
dType.dSleep(300)

# Alarme vor dem Löschen lesen
alarme_vorher = alarm_ids_lesen(api, dType)
print("Alarme vorher:", alarme_vorher)

# Alarme löschen
dType.ClearAllAlarmsState(api)
dType.dSleep(500)

# Alarme erneut prüfen
alarme_nachher = alarm_ids_lesen(api, dType)

if alarme_nachher:
    print("ABBRUCH: Alarm weiterhin aktiv.")
else:
    print("Alarmfrei – neue Bewegung kann vorbereitet werden.")
Wichtig: Ein Bewegungsbefehl kann von Python an die DLL übergeben worden sein, ohne dass der Roboter ihn tatsächlich ausführt. Deshalb nicht nur „Befehl gesendet“ melden, sondern Alarmstatus, Queue-Fortschritt und Endposition kontrollieren.

5. Bewegung und Endeffektoren

SetPTPCommonParams()

Aufgabe

Legt den allgemeinen Geschwindigkeits- und Beschleunigungsfaktor für PTP-Bewegungen fest.

dType.SetPTPCommonParams(api, velocityRatio, accelerationRatio, isQueued)
dType.SetPTPCommonParams(api, 20, 20, 0)

Damit werden Geschwindigkeit und Beschleunigung auf 20 % gesetzt.

GetPTPCommonParams()

Aufgabe

Liest die aktuell eingestellten allgemeinen PTP-Faktoren aus.

werte = dType.GetPTPCommonParams(api)
print(werte)

Typische Ausgabe: [100.0, 100.0].

SetPTPJointParams()

Aufgabe

Legt Geschwindigkeit und Beschleunigung der vier Roboterachsen für PTP-Bewegungen fest.

dType.SetPTPJointParams(
    api,
    v1, v2, v3, v4,
    a1, a2, a3, a4,
    isQueued
)
dType.SetPTPJointParams(
    api,
    200, 200, 200, 200,
    200, 200, 200, 200,
    isQueued=0
)

Reihenfolge: zuerst vier Geschwindigkeitswerte, danach vier Beschleunigungswerte.

GetPTPJointParams()

Aufgabe

Liest die aktuell eingestellten Joint-Parameter.

werte = dType.GetPTPJointParams(api)
print(werte)
[
    200.0, 200.0, 200.0, 200.0,
    200.0, 200.0, 200.0, 200.0
]

Werte 0 bis 3: Geschwindigkeiten. Werte 4 bis 7: Beschleunigungen.

SetPTPCoordinateParams()

Aufgabe

Legt Geschwindigkeit und Beschleunigung für kartesische PTP-Bewegungen fest.

dType.SetPTPCoordinateParams(
    api,
    xyzVelocity,
    rVelocity,
    xyzAcceleration,
    rAcceleration,
    isQueued
)
dType.SetPTPCoordinateParams(
    api,
    200, 100,
    200, 100,
    isQueued=0
)

GetPTPCoordinateParams()

Aufgabe

Liest die aktuell eingestellten kartesischen PTP-Parameter.

werte = dType.GetPTPCoordinateParams(api)
print(werte)

Typische Ausgabe: [200.0, 100.0, 200.0, 100.0].

Reihenfolge: xyzVelocity, rVelocity, xyzAcceleration, rAcceleration.

SetPTPCmd()

Aufgabe

Führt eine PTP-Bewegung aus beziehungsweise trägt sie in die Befehlswarteschlange ein.

index = dType.SetPTPCmd(
    api,
    ptpMode,
    x,
    y,
    z,
    r,
    isQueued
)[0]

Beispiel: lineare Bewegung

index = dType.SetPTPCmd(
    api,
    dType.PTPMode.PTPMOVLXYZMode,
    200, 0, 50, 0,
    isQueued=1
)[0]

Beispiel: MOVJ zu einer kartesischen Zielposition

index = dType.SetPTPCmd(
    api,
    dType.PTPMode.PTPMOVJXYZMode,
    200, 100, 50, 0,
    isQueued=1
)[0]

Beispiel: nur Z ändern

pose = dType.GetPose(api)

x = pose[0]
y = pose[1]
r = pose[3]

index = dType.SetPTPCmd(
    api,
    dType.PTPMode.PTPMOVLXYZMode,
    x, y, 50, r,
    isQueued=1
)[0]
Wichtig: Eine erfolgreiche Rückgabe oder ein Queue-Index bedeutet nicht automatisch, dass die Bewegung ohne Alarm ausgeführt wurde. Bei problematischen Ausgangspositionen zusätzlich Alarmstatus und tatsächliche Endposition prüfen.

SetEndEffectorSuctionCup()

Aufgabe

Schaltet den Saugnapf ein oder aus.

Sauger einschalten

dType.SetEndEffectorSuctionCup(
    api,
    True,
    True,
    isQueued=0
)

Sauger ausschalten

dType.SetEndEffectorSuctionCup(
    api,
    True,
    False,
    isQueued=0
)

6. Vollständiges Grundmuster

Vollständiges Grundmuster

Dieses Muster berücksichtigt die aktuelle Projektstruktur mit sdk64, registriert den DLL-Suchpfad, verbindet den Dobot und trennt die Verbindung zuverlässig wieder.

from pathlib import Path
import os
import sys

COMPORT = "COM13"
BAUDRATE = 115200

PROJEKTORDNER = Path(__file__).resolve().parent.parent

if str(PROJEKTORDNER) not in sys.path:
    sys.path.insert(0, str(PROJEKTORDNER))

sdk_verzeichnis = PROJEKTORDNER / "sdk64"

dll_verzeichnis_handle = os.add_dll_directory(
    str(sdk_verzeichnis)
)

from sdk64 import DobotDllType as dType

api = dType.load()

result = dType.ConnectDobot(
    api,
    COMPORT,
    BAUDRATE
)

if result[0] != dType.DobotConnect.DobotConnect_NoError:
    print("Verbindung fehlgeschlagen.")
    raise SystemExit

try:
    # Eventuell laufende Queue sicher stoppen
    dType.SetQueuedCmdForceStopExec(api)
    dType.dSleep(300)

    # Alte Befehle entfernen
    dType.SetQueuedCmdClear(api)

    # Alarmzustand prüfen
    alarme = alarm_ids_lesen(api, dType)

    if alarme:
        print("Aktive Alarm-IDs:", alarme)

        dType.ClearAllAlarmsState(api)
        dType.dSleep(500)

        alarme = alarm_ids_lesen(api, dType)

        if alarme:
            print("Alarm weiterhin aktiv:", alarme)
            raise SystemExit

    # Roboterprogramm
    pose = dType.GetPose(api)

    print(
        f"Position: "
        f"X={pose[0]:.1f}, "
        f"Y={pose[1]:.1f}, "
        f"Z={pose[2]:.1f}, "
        f"R={pose[3]:.1f}"
    )

finally:
    try:
        dType.SetQueuedCmdStopExec(api)
    except Exception:
        pass

    dType.DisconnectDobot(api)
Hinweis: Die Hilfsfunktion alarm_ids_lesen() ist weiter oben vollständig dokumentiert und muss vor diesem Grundmuster definiert oder importiert sein.

Erweiterungen dieser Fassung

  • Neu dokumentiert: SetQueuedCmdForceStopExec().
  • Neu ergänzt: os.add_dll_directory() für die Windows-DLL-Suche in unserer Projektstruktur.
  • Neu ergänzt: Hilfsfunktion alarm_ids_lesen() zur Dekodierung der Alarmbits.
  • Erweitert: ClearAllAlarmsState() mit anschließender Kontrolle.
  • Neu ergänzt: sicheres Wiederanlaufmuster nach einem Alarm.
  • Erweitert: Hinweise zur Überwachung von Queue-Fortschritt, Alarmstatus und tatsächlicher Endposition.