TwinCAT Debug function
TwinCAT PLC Debug Function
(Using
System Check function)
|
TwinCAT PLC提供 System Check Function , 在 PLC 專案中引用 “CheckBounds,” “CheckDivByte,” 等Check Function時,編譯器會在相關聯運算時自動將該函式一同引入作編譯,以達到先設法避免TwinCAT PLC 出現執行過程的出錯;或避免執行過程變數超出定義邊界造成記憶體重疊,進而利於協助開發人員定位出錯誤碼的位置並修正。
[如何使用System Check function]
https://infosys.beckhoff.com/content/1033/tcplccontrol/html/tcplcctrl_checkbounds.htm?id=4661841464054853992
並依說明檔之範例定義VAR_INPUT & VAR_OUTPUT 層級變數,並將範例程式複製到函式的程式碼區塊中即可,不需特定自行呼叫,編譯器檢查到有此名稱之POU函數,即會自動在該運算時加入Check功能
[Foreword]
TwinCAT provides system
check functions in the TwinCAT PLC compiler. When a PLC project includes POU, “CheckBounds,”
“CheckDivByte,” etc., the PLC compiler produces additional program
code internally in certain conditions, such as index variable access or division
operation, and prevents the system from crashing or memory overlapping.
[How to use system function]
l
In TwinCAT2, it simply declares “Checkxxx function”
in a PLC project. After copying the sample code and compiling,
“Checkxxx function” will be embedded internally in program code.
l
In TwinCAT3, it can be directly activated by Add>POU for implicit checks in PLC
project.
l
Do not change the declaration part. To maintain the
functionality of the monitoring functions, the declaration part must not be
modified. The only exception is to add local variables.
l
Check function may cause increased system load.
Please use Check function only for test purposes.
[TwinCAT 2]
[Sample for CheckBounds]
The “CheckBounds” function is only
performed with a variable array index. A consistently faulty array index
results in a compiler error. TwinCAT calls the function implicitly as soon as
an ARRAY variable is assigned values.
Caution! This is an incorrect sample code. Run this
code will cause system no response or crash!
|
VAR iData : ARRAY [0..9] OF INT; diData : DINT; i : INT; bTest : BOOL; END_VAR |
IF bTest THEN FOR i := 0 TO
15 BY 1 DO iData[i] := i-1; END_FOR bTest := FALSE; END_IF |
In this sample, “i” exceeds the variable index range, which makes
the value of “diData” unpredictable*1. Index
variable “i” not only creates an infinite loop*2 but
consumes high real-time resource and makes no response from PLC.
To avoid index exceeding the boundary, “CheckBounds” function
could be used by simply putting in the PLC project as bellow.
|
VAR_INPUT index, lower, upper: DINT; END_VAR |
IF index < lower
THEN CheckBounds := lower; ELSIF index > upper
THEN CheckBounds := upper; ELSE CheckBounds := index; END_IF |
After putting this function in a project, the
check code generated by the function avoids index exceeding the variable
boundary and memory overlap.
However, the correctness of data is a big issue. In the example, the value of “iData[9]” is incorrect. Besides avoiding memory overlap, programmers require to modify the incorrect code. To detect the incorrect situation, “ADSLOGDINT”* could be applied to display the error or warning messages depending on the setting. In this sample, several windows pop up when the index is out of boundary.
*Note: ADSLOGDINT is illustrated in the Appendix of this document.
FUNCTION CheckBounds :
DINT VAR_INPUT index,
lower, upper: DINT; END_VAR VAR sMessage: STRING; diData: DINT; END_VAR |
IF index < lower
THEN CheckBounds
:= lower; sMessage := 'Out of boundary!
Lower boundary = '; sMessage := CONCAT(sMessage ,
DINT_TO_STRING(lower)); sMessage := CONCAT(sMessage , '.
Upper boundary = '); sMessage := CONCAT(sMessage ,
DINT_TO_STRING(upper)); sMessage := CONCAT(sMessage , '.
Current Index = %d'); diData := ADSLOGDINT(msgCtrlMask := ADSLOG_MSGTYPE_LOG, msgFmtStr := sMessage , dintArg := index); ELSIF index > upper
THEN CheckBounds := upper; sMessage := 'Out of boundary!
Lower boundary = '; sMessage := CONCAT(sMessage ,
DINT_TO_STRING(lower)); sMessage := CONCAT(sMessage , '.
Upper boundary = '); sMessage := CONCAT(sMessage ,
DINT_TO_STRING(upper)); sMessage := CONCAT(sMessage , '.
Current Index = %d'); diData := ADSLOGDINT(msgCtrlMask
:= ADSLOG_MSGTYPE_LOG, msgFmtStr := sMessage , dintArg :=
index); ELSE CheckBounds := index; END_IF; |
Result:
The log can be display on “Logger output” in System manager.
1.
The log can also
be recorded on “Event Viewer” in Windows. (Event Viewer is not included in CE
system.)
2.
For CE system,
check “Enable Log File,” set size and path in the tab of “TwinCAT settings” in “CX
configuration” in control panel. The log file named “tcsyslog” is generated in
the assigned folder.
[Sample for CheckDivxxxx]
The functions “CheckDivByte,
CheckDivReal, CheckDivWord and CheckDivDword” can be used to avoid division by
0. If you integrate these functions in the PLC project, they are called before
each division that occurs in the code. It is recommended that all of these “CheckDivxxxx”
functions are applied in the program due to different data types.
In the sample
below, the divisor is 0(799/0 =?). The divisor will be set to 1 by “CheckDivReal”
function before the compiler goes wrong. Therefore, the result is 799(799/1 =
799). User can also detect the situation in the log simply.
PROGRAM MAIN VAR bTest : BOOL; fResult : REAL; fDivident
: REAL := 799; fDivisor : REAL := 0; END_VAR |
FUNCTION CheckDivReal
: REAL VAR_INPUT divisor : REAL; END_VAR VAR sMessage: STRING; diData: DINT; END_VAR |
IF bTest THEN fResult := fDivident / fDivisor; bTest := FALSE; END_IF; |
IF divisor = 0 THEN CheckDivReal := 1; sMessage := 'The divisor is %d! '; diData := ADSLOGDINT(msgCtrlMask
:= ADSLOG_MSGTYPE_LOG, msgFmtStr :=
sMessage , dintArg := 0 ); ELSE CheckDivReal := divisor; END_IF; |
Result:
The log can be display on “Logger output” in System manager.
[Sample for CheckRangexxxx]
In order to check
for observance of range boundaries at runtime, the functions “CheckRangeSigned”
and “CheckRangeUnsigned” must be introduced. They are implicitly called as soon
as a variable is written as belonging to a subrange type constructed from a
signed or unsigned type.
In the following
example, variable “y” is initially set to 10000. If “bCheckRange” is true, the
variable “Value” is limited to 4095. However, when “bCheckRange” is false, the
variable “Value” is 10000. According to the example, the “CheckRangexxxx”
function is required to be called when variables are needed to be checked
whether they are in the subranges.
Caution: If a
function CheckRangeSigned or CheckRangeUnsigned is implemented, a continuous
loop is created with the use of subrange in a FOR loop. This occurs exactly if
the area indicated for the FOR loop is as large or larger than that for the subrange.
PROGRAM MAIN VAR (*
Variables for CheckRange function *) Value : DINT; y : DINT := 10000; bCheckRange:
BOOL; END_VAR |
FUNCTION
CheckRangeSigned : DINT VAR_INPUT value, lower, upper: DINT; END_VAR VAR sMessage: STRING; diData: DINT; END_VAR |
(* CheckRange *) IF bCheckRange THEN Value := CheckRangeSigned(y, -4095, 4095); ELSE Value := y; END_IF; |
IF (value < lower) THEN CheckRangeSigned
:= lower; sMessage
:= 'Out of range! Lower range = '; sMessage
:= CONCAT(sMessage , DINT_TO_STRING(lower)); sMessage
:= CONCAT(sMessage , '. Upper range = '); sMessage
:= CONCAT(sMessage , DINT_TO_STRING(upper)); sMessage
:= CONCAT(sMessage , '. Current value = %d'); diData
:= ADSLOGDINT(msgCtrlMask :=
ADSLOG_MSGTYPE_LOG, msgFmtStr := sMessage , dintArg := value); ELSIF(value > upper) THEN CheckRangeSigned
:= upper; sMessage
:= 'Out of range! Lower range = '; sMessage
:= CONCAT(sMessage , DINT_TO_STRING(lower)); sMessage
:= CONCAT(sMessage , '. Upper range = '); sMessage
:= CONCAT(sMessage , DINT_TO_STRING(upper)); sMessage
:= CONCAT(sMessage , '. Current value = %d'); diData
:= ADSLOGDINT(msgCtrlMask := ADSLOG_MSGTYPE_LOG, msgFmtStr := sMessage ,
dintArg := value); ELSE CheckRangeSigned
:= value; END_IF; |
Result:
The log can be display on “Logger output” in System manager.
[TwinCAT 3]
It is more user-friendly to apply “Check functions” in the program in TwinCAT3. Right click on POUs à Select Add à Select POU for implicit checks… à Check the functions needed. The standard functions are included in the program automatically.
[Appendix]
[ADSFUNCTION ADSLOGDINT]
This
function issues when called a message box holding a specifiable text on the
screen, and writes an entry into the system’s log. Using the
ADSLOGDINT function, a DINT value (4 byte signed integer) can be inserted in
the text to be output at a point specified by the user. For this purpose the
stored format string must contain the characters ‘%d’ at the desired location.
The result value contains the function error code, or, if successful, 0.
msgCtrlMask : Control mask which
determines the type and effect of the message output (see separate table). “OR” can be used for the desired combination.
Constant |
Description |
ADSLOG_MSGTYPE_HINT |
Message type is advice. |
ADSLOG_MSGTYPE_WARN |
Message type is warning. |
ADSLOG_MSGTYPE_ERROR |
Message type is error. |
ADSLOG_MSGTYPE_LOG |
Message is written into the log. |
ADSLOG_MSGTYPE_MSGBOX |
Message is output to a message box. |
ADSLOG_MSGTYPE_STRING |
Message is a directly given string (default). |
msgFmtStr : Contains the message to be issued. It can contain the
formatting code ‘%d’ for the output of a DINT value at any position.
dintArg : Contains the numerical value
to be inserted into the message.
留言
張貼留言