Beckhoff#Let’s use the TRY, CATCH, FINALLY, and ENTRY! Statement!

This article describes TRY, CATCH, FINALLY, and ENTRY, which can be used on 64Bit OS with Beckhoff 4026.

Come on, let’s enjoy FA.

TRY・CATCH・FINALLY・ENTRY?

These operators are an extension of the IEC 61131-3 standard and are used for exception handling in IEC code. try, catch, and finally are syntaxes used for exception handling in programming and are common in languages such as Java and JavaScript.

Required Platforms

Note that the 4024 version is only available for 32 BitOS.

  • TC3.1 Build 4024 for 32-bit runtime systems
  • TC3.1 Build 4026 for 64-bit runtime systems

Basic usage

Here is a look at how they work.

try block

The try block describes code that may throw an exception. If no exception is thrown, the catch block is skipped.

catch block

If an exception occurs within the try block, the program within this block is executed. This handles the exception and prevents the program from crashing.

finally block

The finally block is executed after try and catch, regardless of whether an exception was thrown or not. It is typically used for cleanup tasks or resource release.

Key Point

To summarize from the basic usage mentioned earlier, please note the following points for successful use of TRY, CATCH, and FINALLY.

  • The try Block contains code that may throw an exception, and the catch Block handles the exception.
  • The finally Block is useful for cleanup operations because it is executed regardless of whether or not an exception was thrown.
  • By using try, catch, and finally, you can write robust programs that handle errors well.

Statements

This will be TRY, CATCH, and FINALLY Statements.

__TRY
    <try_statements>

__CATCH(exc)
    <catch_statements>

__FINALLY
    <finally_statements>

__ENDTRY

<further_statements>

If an error exception occurs in the program that first appears under __Try, the PLC program will not stop.

Instead, it executes the following instruction _CATCH and starts exception handling.

The program under __FINALLY is then executed. Note that instructions under __FINALLY are always executed, i.e., instructions under __TRY are executed without throwing an exception.

Exception handling ends with __ENDTRY, after which the PLC program continues executing subsequent instructions (instructions after __ENDTRY).

__SYSTEM.ExceptionCode

The data type of the IEC variable representing error exceptions is __SYSTEM.ExceptionCode is: __SYSTEM. Such exceptions are caught by, for example, __TRY, __CATCH, __FINALLY, and __ENDTRY. the ExceptionCode data type can also be used to classify and log errors and exceptions that occur in the application code itself.

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

Advantages?

Using try, catch, and finally offers several advantages in programming.

✓Simplified error handling

This allows exceptions to be handled gracefully without crashing the program and facilitates error management.

✓Code Clarity

By specifying how exceptions should be handled in the Catch Block, the code becomes more readable and the action to be taken in the event of an error is clearly indicated.

✓Resource Management

Finally Block can be clearly programmed to ensure that resources such as files and database connections are properly released, helping to prevent resource leaks.

✓Multiple Exception Handling

Different types of exceptions can be caught and handled separately. This allows tailored responses to specific errors.

✓Easier debugging

When an exception occurs, the details of the exception can be captured and logged, making it easier to identify and debug problems.

✓Improved application stability

Implementing proper exception handling will improve overall application stability and lead to a better user experience.

Implementation

From now on,we will  use TRY, CATCH, FINALLY, and ENTRY to CATCH errors that lead to RUNTIME stoppage and record them in the Global Variable List.

DUT_History

This one defines 100 ExceptionCodes as an array and records the error contents when an exception occurs. nExcIndex is the Index of the next array to be recorded.

TYPE DUT_History :
STRUCT
    nExcIndex          : UINT:=0;
    aExceptionHistory  : ARRAY[0..99] OF __SYSTEM.ExceptionCode;
END_STRUCT
END_TYPE

F_ExceptionHisotryStack

Next, a Function Block is created to record the caught exceptions.

VAR

