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.
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.
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
Test driven development (TDD) doesn’t seem to be all too common among TwinCAT-developers, which is a shame. From my experience, TDD has a strong foothold everywhere among developers, but TwinCAT? Not so much. And I don’t blame them. There are TDD frameworks for C++, C#, Ada, Python and basically any other language and/or development environment. Do a Google search on the web on any programming language/IDE and TDD and you get thousands of results. Do the same for TwinCAT and you’re on your own.
Together with TwinCAT release 4022.0 Beckhoff released their product “TE1200 – TC3 PLC Static Analysis“. It’s a tool integrated in the development environment to help the developer increase the quality of the code. Other than being able to set your own naming conventions for the code, TE1200 can be used for various rule checks, for example:
- non-assigned return values
- usage of object-oriented features
- unreachable code
This post has really not too much to do with TwinCAT, at least not directly. Instead, this post will be about a computer that’s close to my heart. So, despite not being directly related to TwinCAT, it’s about the computer which started my interest in software engineering, and ultimately led me to where I am today, therefore this post. The Commodore 64 was my first computer. The first version was released the same year I was born. Rewind the time back to the mid 80s, and this was the computer that everyone had back in those days. It was a fantastic machine back then. 1MHz clock frequency, amazing video-graphics, a whopping 64K of user RAM (hence the name) and fantastic sound (provided by the SID-chip). Despite the limited performance when judged by today standards, people were doing amazing stuff with it. The game and demo-scene was flourishing.
I guess you’ve seen the news, TwinCAT 3.1.4022.0 has been released. At one point or another, when developing TwinCAT software you eventually end up in wanting to write code for the latest runtime, but still being able to do software bug fixes/releases for code running on older TwinCAT runtimes. I thought it would be good to quickly share with you how you can work and develop multiple projects developed for different runtime versions but from the same developer machine!
When creating TwinCAT software I’ve come across a use case where I want to print out and store the actual version of the project that the program resides in. This can be pretty neat when you do version control, and for instance create a release of your program and want this information available somewhere in the output of the program. I’ve had this scenario when we had a project that was continuously updated. The test/integration team needed constant bug fixes/new software releases. As a software engineer I needed to keep track of what version the test/integration team were actually running at a specific time. By updating the version number in the project information I was being able to log the actual running version of the software in a database, which is important to know when going back to fault trace any strange behavior in a particular test.
PLCopen has released their coding guidelines for 61131-3 structured text (ST) some time ago. If you haven’t read that yet, I highly recommend you to do so! Even if I don’t agree with everything, it’s still a good read and a really good initiative to consolidate all the different coding guidelines that every vendor has for their 61131-3 ST environment.
Included in this is Rule L16 “Define the use of tabs”. Let me quote:
Use of tab character (ASCII code 9) should be avoided, and Programming Support Environment set to replace tabs with spaces
This is a common rule in many projects, as this simplifies copying of code into other contexts and makes the code less dependent on the user settings for display. Simply put, the visual interpretation of a tab character varies wildly. As the TwinCAT development environment integrates into visual studio, this is the place we need to do our change. I’m going to use visual studio 2015 community edition for this particular demonstration, but it should be more or less the same in the other versions of visual studio.
When I develop software I mostly do the testing on my development computer. It is after all one of the big strengths of being able to run your code on a PC platform – it should more or less work the same on a PC based PLC. But then there is only so much testing you can do in your development machine, at some point you still end up needing to have the real hardware. I’ve already ended up with having some EtherCAT-slaves connected to the development computer so I decided I’ll go for a PLC to split the development computer and run-time environment completely. As Beckhoff has released PLCs from their embedded line with Windows 10 IoT Enterprise LTSB I though that was another reason good enough to buy one and experiment with it. Ended up with a CX5140 with 4gb of RAM and 32GB of flash-storage. Works like a charm out of the box, and I’ve already noticed some changes compared with running a controller with Windows 7 embedded. Since Windows 8 embedded, Microsoft have apparently replaced the FBWF (File-Based Write Filter) with the new UWF (Unified Write Filter). I’ll continue running/testing all my code on this controller, and will be posting new content to this blog as often as I can.