BCD Converter

Hello,

I’ve written some expression code to scale Omron BCD values over OPC to regular values in Ignition since Ignition does not natively support BCD. I’ve also written some python script to allow the user to write a value back to a BCD point.

Is there a way that I can use the SDK to take out some of the layers? I currently have to have a “raw values” tag, a “scaled values” tag, etc. Could I somehow put it under “scaling” with a plugin via SDK? Is there some other way I could do this?

thanks

Are you sure you can’t just change the data type of the tag in Kepware to ‘Short’ or something like that?

Unfortunately, no, kepserver won’t cast types. It still serves the data to Ignition as BCD, which Ignition doesn’t support.

Well the thing is that OPC doesn’t support BCD either. It’s simply not a valid datatype. I’m surprised Kepware is serving up an incorrect value for a tag it must be claiming is an Int16/UInt16 over its OPC interface.

I’m pretty sure we’ve seen other people dealing with BCD encoded value sources before… I wonder how they’re dealing with it.

Is the Data Type in Kepware set to BCD?

EDIT: Here’s a pic to illustrate.

Observe how the Kepware browser correctly interprets the BCD value, but the Ignition OPC quick browser is unable to interpret the BCD as anything but a strange number:

You could use this:

def BCDtoDEC(x):
	result = ""
	o = "%o" % x
	neg = (o[0] == "-")
	for i in range(neg, len(o)):
		if (4 & int(o[i])):
			result += "1"
		else:
			result += "0"
		if (2 & int(o[i])):
			result += "1"
		else:
			result += "0"
		if (1 & int(o[i])):
			result += "1"
		else:
			result += "0"
	result = ("0" * (4 - (len(result) % 4))) + result
	finalresult = ""
	for i in range(0, len(result), 4):
		finalresult += str(int(result[i:i+4],2))
	return int(finalresult) * (1 - 2 * neg)

This looks like a bug in Kepware to me. It seems that you get a different value for the tag depending whether you’re accessing Kepware over OPC-DA or OPC-UA.

Try using the Ignition’s COM module, making a DA connection to Kepware, and see if the value is what you’re expecting when coming from the DA connection.

Don't know what to say, as we've been doing it for a couple of years. Just tried it out on a fresh install:

EDIT: Dang! Kevin Beat me to it.

[quote=“adamaustin”]You could use this:

def BCDtoDEC(x): result = "" o = "%o" % x neg = (o[0] == "-") for i in range(neg, len(o)): if (4 & int(o[i])): result += "1" else: result += "0" if (2 & int(o[i])): result += "1" else: result += "0" if (1 & int(o[i])): result += "1" else: result += "0" result = ("0" * (len(result) % 4)) + result finalresult = "" for i in range(0, len(result), 4): finalresult += str(int(result[i:i+4],2)) return int(finalresult) * (1 - 2 * neg) [/quote]
He’s getting the decimal representation of a BCD Number. Since BCD is really just hex without A-F, you just need to convert to hex to get it back-- which makes for a lot shorter code…

def dec2BCD(decNumIn): return int(str(hex(decNumIn))[2:])

[quote=“JordanCClark”]…you just need to convert to hex to get it back-- which makes for a lot shorter code…

def dec2BCD(decNumIn): return int(str(hex(decNumIn))[2:])[/quote]

Awesome!

I kept trying to use bin but it just wouldn’t work.

That's because Kepware is returning the value as BCD and Ignition is interpreting that value as an Int or Float depending on how you created the SQLTag.

If you go into Kepware and turn on Scaling for your tag, you can scale the tag from BCD to Int or Float and then Ignition should read the value correctly.

If you want to access the memory location directly through Kepware then you would add @BCD or @LBCD to the end of the memory location - D11002@BCD for 16bit or D11002@LBCD for 32bit.

1 Like

Using DA worked, but requires I buy the DA module. I don’t believe you can scale tags in Kepserver without “Advanced tags” plugin.

Unless you go the expression tag route, I have to assume buying the COM module for Ignition is your cheapest option.

There isn’t a Scaling tab under Tag Properties in your version of KepServer? It’s there in AutomationDirect’s version of KepServer, this is where you can have KepServer convert the BCD value to Int or Float.

kepware.com/Products/feature-datascaling.asp

It turns out the issue had to do with not properly addressing the PLC points with a letter at the end that provided the casting.