The TBASIC compiler in i-TRiLOGI supports full 32-bit integer computations. However, only variable A to Z are 32 bits in length which allow them to represent number between -231 to -231, the remaining system variables and data memory DM[n] are all 16-bit variables which means that they can only store number between -32768 to +32767 (two adjacent 16-bit DMs can also form a 32-bit DM32[] variable). However, all numerical computations and comparisons in TBASIC are carried out in 32-bit signed integer, regardless of the bit-length of the variables involved in the numerical expression.
These may be entered directly in decimal form, or in hexadecimal form by prefixing the number with the symbol “&H”. e.g.
12345678
&H3EF =1007 (decimal)
If the result of an expression is outside the 32-bit limits, it will overflow and change sign. Care must therefore be exercised to prevent unexpected result from an integer-overflow condition.
A constant may be used in an assignment statement or in an expression as follow:
A = 12345
IF A*30 + 2345/123 > 100
THEN ….ENDIF
IMPORTANT (16-bit variables comparison) |
When entering an integer constant using the hexadecimal prefix “&H”, it is important to note the sign of the intended value and extend the signs to most significant bit of the 32 bit expression. E.g. to represent a decimal number “-1234”, the hexadecimal representation must be “&HFFFFFB2E” and not “&HFB2E”.
Assuming that a 16-bit variable DM[1] contains the number -1234 and a comparison statement is made to check if the number is -1234. The 32-bit hexadecimal representation of constant -1234 is &HFFFFFB2E. If you enter the constant as 16-bit representation “&HFB2E” as follow:
IF DM[1] <> &HFB2E CALL 5
TBASIC translates the number “&HFB2E” into a 32-bit decimal number 64302, which when compared to the number “-1234” contained in DM[1] will yield a “False” result which is an error. The following are the correct representation:
a) IF DM[1] <> -1234 CALL 5 : ENDIF
b) IF DM[1] <> &HFFFFFB2E” CALL 5: ENDIF |
Variables are memory locations used for storing data for later use. All Integer variables used in TBASIC are GLOBAL variables – this means that all these variables are shared and accessible from every custom function.
Specific examples with each variable type are shown below.
TBASIC supports the following integer variables:
- 26 Integer variables A, B, C….Z which are 32-bit variables. Note that the variable name is a single character by default; however, as mentioned above, you can append a comment to the variable. EG: A_temperature, A_distance – both refer to the same variable A
- A large, one-dimensional 16-bit integer array from DM[1] to DM[4000], where DM stands for Data Memory. A DM is addressed by its index enclosed between the two square brackets “[” and “]”. e.g. DM[3], DM[A+B*5], where A and B are integer variables. A comment can also be appended to DM[] variables as follows: DM[1]_Current_status_of _product1 – refers to variable DM[1].
- DM[1] to DM[4000] can also be used as 32-bit variables DM32[1] to DM32[2000] in the following manner:
DM[1] and DM[2] == DM32[1],
DM[3] and DM[4] == DM32[2]
...
DM[2N-1] and DM[2N] = DM32[N].
If you require lots of 32 bit variables it may be simpler to use only the DM32 and not the 16-bit DM. If you mix the use of both DM and DM32 then you need to manage the memory properly to ensure that they don’t overwrite each other memory space.The simulator fully support the use of DM32 variables in any expression. Wx100 and all SmartTILE-Fx based PLCs support DM32[n] variable. For FMD or Nano-10 PLCs only those with firmware > r78 supports DM32 variables. PLCs with older firmware cannot directly use DM32 in the program.
E.g. DM32[100] = DM[1] * A
- System variables. These are special integer variables that relate to the PLC hardware, which will be described in the next section.
NOTE: All of the following System Variables can have comments appended to them with the same format as described in section 5 (Integer Variable Comments).
Inputs, Outputs, Relays, Timers and Counters Contacts
The bit addressable I/Os elements are organized into 16-bit integer variables INPUT[n], OUTPUT[n], RELAY[n], TIMERBIT[n] and CTRBIT[n] so that they may be easily accessed from within a CusFn. These I/Os are arranged as shown in the following diagram:
Timers and Counters Present Values
The present values (PV) of the 128 timers and 128 counters in the PLC can be accessed directly as system variables:
timerPV[1] to timerPV[256], for timers’ present value
ctrPV[1] to ctrPV[256], for counters’ present value
DATE and TIME Variables
The PLC’s Real-Time-Clock (RTC) derived date and time can be accessed via variables DATE[1] to DATE[3] and TIME[1] to TIME[3], respectively as shown in the following table:
Date |
Time |
YEAR |
DATE[1] |
HOUR |
TIME[1] |
MONTH |
DATE[2] |
MINUTES |
TIME[2] |
DAY |
DATE[3] |
SECOND |
TIME[3] |
Day of Week |
DATE[4] |
|
|
DATE[1] : may contain four digits (e.g. 1998, 2003 etc). DATE[4] : 1
for Monday, 2 for Tuesday, …. 7 for Sunday.
High Speed Counters
The M-series and F-Series PLCs support High Speed Counters (HSC), which can be used to capture high frequency incoming pulses from positional feedback encoder. These high speed counters are accessible by CusFn using the variables HSCPV[1] to HSCPV[8]. All HSCPV[n] are 32-bit integer variables.
Special Variables – Legacy variables used 4 x special 16 bit integer variables
EMEVENT[1] to EMEVENT[4] – emEvent[1] is also used for email purpose. 16 x 16-bit integer variables: EMINT[1] to EMINT[16] 16 x 32-bit integer variables: EMLINT[1] to EMLINT[16]
“Operators” perform mathematical or logical operations on data. TBASIC supports the following integer operators:
i) Assignment Operator: An integer variable (A to Z, DM and system variables, etc) may be assigned a value using the assignment statement:
A = 1000 X = H*I+J + len(A$)
ii) Arithmetic Operators:
Symbol |
Operation |
Example |
+ |
Addition |
A = B+C+25 |
– |
Subtraction |
Z = TIME[3]-10 |
* |
Multiplication |
PRINT #1 X*Y |
/ |
Division |
X = A/(100+B) |
MOD |
Modulus |
Y = Y MOD 10 |
iii) Bitwise Logical Operators: logical operations is perform bit-for-bit between two 16-bit integer data.
Symbol |
Operation |
Example |
& |
logical AND |
IF input[1] & &H02 … |
| |
logical OR |
output[1] = A | &H08 |
^ |
Exclusive OR |
A = RELAY[2] ^ B |
~ |
logical NOT |
A = ~timerPV[1] |
iv) Relational Operators : Used exclusively for decision making expression in statement such as IF expression THEN ….. and WHILE expression ….
Symbol |
Operation |
Example |
= |
Equal To |
IF A = 100 |
<> |
Not Equal To |
WHILE CTR_PV[0]<> 0 |
> |
Greater Than |
IF B > C/(D+10) |
< |
Less Than |
IF TIME[3] < 59 |
>= |
Greater Than or Equal To |
WHILE X >= 10 |
<= |
Less Than or Equal To |
IF DM[I] <= 5678 |
AND |
Relational AND |
IF A>B AND C<=D |
OR |
Relational OR |
IF A<>0 OR B=1000 |
v) Functional Operators : TBASIC supports a number of built in functions which operate on integer parameters as shown below:
ABS(n), ADC(n), CHR$(n), HEX$(n), STR$(n)
For detailed explanation of these functions please refer to the next chapter: “TBASIC Language Reference”
The hierarchy of operators represent the priority of computation. Eg. X = 3 + 40*(5 – 2). The compiler will generate codes to compute 5 – 2 first because the parentheses has the higher hierarchy, the result is then multiplied by 40 because multiplication has a higher priority then addition. Finally 3 will be added to the result.
If two operators are of the same hierarchy, then compiler will evaluate from left to right. e.g. X = 5 + 4 – 3. 5+4 is first computed and then 3 will be subtracted. The following table list the hierarchy of various operator used.
Hierarchy |
Symbol |
Descriptions |
Highest |
( ) |
Parentheses |
|
*, / , MOD |
Multiplication/Division |
|
+, – |
Add/Subtract |
|
– |
Negate |
|
&, |, ^,~ |
Logical AND,OR,XOR,NOT |
Lowest |
=,<>,>,>=,<,<= |
Relational operators |
With i-TRiLOGI version 6.2 and above, you can now attach comments to any variable/register name of any length to make program easier to read. The compiler will ignore any alphanumeric characters (A to z, 0 to 9 and ‘_’) that are attached behind the variable name following an underscore character “_”. It is important to understand that by appending these comments to variables, no new variables are being created.
For Example: “X_Some_Integer” corresponds to variable “X”. An integer variable (such as DM[1]) can have different comments each time it is referenced in the same program because the compiler ignores the comments anyways. Although, in most cases it may be best to limit a variable to one comment to avoid potentially overwriting data since no new variables are actually created, as mentioned above. For Example: If an integer variable, DM[1], was named “DM[1]_one_integer” in one part of a program and named “DM[1]_two_integer” in another part of the program, then they will still both refer to DM[1]. If each variation has different integer data, then the data that was stored in the last variation that was updated will be the data in DM[1]. Then if the previous variation is accessed, it won’t contain the data that was originally stored in it.
We recommend you consider using the #Define Table (see next section) or #DEFINELOCAL command to assign easy-to-read names to variables which work much better than using this method of identifying a variable. We continue to support this legacy feature to maintain compatibility with some exiting user’s program that may still be using this method of naming variables.
With TRiLOGI version 6.42 and higher, it is possible to create a table of variable/constant/expression definitions. Please refer to Section 7.3 for details and examples.
h) Using #DEFINELOCAL keyword within a Custom Function
Starting from i-TRiLOGI version 6.47, besides using the #Define table you can also define label names that only has local scope by using the #DEFINELOCALlabelname = expression. E.g
#defineLocal RoomTemperature = DM[100]
You can then freely use the label name “RoomTemperature” within this custom function in place of DM[100] so that the program is more readable.
The #DEFINELOCAL keyword is useful if you only want the labels to be valid in the current function. It could make it easier to create a library function that you can re-use in other applications without exporting and importing the #Define table. Note that the compiler will first process any label names defined using the #DEFINELOCAL before it processes the #Define table.
However, unlike the #Define table the program does not conduct a check on whether you have duplicate #DEFINELOCAL on the same label, or whether a label so defined is a reserved keyword. So the programmer must exercise care when using #DEFINELOCAL to avoid ending up with hard-to-debug compilation errors.