Is this the ultimate tool for generics in TwinCAT?

The answear is probably NO! But it will give you functionalities you may know from high level languages such as getting name or type of variable as a string.

And what are we even talking about? In one of my occasional raids to infosys in a quest to find some cool functions I have discovered methods called GetSymbolNameByAddress() and similar. Name looks promising so let’s try it out.

Library and licence

Method belongs to the FB_JsonReadWriteDataType object which is part of Tc3_JsonXml library. JsonXml in the name sounds alarming but don’t be afraid! The library is part of the base TE1000 licence so there should be no extra costs. Also this library is duplicitly documented in some IoT TwinCAT function which is a little confusing for me but so far TwinCAT did not ask for any extra licences for using Tc3_JsonXml library.

Useful methods

Of all the methods the FB can offer I find these two most useful in this case:

GetDataTypeNameByAddress()
GetSymbolNameByAddress()

Since codesys does not seem to have this functionality built into language by default then informations provided by these methods are probably obtained using ADS or some TwinCATs system whatever and thus it will probably not be as fast. Good thing is both methods return STRING so they are synchronous and will finish in the same cycle.

So let’s see whether it really works? We will create instance of FB_JsonReadWriteDataType, some test variable to get info about and variables to save obtained strings in. Methods require to input adress and size of variable.

Full variable name and datatype were successfully obtained.

Load test

We may now wonder how fast or slow is it actually? I have done test of million times executing both functions and compared the result with same amount of string assignments (because we are obtaining string from out methods).

On my laptop setup each method took roughly 200 ms to execute million times in a row as opposed to assigning string which takes around 5 ms. So the methods are roughly 50x slower than just assigning string and take around 2 us to execute single time on a laptop with modern cpu. With moderate usage this seems usable in my opinion.

*Running test repeatedly produced slightly different times in each test. Numbers mentioned are rought just to get some general idea about speed.

Wrapper class for ease of use

Whenever I see function requiring address and size of variable it hits me “this needs to be simplified with ANY datatype!” So here is my wrapper class / function block.

FUNCTION_BLOCK Symbol
VAR
	symbolReader		: FB_JsonReadWriteDatatype;
END_VAR
METHOD GetType : STRING
VAR_INPUT
	symbol			: ANY;
END_VAR

GetType := symbolReader.GetDatatypeNameByAddress(pData := symbol.pValue, nData := TO_UDINT(symbol.diSize));
METHOD GetName : STRING
VAR_INPUT
	symbol			: ANY;
END_VAR

GetName := symbolReader.GetSymbolNameByAddress(pData := symbol.pValue, nData := TO_UDINT(symbol.diSize));

How to use:

VAR
	symbolReader	: Symbol;
	name		: STRING;
	datatype	: STRING;
END_VAR

name := symbolReader.GetName(customType);
datatype := symbolReader.GetType(customType);

Final word

Interesting functionality which can help you when dealing with datatypes or variable names. Since neither ANY nor __VARINFO will give you datatype name of nonprimitive types this can be used instead (and is so far only way I know about). Also they are kinda universal because methods can be queried anytime with just pointer and size of variable. Downside is speed.

Example file

737 KB


Posted

in

by

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Optionally add an image (JPEG only)