PLC naming conventions

Name a few things that software developers always have strong opinions about and naming conventions on code is one of the things that surely will come up. What lengths for identifiers should we use? Should we use hungarian notation? CamelCase or under_score case? While programming guidelines covering these topics have been existing since the rise of the early programming languages, they are much less common for industrial control.

Initially the only one that I found was Beckhoffs for TwinCAT3. Most of Beckhoffs libraries and example code used this, even though even Beckhoff themselves have not been consistent. More recently PLCopen have released their coding guidelines written specifically for IEC61131-3. Just out of curiosity I decided to compare the two standards and their take on naming conventions, and comparing them to my own personal opinions.

A quote that I often come to think of when you having many (and often colliding) standards is:

The nice thing about standards is that you have so many to choose from – Andrew S. Tanenbaum

The PLCopen guidelines mandate that any scheme can be used for prefixes, as long as the notation is documented. Beckhoff however have created rules for the name prefixes, which makes sense since they want to have common names for their own libraries. While PLCopen leaves it open to the developer to decide for the naming conventions, they have provided some examples of naming prefixes of different types, which in turn is a reference to the 3rd edition of IEC61131-3. If we look at the case for prefixes of variables they are:

TypeBeckhoffPLCopen
ENUMee
ARRAYaa
STRUCTstst
REFERENCEref*ref
FUNCTION BLOCKfbfb
PROGRAMprg
BOOLbx
SINTnsi
INTni
DINTndi
LINTnli
USINTnusi
UINTnui
UDINTnudi
ULINTnuli
REALfr
LREALflr
TIMEttim
LTIMEtltim
DATEddt
LDATEdldt
TIME_OF_DAYtdtod
LTIME_OF_DAYtdltod
DATE_AND_TIMEDTdt
LDATE_AND_TIMEDTldt
STRINGsstr
WSTRINGwswstr
CHARN/Ac
WCHARN/Awc
BYTEnby
WORDnw
DWORDnd
LWORDnlw

* only if not used as method input, in which case it shall be prefixed according to the basic data type of the reference

PLCopen also show examples for prefix of scope:

ScopePrefix
Global scopeg
Local scopel
POU Parameterp
Temporary varaibletmp

And of control:

ControlPrefix
Inputi
Outputo

However, PLCopen mentions:

Attributes can be omitted if the Programming Support Environment clearly shows them by other means, for instance by hovering over it.

Which is my personal opinion, as the TwinCAT XAE (Visual Studio IDE) clearly shows the type of a variable by just hovering over it.

Hovering a variable “DonePrintingTestResults” in Visual Studio

In the screenshot we do not only clearly see the type (BOOL) but also the complete instance search path, what type of variable it is (instance, input, output) and the accompanying comment to the variable. This is a much clearer than for example putting “lin” in front of all integer and bit-based local input variable numbers, which is why I’ve started to avoid using prefixes altogether.

Regarding the use of case (capitals) then again PLCopen doesn’t mandate any particular standard other than that the use of capital letters in object names should be clear and consistent across the project. They do as a guideline however propose that:

  • UPPER_SNAKE_CASE should be used for constants, user defined types and keywords
  • Use UpperCamelCase for all other multi-word items

The Beckhoff rules doesn’t specify that that constants should be UPPER_CASE, but are on the same track with CamelCasing, let me quote:

If an identifier is made up of several words, the first letter of each word is capitalized (CamelCase). Usually, no delimiters such as ‘_’ are used between the words.

Personally I was all in for UpperCamelCase, but have started to doubt this since I decided to not let my opinions and feelings decide what I prefer, but rather let science speak. Considering the amount of developers around the world, someone must have done some science on this? I found this paper that in the abstract concludes:

Results indicate that camel casing leads to higher accuracy among all subjects regardless of training, and those trained in camel casing are able to recognize identifiers in the camel case style faster than identifiers in the underscore style.

“All fine then” I thought, but then I found a blog post that in the discussion puts forward some convincing arguments of why the results of the paper are flawed. At least the nerd inside of me got some fun reading on this topic.

At the end of the day, what matters are not the actual rules but rather that there are rules in a project and that they are used consistently followed. I would highly recommend you to read the PLCopen coding guidelines as they provide a good deal of information not only on naming conventions but more importantly on coding practices.

What are you personal preferences? Do you follow the Beckhoff or PLCopen naming conventions or do you have your own?

  • Share on:

5 Comments, RSS

  1. Mark 2019-02-13 @ 09:23

    An interesting post. I always encourage my clients to adopt a documented coding style, and have written many on their behalf. I often have to write one I do not entirely agree with, but having consistency is generally more important than anything else.

    I use camel case for all non-constant private variables, methods and properties, and upper camel case (which I refer to as pascal case) for all non-constant public.

    I also use upper snake for constants.

    I do make exceptions for property backing fields, where they exist, which are always prefixed with an underscore.

    Other prefixes I use in definition: Classes get a “T_”, Interfaces an “I”, Enums an “E_”, Function Blocks (differentiated from classes by implementation style) get an “FB_” and Functions an “F_”.

    If declaration, my public / private naming rules are used. I’m also a firm believer in well named variables, so maintainers can clearly see the intent of the software throughout.

    I’m generally against any kind of declarative encoding of type into variable names. They add clutter through the full software lifecycle. In Industrial Automation, surely everyone is now using an IDE that has some form of “intellisense” (auto-complete, hover-reveal, etc) too!

    Where clients have adopted my proposals wholesale, they have always been happier with the result. Their support staff, who are generally not software designers, find the resulting code easier to read.

    I keep coming back to this phrase, by John F Wood, in 1991 :
    “Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. Code for readability.”

  2. Yannick Asselin 2019-02-14 @ 18:43

  3. Juozas 2019-02-15 @ 10:04

    The company I work in now uses prefixes for data types. b – bool, i – int, r – real…
    I have to do that now, but I doubt there is significant advantage in doing that.

    I have worked on some software from large system integrators, which used many globals, but used prefixes to differentiate between functions of variables.
    For example, B_ for button, AI_ for analog inputs, SM for state machine functions, MAIN for main functions of parts of process, etc..

    It actually worked! Even though that software had almost all data declared globally(which I don’t propose), it was easy to read, understand and quick to modify.

    However, I know this company had done 50+ similar projects, so the had many chances to improve and refine it. You may not get the same results if you’re doing a one off project.

  4. robin 2019-03-12 @ 02:39

    Thank you,That’s great. I think we can put it on GitHub and let more people know about it, because industrial programming is such a mess.

  5. Guillaume 2019-05-20 @ 07:18

    The link to the PLCopen guidelines returned a 404…

    I like your content and TcUnit, btw! As I am a SW Engineer without a real automation background, I share your opinion that TDD for TwinCAT is a real addition to the field.

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.