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?
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.
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:
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.
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…
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.
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.