Automation Professionals' Advanced Modbus Driver

Hi Phil,
I've been running some tests and have been able to read HR, IR, C, and Di without any problems.
Now I'm trying to write a single coil (C) and I see that the driver uses function 15 (0x0F) to execute it when it should normally use function 05 (0x05). Is there a driver setting to correct this?

imagen

Regards, Andrés

There is a setting to disable the use of function 15 entirely. Then all coil writes are one-by-one with function 5. (Set the node write option "Max Coils" to zero.)

(The modbus spec seems pretty clear that function 15, if supported at all, needs to support writing single bits.)

This setting applies to the whole channel. It cannot be set per unit address.

1 Like

I tried this:

But then I get this when I write the Coil

I'll need logs for that.

1 Like

I sent it to you by email.

Sigh. Broken RTU implementation for functions 5 and 6.

For Ignition v8.1: v1.1.13.251071737

2 Likes

Well, the function 5 is now working fine, thanks.

I continued trying other things and had trouble using the rawModbus function via scripting.
I get this error when I run it:

When I run it using ID=2 for my device, it works fine, but as soon as I change it to 300, it starts to fail.

I sent you an email with the logs in case it helps.

That is a gateway scope function only.

Oh, that one doesn't accept units above 255 anyways. You will have to lie to it, and put the second byte of the unit in the payload.

1 Like

Hmmm. No, that won't work. :frowning:

Unanticipated lack of support for ELAM on the rawModbus function. Will have add that to my to-do list. It won't be soon. I have travels interfering.

2 Likes

Yeah, I know. I used the message handler you recommended a few years ago when you added the rawModbus function. In fact, I used it with ID:2 and it worked fine.

More. Hmmm. It should have worked. I see in the logs where you used rawModbus() to run function code 4, and the log message suggests you supplied an expected response length of 5 when that function returns 6 (16-bit bytes to follow, not 8).

Please test with something other than functions 3 and 4, or compute the response length for your tests using Lufkin expectations.

I don't see any reason the rawModbus function won't work with ELAM.

Oh, I see. I don't really understand how to calculate the expected response length. I used that size because I took it from an example where two HR were read, and I assumed it was the same for two IR. Is there a formula or function I can use to calculate the expected response length depending on the Modbus function and the number of registers to be read?

The modbus specification describes all of the packet formats, with examples.

The format of function code 4 is identical to function code 3, so your expected response length for reading two registers of either type is five. But not for ELAM.

1 Like

You were right!
I computed the response length (6 for 2 registers or 4 for 1 register), and it works.
The only downside is that using this code, I can't extract the values ​​from the read registers (I get "Bytes to follow=0"),


from java.io import ByteArrayInputStream, ByteArrayOutputStream, DataInputStream, DataOutputStream
from com.inductiveautomation.ignition.common.model.values import QualifiedValue

baos = ByteArrayOutputStream()
dos = DataOutputStream(baos)
#Read start address and quantity
dos.writeShort(1)
dos.writeShort(1)

#Ensure data is in the byte stream
dos.flush()

rpcPayload = {'devName': 'POFF-LABO', 'unit': 300, 'functionCode': 4, 'payload': baos.toByteArray(), 'responseLen': 4}
retv = system.util.sendRequest('Test', 'RawModbus', rpcPayload)


if isinstance(retv, QualifiedValue):
	if retv.quality.good:
		bais = ByteArrayInputStream(retv.value)		
		dis = DataInputStream(bais)
		bCount = dis.readByte()		
		print "Bytes to follow=%d" % bCount
		while bCount > 0:
			bCount -= 2
			register = dis.readShort()
			print "Register = %d" % register
	else:
		print repr(retv)
else:
	print retv

but I know it's working because I can see it in Wireshark.

Unfortunately, I don't have enough programming experience to debug this code. :pensive_face: