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.
The actual information is available under “Project” ->”<Name of project> properties” in Visual Studio 2015.
This will give you the following:
Now, how do you access this from PLC-code? To start with, for libraries this is easy and is actually documented in the Beckhoff documentation. Here you are supposed to use the type “ST_LibVersion“, and Beckhoff documentation explicitly states “Each library contains a global structure of this data type.” This struct type provides the following data:
TYPE ST_LibVersion : STRUCT iMajor : UINT; iMinor : UINT; iBuild : UINT; iRevision : UINT; sVersion : STRING(23); END_STRUCT END_TYPE
For instance, if you need access to the version of the commonly used “TC2_Standard“-library:
VAR sVersion : STRING(23); END_VAR
sVersion := stLibVersion_Tc2_Standard;
“stLibVersion_Tc2_Standard” is defined as a constant global variable in the project library. In this case it will for instance give you the string ‘22.214.171.124’.
Now, what if you want to include the version of your running program (not library!) that you have defined in your project properties? Because your program is not a library this constant global variable is not available per default as in library projects. What you need to do is to click “Add” next to “POUs for property access” under the project properties.
This will create the folder “Project Information” and the three functions “F_GetCompany()”, “F_GetTitle()” and F_GetVersion()” in your project. Opening F_GetVersion() gives the following:
Perfect, a function returning a “ST_LibVersion” structure holding the Major/Minor/Build/Revision numbers! Even though the “ST_LibVersion” in itself holds a String(23), for some reason this is not included in the call to F_GetVersion (at least not in TwinCAT 3.1.4020.28). Whether this is a bug or not is unknown to me. If you update the project information, this function automatically gets updated with the correct numbers! Now that we have access to this information by calling this function in our own program, we can easily convert this to a string by a mixture of UDINT_TO_STRING and CONCAT.
VAR sVersion : STRING(23); stProgramVersion : ST_LibVersion; END_VAR
stProgramVersion := F_GetVersion(); sVersion := CONCAT(UDINT_TO_STRING(stProgramVersion.iMajor), '.'); sVersion := CONCAT(sVersion, UDINT_TO_STRING(stProgramVersion.iMinor)); sVersion := CONCAT(sVersion, '.'); sVersion := CONCAT(sVersion, UDINT_TO_STRING(stProgramVersion.iBuild)); sVersion := CONCAT(sVersion, '.'); sVersion := CONCAT(sVersion, UDINT_TO_STRING(stProgramVersion.iRevision));
Running this code gives the end result:
Binary code icon by Vectors Market from www.flaticon.com / CC 3.0 BY
Did you manage the version number manually or was this number incremented automatically?
Manually, but it could be done automatically from a build server or such as it’s part of the XML-file definition of the project.
Hi Jakob, can you kindly share the hint of how to trigger automatic version number incremental through build event or the build server you said?
Hi Ju-Hsien! I’d solve it by a pre-build step in Jenkins. Simply add a step that opens the .plcproj-file and alters the
-tag prior to build. This can be done by any tool, such as a simple Python-script.
I would like to manage the version incremented automatically and is there a way to do it?
How can I do it from build server and/or XML file definition of the project?
sometimes I use this in my projects too. But I insert the ‘Global version structure’ and ‘POUs for property access’. Inside the global version structure is a constant of the type ST_LibVersion. The element ‘sVersion’ is initialized with the correct string (TwinCAT 3.1.2024).
stLibVersion_Title : ST_LibVersion := (iMajor := 1, iMinor := 2, iBuild := 3, iRevision := 6, sVersion := ‘126.96.36.199’);
Now I use this global constant in F_GetVersion:
FUNCTION F_GetVersion : ST_LibVersion
F_GetVersion := stLibVersion_Title;
Now, it’s not necessary to build the string for the version number.
Hi Stefan! Thanks for sharing this! I will use this in my future projects!
do you know if there is a method to have an automatic increment of the build number at the generation of the startup application ?