twincat

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.

Read more

When being in an early phase of a project, it’s common to use “latest and greatest” of the dependencies that your software relies on. In the beginning of a project, it’s usually low risk to built your system on the latest of everything as you’ve got plenty of time to make sure everything works as expected. I guess that’s one of the many joys of starting a new project, you are more free and can experiment more. But as you get closer and closer to the delivery of the project, it’s usually a good idea to start and “freeze” parts of the software. This includes everything from own developed libraries, TwinCAT supplied libraries, drivers, TwinCAT runtime and even the operating system on the target device (which anyways doesn’t change too often). Twenty years from now, I want to be able to compile and build the exact same executable binary that is running on that nice expensive machine right now. When I was close to delivery of a TwinCAT project, I got some problems related to this topic.

Read more

Software engineers make mistakes. No matter how well experienced you are, or how many unit tests you’ve written for your code, or how well reviewed the code is, we’re humans and at some point or another we’ll make mistakes. It can be a null pointer reference, an out-of-bound indexing of an array, segmentation fault, a zero-division or any other selection of the thousands of software bugs that should not happen but will happen. In my current area, development of wave energy converters (WEC), I don’t have the luxury of being able to easily reboot the PLC/controller if a software crash happens. I can’t just walk up to the system, and do a power-reset. The WEC can be far out in the ocean. Going out on the ocean and doing any form of maintenance involves costs, which we want to avoid. With this type of scenario, it’s time to consider a watchdog timer.

Read more

We’re finally at the last post of this series! Patiently we’ve written all our tests and done all our code that implements the required functionality and made sure that our code passes all the tests. But in the end of the day, despite all the theory and coding we want our code to run on a real physical device. Now it’s time for the favorite part of every PLC programmer, which is getting down to the hardware and micro controllers! Let’s get to the grand finale, and test our code on a real PLC, IO-Link master and IO-Link slave.

Read more

In part five of these series we started the implementation of the function blocks that we previously have done unit tests for. As we have our tests, we could verify that our newly implemented code did what it is supposed to do, and thus we made our code pass the tests. What we’ve got left is to do the implementation for three of the remaining function blocks. Once this is done, we have implemented all the required functionality that we’ve declared that our unit tests require us to.

Read more

In the last post of the series of unit testing in TwinCAT we finalized our unit tests, thus creating the acceptance criteria for the expected functionality for our function blocks. Now it’s time to do the actual implementation of the function blocks that we described in part 2 of these series. As we have our unit tests finished, we can anytime during our development run them and check whether the implemented code passes the tests.

Read more

In the previous post we defined the general layout of our unit tests, and also did the implementation of the tests for two of the five function block that we’re going to use to verify the functionality of parsing IO-Link events. What we’ve got left is to create test cases for the parsing of the text identity and the timestamp of the diagnostic event. Then we also want to have a few tests that closes the loop and verifies the parsing of a complete diagnosis history message.

Read more

In the last post of this series we were looking at a use case for a certain set of functionality, more specifically creating parser function blocks for the handling of IO-Link events. The result was a series of function blocks with defined input and output. In this post we’ll create the unit tests that will use the function blocks that we’ve started doing. Naturally, when defining the tests they will all fail as we don’t have the implementation code ready yet.

Read more

In my previous post I explained some of the benefits of using test driven development (TDD) while developing PLC software. This post is the second part of a series of seven, where we will look at a real use case scenario of writing test cases prior to doing the actual implementation. The scenario which I thought would be good for this is by creating a parser for IO-Link events. Shortly, IO-Link is a standardized point-to-point serial communication protocol used to communicate with sensors and/or actuators. It is not a fieldbus, but only takes care of the communication to the end device. As it’s a fully digital protocol that on top of process data also supports services such as events and parameterization, it’s standing well prepared for the Industry 4.0 thinking. One of the functionalities of IO-Link devices is that they can fire off events to the IO-Link master to notify that something has happened, for instance an alarm that something is wrong. To integrate these IO-link devices (slaves) into your EtherCAT network you need an IO-Link master, which usually allows you to connect 4 or 8 IO-Link slaves.

Read more

One problem I face quite often is that I need to have some code executed only once in the first cycle of the PLC, and then never again. Up until now I’ve always used a boolean of some sort; “bFirstCycleExecuted”, instantiated to false and then set to true after the first cycle resulting in something like:

PROGRAM MAIN
VAR
    bFirstCycleExecuted : BOOL := FALSE;
END_VAR

IF NOT bFirstCycleExecuted THEN
    // The code that you want to be executed at the first cycle
    bFirstCycleExecuted := TRUE;
END_IF

There actually is a built-in way in TwinCAT to know whether the current cycle is the first one or not, using the global data type PlcTaskSystemInfo. Among other parameters in this data type is the boolean FirstCycle. In your program you have access to an array of the data type PlcTaskSystemInfo, accessing it by _TaskInfo[index_of_current_task]. The index of current task can be retrieved by using the function block GETCURTASKINDEX. Replacing the above piece of code with our new knowledge results in:

PROGRAM MAIN
VAR
    fbGetCurTaskIndex : GETCURTASKINDEX;
END_VAR

fbGetCurTaskIndex();
IF _TaskInfo[fbGetCurTaskIndex.index].FirstCycle THEN
    // The code that you want to be executed at the first cycle
END_IF
Read more