This is the FB Interface, which operates on the DUT_History defined earlier in VAR_IN_OUT.

FUNCTION F_ExceptionHisotryStack : BOOL
VAR_INPUT
InexcInput           : __SYSTEM.ExceptionCode;
END_VAR
VAR_OUTPUT

END_VAR
VAR_IN_OUT
ioData :DUT_History;
END_VAR
VAR
_MaxIndex:DINT;
END_VAR

Program

Here is the program content: UPPER_BOUND retrieves the Index of the array, and if the Index to be recorded is less than the maximum Index, it stores Exception information and sets the Index to +1.

_MaxIndex:= UPPER_BOUND(ioData.aExceptionHistory,1);


IF ioData.nExcIndex <=_MaxIndex THEN
ioData.aExceptionHistory[ioData.nExcIndex]:=InexcInput;
ioData.nExcIndex:=ioData.nExcIndex+1;
END_IF

MAIN

The last is the MAIN program, which contains an invalid pointer access and an error dividing by 0.

PROGRAM MAIN
VAR
History:DUT_History;
END_VAR
VAR
    nCounter_TRY1      : UINT;
    nCounter_TRY2      : UINT;
    nCounter_CATCH     : UINT;   
    nCounter_FINALLY   : UINT;

    exc                : __SYSTEM.ExceptionCode;
    lastExc            : __SYSTEM.ExceptionCode;

    pSample            : POINTER TO BOOL;
    bVar               : BOOL;
    nSample            : INT := 100;
    nDivisor           : INT;
END_VAR

__TRY
    nCounter_TRY1 := nCounter_TRY1 + 1;
    pSample^      := TRUE;                // null pointer access leads to “access violation” exception
    nSample       := nSample/nDivisor;    // division by zero leads to “divide by zero” exception
    nCounter_TRY2 := nCounter_TRY2 + 1;

__CATCH(exc)
    nCounter_CATCH    := nCounter_CATCH + 1;

    // Exception logging
    lastExc := exc;
    F_ExceptionHisotryStack(InexcInput:=exc,ioData:=History);

    // fix the error
//correct the Pointer
IF (exc = __SYSTEM.ExceptionCode.RTSEXCPT_ACCESS_VIOLATION) AND (pSample = 0) THEN
pSample  := ADR(bVar);
//corret the Divide value
ELSIF ((exc = __SYSTEM.ExceptionCode.RTSEXCPT_DIVIDEBYZERO) OR (exc = __SYSTEM.ExceptionCode.RTSEXCPT_FPU_DIVIDEBYZERO)) AND (nDivisor = 0) THEN
nDivisor := 1;
END_IF

__FINALLY
    nCounter_FINALLY := nCounter_FINALLY + 1;
__ENDTRY

Error

This is the part of the program that performs invalid pointer access and division by zero, and is executed in the __TRY Block.

Catch

Exceptions raised in __TRY Block are taken to __CATCH, the first exception corrects the value of the pointer pSample, and the second exception corrects the value of the divisor nDivisor. These two exceptions are also stored in a global array for exception history.

So, as a result, the array aExceptionHistory has the following values

  • aExceptionHistory[0] = RTSEXCPT_ACCESS_VIOLATION
  • aExceptionHistory[1] = RTSEXCPT_DIVIDEBYZERO
  • aExceptionHistory[2] to aExceptionHistory[99] = RTSEXCPT_NOEXCEPTION

Result

As you can see, an invalid pointer access and a divide-by-zero error will not stop TwinCAT

 Runtime.

You can see that the Global Variable List stores exceptions that occur in the program.

Footer_Basic

Please Support some devices for my blog

Amazon Gift List

Find ME

Twitter:@3threes2
Email:soup01threes*gmail.com (* to @)
YoutubeChannel:https://www.youtube.com/channel/UCQ3CHGAIXZAbeOC_9mjQiWQ

シェアする

  • このエントリーをはてなブックマークに追加

フォローする