Converting DINT to ascii - Calling all bit wranglers

Hi,

I having trouble converting a DINT to ascii. I have a recipe that is represented in the PLC across 5 array elements in the following form:

Recipe[5] = 22355
Recipe[6] = 13620
Recipe[7] = 13620
Recipe[8] = 12832
Recipe[9] = 12337

Where each DINT represents two ascii chars. For example, looking at element 5 in binary we have
22355 → 0000 0000 0000 0000 0101 0111 0101 0011

The first byte 0101 0111 is the first ascii char, “W”
The second byte 0101 0011 is the second ascii char “S”

I need to convert the first two bytes of each 32-bit word into ascii chars and then concatenate all the chars to form the recipe. I am not sure what is the most efficient way to go about this. I.E. using scripting on a tag change event or the expression language. Any help would be much appreciated.

Thanks,
Patrick

If you were going to do this in a tag change event then you could use this script. Note this script will work in Version 7 or 8. For Version 7 you would need to change from system.tag.*Blocking() to system.tag.*All().

import struct
#read all tag values needed.
qValues = system.tag.readBlocking(['path/to/tag1','path/to/tag2','path/to/tag3','path/to/tag4','path/to/tag5'])

#convert to Ascii string
strVal = ''.join([struct.pack(qValue.value) for qValue in qValues])

#write value to new holding tag
system.tag.writeBlocking(['path/to/strTag'],[strVal])

You could do this in an expression to, though I haven't worked that out. You could use the expression from this post for some inspiration, it isn't exactly the same but it does take care of the conversion and concatenation. I think I prefer the script in this case.

That Irose,

I was trying something similar, but I wasn’t privy to the struct module. I tested the code, when I try to print the resulting string, strVal, I am getting am not getting a empty string. I don’t actually need to write back to a holding tag as the recipe will only be used for visualization in Ignition. Not sure why I am getting a blank string, but I don’t think it would have to do with writing to a holding tag.

Thanks for you help. I really appreciate it.

system.tag.readBlocking() will return a list of values, assuming that those values match what you gave, when I ran this code I got WS54542 01.

if you provide the code as you used it, then I can help trouble shoot it. I believe the script does work thogh, and strVal would only be “blank” if all the tags are 0.

Hi Irose,

I just double checked to make sure they didn’t change the recipe on me. It is still populated, and the returned string is correct. I wonder what I am missing. Please note the tag values are returned as DINTs. I am not sure if they need to be Binary.

I.E. [22355, Good, Mon Jul 18 11:52:53 PDT 2022 (1658170373008)]

Here is this code below that is producing the empty string:

import struct

paths = ['[default]Tags/Recipe_' + str(i) + '_' for i in range (5,10)]
qValues =  system.tag.readBlocking(paths)
strVal = ''.join([struct.pack(qValue.value) for qValue in qValues])
print strVal

You might like the performance of this one better:

from java.nio import ByteBuffer, CharBuffer
from java.nio.charset import StandardCharsets, CodingErrorAction

def wordsAscizBE(*args):
	bb = ByteBuffer.allocate(2 * len(args))
	for arg in args:
		if not arg & 0xff00:
			break
		bb.putShort(arg)
		if not arg & 0xff:
			bb.position(bb.position() - 1)
			break
	bb.flip()
	decoder = StandardCharsets.ISO_8859_1.newDecoder().onMalformedInput(CodingErrorAction.REPORT).onUnmappableCharacter(CodingErrorAction.REPORT)
	cb = CharBuffer.allocate(bb.limit())
	decoder.decode(bb, cb, True)
	cb.flip()
	return str(cb)

You can call this from runScript like so:

runScript("someLibraryScript.wordsAscizBE", 0, {tagpath.to.word1}, {tagpath.to.word2}, {tagpath.to.word3})

It stops without error at the first null or unconvertible character.

Hi pturmel,

I created a project script named “Dint_to_ascii_converter” and copied the above code. I then created an expression tag (type:String) in Ignition with the following arguments:

runScript("Dint_to_ascii_converter.wordsAscizBE", 0, {[.]Tags/Recipe_5_})

The tag is returning “Error_ExpressionEval”

Is this script in the project that is designated as the Global Scripting Project? Expression tags can only call functions in that project's library.

pturmel, that was it. I set the project as the Global Scripting Project and the tag evaluated correctly. Thanks for the help. I am still curious why the solution that Irose provided is not working on my system them. It is odd to me that it is returning blank from the print statement.

Where did you run the script from?

print doesn’t work the same in all scopes.

The tags being integers is expected.

Glad you’ve got a solution working.

Hi Irose,

For testing, I ran the script from the actionperformed event handler on a simple button.

How would you do this for a 32 bit DINT to covert to ascii. Using pturmel project script i am only getting two characters (i know that was all the original post was asking for). How can i modify the script to get the other two characters

Change the bb.putShort(arg) to bb.putInt(arg).

That did it. Thank you