I’ve been using TwinCAT 3 more or less since it was released, and since then it has become such an integrated part of my daily work that it’s my main software development platform. I like to develop software using TwinCAT 3, but I’ve come to the conclusion that there are some features I miss. I’m not the only person that uses TwinCAT 3, and this video is made in collaboration with someone that has vastly more experience in industrial automation than me – Peter Kurhajec. As we both work with TwinCAT 3 on a daily basis, we decided to do a video with the title “4 things we want in TwinCAT 4”. Consider this as a wish list for a future version of TwinCAT, so some kind of dream session.
One of the things that have annoyed me ever since I started using TwinCAT is the fact that if you create an enumeration, it will automatically have a global scope. It will be accessible from all functions and function blocks. What’s even worse is that if you create a library project with an enumeration and include that library in another project, the enumeration will be visible there, too. This pollutes the namespace by creating unnecessary types. But no more.
Some time ago I wrote a post about developing code for different runtimes, and since then I’ve come to the realization that there is so much information missing in that blog post that I simply needed to write another one. What’s even worse is that the information regarding development, deployment, and just general handling of several TwinCAT versions on the Beckhoff website is not that good. I’ve talked to numerous automation engineers regarding this topic, and everyone seems to have a different understanding about it. As I was working in a development project that had many PLCs (hundreds!) with different versions of TwinCAT, I finally had a good excuse to dive into the details of this. With this blog post, I’d like to share some of the facts and misconceptions.
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.
While doing software development in TwinCAT, I have always been missing some sort of generic data type/container, to have some level of conformance to generic programming. “Generic programming… what’s that?”, you may ask. I like Ralf Hinze’s description of generic programming:
A generic program is one that the programmer writes once, but which works over many different data types.
I’ve been using generics in Ada and templates in C++, and many other languages have similar concepts. Why was there no such thing available in the world of TwinCAT/IEC 61131-3? For a long time there was a link to a type “ANY” in their data types section of TwinCAT3, but the only information available on the website was that the “ANY” type was not yet available. By coincidence I revisited their web page to check it out, and now a description is available! I think the documentation has done a good job describing the possibilities with the ANY-type, but I wanted to elaborate with this a little further.
If you’ve done development in TwinCAT for some time, you’ve most likely come across at least one of the OSCAT libraries. These are open source libraries developed in accordance to the IEC61131-3 standard. They provide a total of three different libraries; OSCAT-Basic, OSCAT-Building and OSCAT-Network. I’ve so far only used the OSCAT-Basic library, which provides function blocks and functions for engineering, mathematics, string handling, time/date and much more. There is only a small problem with using the OSCAT-Basic library in TwinCAT – there is a broken reference in it! What follows is a guide on how you can fix this so that you can fully utilize this library in TwinCAT.