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.