Verwenden des try/catch-Blocks zum Abfangen von Ausnahmen
Exceptions sollten meiner Meinung nach, nur für wirklich unerwartete Probleme verwendet werden, und nicht um einen „normalen“ Fehler zu erkennen. In diesem Artikel möchte ich euch zeigen für welche Fälle es Sinn macht und wie Ihr die Operatoren Anwenden könnt. Normalerweise würde ich sagen, dass die Fehler innerhalb eines Funktionsbausteins, an einen ErrorHandler geroutet werden. D.H. beim Erstellen eurer Bausteine solltet Ihr immer die Fehlerbearbeitung mit bedenken. So kann euer übergeordneter Programmteil entsprechend auf den Fehler reagieren und Maßnahmen, schlimmstenfalls ein sicheres Abschalten der Maschine, durchführen.
Auf der anderen Seite gibt es nun innerhalb des Funktionsbausteins oder des Programms Fehlerhaften Code oder Routinen die Exceptions auslösen. Mit der oben genannten Methode können wir diese Art von Fehler natürlich nicht behandeln. Unter anderem kann das bei überschreiten von Array-Grenzen passieren, oder wenn Ihr ins Dateisystem der SPS schreibt und keinen Zugriff habt. In diesem Fall wirft das Zielsystem, zum Beispiel, die Exception „Zugriffsverletzung“.
Lösung try/catch Block
Platziert die Codeabschnitte, die möglicherweise Exceptions auslösen, in einem _TRY
-Block, und platziert den Code, der die Ausnahmen behandelt, in einem _CATCH
-Block.
Das folgende Beispiel verwendet einen _TRY
/_CATCH
-Block, um eine mögliche Ausnahme abzufangen. Dabei wird der Programmablauf nicht gestoppt, sondern die Befehle im _CATCH
-Block bearbeitet. Die mSaveRawData
-Methode speichert, einen Datensatz, in die example.txt-Datei auf dem Zielsystem. Die gesamte Anweisung zum Speichern der Zeichenfolge wird in einen _TRY
-Block aufgerufen. Dem _TRY
-Block folgt ein _CATCH
-Block, der alle Ausnahmen abfängt.
Sollte die mSaveRawData-Methode eine Ausnahme produzieren, werden zuerst die Anweisung unter _CATCH
und danach die Anweisung unter _FINALLY
ausgeführt.
//Variable deklarieren VAR exceptionCode : __SYSTEM.ExceptionCode; path:STRING; END_VAR //Funktionsbaustein code __TRY bSaved := mSaveRawData(data, path); __CATCH(exceptionCode) mHandleExc(exceptionCode); __FINALLY mClearRawDataFilter(); //Im Finally abschnitt können wir unsere Daten bereinigen. __ENDTRY
Auf der Homepage von Microsoft gibt ein paar Vorschläge dazu, wann Ihr einen Code in einem try-Block platzieren solltet. Die Beispiele sind für .NET. Die bewährte Methoden, lassen sich allerdings, analog zu CODESYS übertragen.
Datentyp __System.ExceptionCode
Im Beispiel oben habt Ihr wahrscheinlich schon gesehen, dass ich eine variable vom Typ „_System.ExceptionCode“ deklariert habe. In diesem Datentyp findet Ihr alle unterstützten Exceptions.
TYPE ExceptionCode : ( RTSEXCPT_UNKNOWN := 16#FFFFFFFF, RTSEXCPT_NOEXCEPTION := 16#00000000, RTSEXCPT_WATCHDOG := 16#00000010, RTSEXCPT_HARDWAREWATCHDOG := 16#00000011, RTSEXCPT_IO_CONFIG_ERROR := 16#00000012, RTSEXCPT_PROGRAMCHECKSUM := 16#00000013, RTSEXCPT_FIELDBUS_ERROR := 16#00000014, RTSEXCPT_IOUPDATE_ERROR := 16#00000015, RTSEXCPT_CYCLE_TIME_EXCEED := 16#00000016, RTSEXCPT_ONLCHANGE_PROGRAM_EXCEEDED := 16#00000017, RTSEXCPT_UNRESOLVED_EXTREFS := 16#00000018, RTSEXCPT_DOWNLOAD_REJECTED := 16#00000019, RTSEXCPT_BOOTPROJECT_REJECTED_DUE_RETAIN_ERROR := 16#0000001A, RTSEXCPT_LOADBOOTPROJECT_FAILED := 16#0000001B, RTSEXCPT_OUT_OF_MEMORY := 16#0000001C, RTSEXCPT_RETAIN_MEMORY_ERROR := 16#0000001D, RTSEXCPT_BOOTPROJECT_CRASH := 16#0000001E, RTSEXCPT_BOOTPROJECTTARGETMISMATCH := 16#00000021, RTSEXCPT_SCHEDULEERROR := 16#00000022, RTSEXCPT_FILE_CHECKSUM_ERR := 16#00000023, RTSEXCPT_RETAIN_IDENTITY_MISMATCH := 16#00000024, RTSEXCPT_IEC_TASK_CONFIG_ERROR := 16#00000025, RTSEXCPT_APP_TARGET_MISMATCH := 16#00000026, RTSEXCPT_ILLEGAL_INSTRUCTION := 16#00000050, RTSEXCPT_ACCESS_VIOLATION := 16#00000051, RTSEXCPT_PRIV_INSTRUCTION := 16#00000052, RTSEXCPT_IN_PAGE_ERROR := 16#00000053, RTSEXCPT_STACK_OVERFLOW := 16#00000054, RTSEXCPT_INVALID_DISPOSITION := 16#00000055, RTSEXCPT_INVALID_HANDLE := 16#00000056, RTSEXCPT_GUARD_PAGE := 16#00000057, RTSEXCPT_DOUBLE_FAULT := 16#00000058, RTSEXCPT_INVALID_OPCODE := 16#00000059, RTSEXCPT_MISALIGNMENT := 16#00000100, RTSEXCPT_ARRAYBOUNDS := 16#00000101, RTSEXCPT_DIVIDEBYZERO := 16#00000102, RTSEXCPT_OVERFLOW := 16#00000103, RTSEXCPT_NONCONTINUABLE := 16#00000104, RTSEXCPT_PROCESSORLOAD_WATCHDOG := 16#00000105, RTSEXCPT_FPU_ERROR := 16#00000150, RTSEXCPT_FPU_DENORMAL_OPERAND := 16#00000151, RTSEXCPT_FPU_DIVIDEBYZERO := 16#00000152, RTSEXCPT_FPU_INEXACT_RESULT := 16#00000153, RTSEXCPT_FPU_INVALID_OPERATION := 16#00000154, RTSEXCPT_FPU_OVERFLOW := 16#00000155, RTSEXCPT_FPU_STACK_CHECK := 16#00000156, RTSEXCPT_FPU_UNDERFLOW := 16#00000157, RTSEXCPT_VENDOR_EXCEPTION_BASE := 16#00002000 RTSEXCPT_USER_EXCEPTION_BASE := 16#00010000 ) UDINT ; END_TYPE
Fehler finden trotz Exceptionhandling
Dadurch dass wir die_TRY
/_CATCH
-Blöcke einsetzten, wird unser Applikationscode im Falle einer Exception nicht mehr angehalten. Denn in diesem Fall, soll natürlich der Code im _CATCH
Blog für die weitere Bearbeitung, herangezogen werden. Wollt Ihr die Exception nun lokalisieren, könnt Ihr den Befehl ‘Ausführung an behandelten Exceptions anhalten’ verwenden.
Der Befehl ist standardmäßig deaktiviert, kann aber über
hinzugefügt werden. Dazu sind folgende Schritte notwendig:
Nachdem wir den Befehl in das Menü
konfiguriert haben und ihn dort aufrufen (funktioniert nur im Onlinebetrieb), können wir damit leicht die Ausnahme lokalisieren. Der Befehl bearbeitet die gerade aktive Applikation. Das ist wichtig zu wissen wenn Ihr mehrere Applikationen in einem Projekt habt.
Schreibe einen Kommentar