64-Bit Double Little Endian Input Register

Okay, I'm stuck. I'm trying to do a Modbus TCP read from a device only has 64-Bit Double Little Endian Input Registers. Modbus Poll can bring in the data correctly when selecting the data format as 64-Bit Double Little Endian but Ignition does not when doing a "Input Register Double" with a direct Modbus Address. I've tried doing [Device]1.IRD30001 with data type set to Double and tried [Device]1.IR30001 with data type set to Double. I've tried swapping the word order on the Device Connection as well.

I've also tried to do four individual integer reads and then created an expression tag to bring all four words in and changing around the word order with "stringFormat("%d%d%d%d", {[~]1_IRD30001}, {[~]1_IRD30002}, {[~]1_IRD30003}, {[~]1_IRD30004})".

Any other suggestions out there? The closest I've found on Ignition is the Omron Fins driver with setting the type as @LE but that failed.

I get values from most of the ways I've tried but just not the correctly formatted value...

Here is the register map from the manufacturer:

This is probably the approach you need, except string formatting doesn't do what you want. You need to use bitwise operators to combine the 4 registers.

edit: ooph, nevermind, it's actually a little trickier because it's a Float/Double and not a Long... will require scripting... hang on.

Okay... you need a script in a library like this:

def double_le(w1, w2, w3, w4):
	from java.lang import Double
	bits = w1 | (w2 << 16) | (w3 << 32) | (w4 << 48)

	return Double.longBitsToDouble(bits)

Then you can either call this however you like, or use runScript on an expression tag like:

runScript("ByteUtil.double_le", 0, {[~]W1}, {[~]W2}, {[~]W3}, {[~]W4})

If you need to write to the tag also you'll have to do the inverse of this, using doubleToLongBits... it's not pretty.

@pturmel's Modbus driver probably natively supports reading this type.

edit: also, you'd address each register/word as IR, not IRD.

1 Like

Would the data type for each tag still be Double with the IR? How about the final tag data type? I just tried your suggestion on an expression tag and it returns Error_ExpressionEval

No, the intermediate tags would be Integer, the final expression tag would be Double.

Before you go further, set your device to zero-based addressing, and drop the '3' prefix. So, 1.IRD0, 1.IRD4, and so on.

Didn't want to get into whether this was necessary yet... he does seem to be getting values at 30001 etc... 5 digit addressing is ambiguous :roll_eyes:

Same error on the expression tag.

Did you create a script in the library called "ByteUtils" and add that function? Is your "Gateway Scripting Project" set to the project containing this library?

https://docs.inductiveautomation.com/display/DOC81/Project+Library#ProjectLibrary-GatewayScriptingProject

I did not...sorry. Added to the Project Library now as you wrote it with the W1, W2... Pardon my ignorance but do I need to change those to a tag reference in the Project Library? And how does the runScript {[~]W1} need to be changed to reference each tag?

Your runScript looks fine, it should use your actual tag names.

Still getting the error. The link to the manual refers to placing the project name in the Gateway Settings but I am not seeing a field for Gateway Scripting Project to place the project name.
I'm sure I'm still doing something wrong...

Thanks for all the help on a Saturday morning! You as well @pturmel

Hmm, might not be necessary on Edge since there is only 1 project.

What is the error in the tag diagnostics?

Update: Error_TypeConversion("Invalid value: Tag value is Infinity or NaN.")
In the Script Console it works to output a value when I define the w1..etc with integers manually but I get nan if any of the values entered are a negative.

There should be more details with it.

I plugged in your numbers and see, though:

Try this change to the script:


def double_le(w1, w2, w3, w4):
	from java.lang import Double
	bits = (w1 & 0xFFFF) | ((w2 << 16) & 0xFFFF) | ((w3 << 32) & 0xFFFF) | ((w4 << 48) & 0xFFFF)

	return Double.longBitsToDouble(bits)

Now I get a very very small value that shows as 0 in the tag browser unless you double click.

If you can show me exactly what Mod Poll reads and the value it ends up with that will help.

I can't tunnel in using ModPoll while remote so I'm not sure what the current values are. I'm pulling in 5 registers with temperature being one of them. I'm trying the other register groups now but I'm getting the small 0 value on all attempts so far.

I think my script is wrong, it's rearranging the word order, not the byte order.

Maybe something like this instead:

def double_le2(value):
	from java.lang import Double
	b0 = (value >> 56) & 0xFF
	b1 = (value >> 48) & 0xFF
	b2 = (value >> 40) & 0xFF
	b3 = (value >> 32) & 0xFF
	b4 = (value >> 24) & 0xFF
	b5 = (value >> 16) & 0xFF
	b6 = (value >>  8) & 0xFF
	b7 = (value >>  0) & 0xFF
	
	return Double.longBitsToDouble(b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7)

and you only pass in 1 tag, not 4, addressed as IRI_6430001.