pcall in Dobot Lua: Fehlerbehandlung, die Ihre Roboterzelle nicht stoppt

Ein unbehandelter Lua-Fehler beendet das Roboterprogramm, und zwar sofort: Die Zelle steht, das Teil klemmt im Greifer und die Schicht ruft die Instandhaltung. Dabei stellt Lua mit pcall ein Werkzeug bereit, das genau das verhindert. Dieser Beitrag zeigt an DobotStudio-Beispielen, wie Sie Bewegungsbefehle absichern, Fehler gezielt wiederholen, eigene Fehlerobjekte definieren und Störungen zentral sichtbar machen, damit aus einem Laufzeitfehler kein Schichtstillstand wird.

Warum Fehlerbehandlung im Roboterprogramm anders tickt

In einer Desktop-Anwendung ist ein abgestürzter Prozess ärgerlich. In einer Roboterzelle bedeutet er: Das Programm bricht mitten im Zyklus ab, Achsen bleiben in undefinierter Position stehen, Werkstück und Greifer sind in einem Zustand, den niemand geplant hat. Der Neustart kostet nicht nur Minuten, er braucht oft eine Person, die den Roboter von Hand freifährt.

Typische Fehlerquellen im Dobot-Alltag: ein Werkstück liegt schief und die Bewegung läuft gegen einen Endschalter, eine TCP-Verbindung zum Kamerasystem bricht ab, eine Datei auf der SD-Karte lässt sich nicht öffnen, ein Sensor liefert einen unerwarteten Wert. Nichts davon muss das Programm beenden, wenn der Fehler an der richtigen Stelle abgefangen wird.

pcall in 60 Sekunden

pcall steht für "protected call": Die übergebene Funktion wird ausgeführt, aber ein Fehler in ihr beendet nicht das Programm. Stattdessen liefert pcall zwei Werte zurück: ein Erfolgsflag und, im Fehlerfall, die Fehlermeldung.

-- Grundmuster: geschuetzter Aufruf
local ok, err = pcall(function()
    riskante_funktion()
end)

if not ok then
    print("Fehler abgefangen: " .. tostring(err))
    -- Programm laeuft weiter, wir entscheiden, was passiert
end

Bewegungsbefehle absichern

Der praktischste Einstieg ist ein Wrapper um die Bewegungsbefehle. Statt MovJ und MovL direkt aufzurufen, kapseln Sie sie in einer Funktion, die Fehler abfängt, protokolliert und die Zelle in einen definierten Zustand bringt:

-- Global.lua: abgesicherte Bewegung mit Protokoll
function sichere_bewegung(name, bewegung)
    local ok, err = pcall(bewegung)
    if not ok then
        log_local("ERROR", "Bewegung '" .. name .. "' fehlgeschlagen: " .. tostring(err))
        DO(GREIFER, OFF)   -- Werkstueck kontrolliert ablegen bzw. Greifer oeffnen
        Sync()
        return false
    end
    return true
end

-- Verwendung im Zyklus
if not sichere_bewegung("Anfahrt Ablage", function() MovJ(P_ABLAGE) end) then
    return  -- Zyklus sauber beenden statt mitten in der Bewegung abzubrechen
end

Wiederholen mit Augenmaß: Retry mit Obergrenze

Nicht jeder Fehler ist endgültig. Eine abgerissene Netzwerkverbindung zum Kamerasystem oder ein kurz prellender Sensor sind nach einer Sekunde oft wieder da. Für solche Fälle lohnt ein Retry, aber immer mit Obergrenze und Wartezeit, sonst hämmert das Programm im Fehlerfall ungebremst weiter:

-- Wiederholung mit Grenze: max. 3 Versuche, 1 s Pause
function mit_retry(name, versuche, pause_ms, fn)
    for versuch = 1, versuche do
        local ok, err = pcall(fn)
        if ok then return true end
        log_local("WARN", name .. " Versuch " .. versuch .. "/" .. versuche
            .. " fehlgeschlagen: " .. tostring(err))
        Wait(pause_ms)
    end
    log_local("ERROR", name .. " endgueltig fehlgeschlagen nach " .. versuche .. " Versuchen")
    return false
end

