I have been using TwinCAT for quite some time now, and since I started developing software with TwinCAT it has changed almost everything for me as a software engineer, both as a profession and as a hobby. This includes the programming language, development environment, software development processes, hardware, communication protocols and much more. I have recently philosophized about how my life as a software developer has changed compared prior to doing automation software. Overall, I would say that I can do tremendously more things (in a reasonable amount of time) with TwinCAT by myself, than I could do before when I was developing software in the “standard” programming languages. It has given me opportunities to work with insanely fun projects that I would never have worked with if I didn’t start with PLC software development. What I would want to share with you is a list of five things that I think Beckhoff have done right, and five things that they could improve.
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.
In my earlier posts I’ve written about development of TwinCAT software using test driven development (TDD), by writing unit tests. One of the advantages by adhering to the process of TDD is that you mostly will end up with function blocks (FBs) which have limited but well defined responsibility. Eventually you will however have FBs that are dependent on other function blocks. These could be FBs that are your own, or part of some 3rd party library, for example a Beckhoff library. Further, what if this external FB relies on some other functionality such as external communication using sockets that we have no control of? The external FBs should already be tested, we’re only interested in making sure our unit tests test our code! What do we do? A solution to this is to mock the external functionality and use dependency injection.