Over the years I’ve come across some features of TwinCAT or programming in general which can improve your code or your coding experience. Read on to level up your TwinCAT game in 2022!
- Don’t repeat yourself, often abbreviated as DRY, is a saying in software development to denote unnecessary repeating code. One tell-tale sign if you write non-DRY code, is that you copy and paste a lot of code.
-
You can activate multi-line editing by pressing the Alt key and dragging your mouse across several lines. If you use this function a lot, then it is a sign that your code is probably not DRY. So it is time to think about how to refactor your code.
- A
_
can be used as a thousand-separator. For example:number : INT := 1_000_000;
. Or you can use scientific notation if most decimals are zeros:number : INT := 1E6;
. -
(TwinCAT 4024+) Use Ctrl + K, Ctrl + C to comment one or more lines and Ctrl + K, Ctrl + U to uncomment them again. Check InfoSys for more hotkeys.
- In a
CASE
statement you can use multiple cases1, 3, 61
or a whole range1..10
for a single case. For example:
// Instead of this
CASE aCase OF
1: Method1();
2: AnotherMethod();
3: AnotherMethod();
4: AnotherMethod();
6: Method1();
END_CASE
// You can do this
CASE aCase OF
1, 6: Method1();
2..4: AnotherMethod();
END_CASE
- Using numbers to denote a case is usually not the best way to denote a case. You can make cases self-documenting by creating an ENUM for each case.
- There are implicit enums or local enums in TwinCAT. They can be used if you only need an enum in a single function block. You can define them as follows:
colors : (Red, Blue, Green);
. See for more info this AllTwinCAT post. - If you have a method or a function which returns a boolean, try to avoid the usage of an
IF
statement. Since you’re returning a boolean, you can often do this in a single line:
// Do not do this
METHOD LargerThenTwelve : BOOL
VAR_INPUT
number : INT;
END_VAR
IF number > 12 THEN
LargerThenTwelve := TRUE;
ELSE
LargerThenTwelve := FALSE;
END_IF
// Do this
METHOD LargerThenTwelve : BOOL
VAR_INPUT
number : INT;
END_VAR
LargerThenTwelve := number > 12;
- Use
{attribute 'call_after_init'}
to call a method once after a function block was initialized. You can use this, instead of abInitialized
flag in your code, which inevitability you forget to set toTRUE
at least once 😉. - Prevent the usage of
POINTER
s. They can lead to some pretty unpredictable behavior since you’re accessing a piece of memory directly. A better alternative is to useREFERENCE
, because it has a cleaner syntax and type safety. Although also references need to be checked for validity as I wrote about earlier. For the health and safety of you and your code, I recommend to only use them if you’re memory constrained for example. - Try to prevent method calls from multiple tasks, since it makes debugging difficult. If you really have to do it, use this.
-
You can use bit access for integer variables. For example,
variable.2 := TRUE
, sets the third bit toTRUE
. There is read access as well. You can for example check if some bit of a number is true byIF variable.3 THEN ...
. This method allows you to decipher an error code where each bit represents a specific error. Note that bit access can be a factor five slower than using a bit mask.Timing results from Toni Kucic.