-- Beispiel: Kamera-Trigger ueber TCP, verkraftet kurze Aussetzer
local ok = mit_retry("Kamera-Trigger", 3, 1000, function()
    local socket = TCPCreate(false, KAMERA_IP, KAMERA_PORT)
    TCPStart(socket, 0)
    TCPWrite(socket, "TRIGGER")
    TCPDestroy(socket)
end)

error() gezielt einsetzen: eigene Fehlerobjekte

pcall fängt nicht nur Laufzeitfehler, sondern auch alles, was Sie selbst mit error() auslösen. Das macht Plausibilitätsprüfungen elegant: Die Prüfung wirft, der zentrale Handler entscheidet. Als Fehlerwert ist auch eine Tabelle erlaubt, dann transportiert der Fehler strukturierte Information statt nur Text:

-- Pruefung wirft ein strukturiertes Fehlerobjekt
function pruefe_teil()
    if DI(SENSOR_TEIL) ~= ON then
        error({ code = "KEIN_TEIL", text = "Kein Werkstueck an Position" })
    end
end

local ok, err = pcall(pruefe_teil)
if not ok then
    if type(err) == "table" and err.code == "KEIN_TEIL" then
        -- erwartbarer Fall: Zufuhr leer, geordnet auf Nachschub warten
        log_local("WARN", err.text)
        warte_auf_nachschub()
    else
        -- alles andere ist ein echter Fehler
        log_local("ERROR", tostring(type(err) == "table" and err.text or err))
        fahre_grundstellung()
    end
end

Fehler sichtbar machen: zentrales Logging mit Leif

Abgefangene Fehler, die nur auf der Roboter-Konsole landen, sieht niemand. Erst mit zentralem Logging wird aus der Fehlerbehandlung ein Frühwarnsystem: Häufen sich die Retries an einer Station, kündigt sich ein mechanisches Problem an, lange bevor die Zelle wirklich steht. Wie Sie die log_local-Funktion aus den Beispielen um einen Versand an Leif erweitern, zeigt Schritt für Schritt der Beitrag Logging mit Dobot Lua. In Leif sehen Sie dann alle WARN- und ERROR-Meldungen Ihrer Roboter live, mit Alarm nach Microsoft Teams, und der Störungs-Zeitstrahl spielt zu jeder Meldung Kamerabild und Programmzeile nach.

Checkliste für robuste Dobot-Programme

  • Jeden Bewegungsbefehl über einen pcall-Wrapper führen, nie nackt im Zyklus
  • Im Fehlerfall zuerst den Greifer und das Werkstück in einen definierten Zustand bringen
  • Retries immer mit Obergrenze und Wartezeit, danach geordnet in den sicheren Zustand
  • Erwartbare Zustände (Zufuhr leer, Tür offen) mit error()-Objekten von echten Fehlern trennen
  • Jeden abgefangenen Fehler protokollieren, WARN für wiederholbare, ERROR für endgültige
  • Meldungen zentral sammeln, damit Häufungen auffallen, bevor die Zelle steht

Häufige Fragen

Was macht pcall in Lua genau?

pcall führt eine Funktion im geschützten Modus aus. Tritt darin ein Fehler auf, bricht nicht das Programm ab; stattdessen gibt pcall false und die Fehlermeldung zurück. Ohne Fehler liefert es true und die Rückgabewerte der Funktion.

Wann nehme ich xpcall statt pcall?

xpcall erlaubt zusätzlich einen eigenen Fehler-Handler, der noch im Moment des Fehlers läuft und zum Beispiel einen Stacktrace mit debug.traceback festhalten kann. Für die meisten Roboterprogramme reicht pcall; xpcall lohnt sich, wenn Sie bei der Fehlersuche wissen wollen, wo genau es geknallt hat.

Verlangsamt pcall das Roboterprogramm?

Der Aufwand eines pcall-Aufrufs ist gegenüber einer Roboterbewegung im Millisekundenbereich vernachlässigbar. In engen Schleifen ohne Bewegungen sollte man pcall nicht um jede einzelne Kleinstoperation legen, sondern um sinnvolle Blöcke.

Lassen Sie uns sprechen.

Kostenloses Erstgespräch: Wir melden uns schnellstmöglich zurück.