Modbus library with extended register range >9999 ?

Hi,
I have implemented the ArduinoModbus library in my project but found out, that it is limited to the register range of 0-9999. Unfortunately I have to address registers above that.

I need extended register referencing with six digits Modicon notation. Can someone give me a hint if there is an Arduino Modbus library capable to do so?

Thanks,
Chris

I have implemented the ArduinoModbus library in my project but found out, that it is limited to the register range of 0-9999. Unfortunately I have to address registers above that.

Please explain where you found that limitation. As far as I reviewed the sourc code the only limitation is the use of signed integers (instead of unsigned integers) but that limits the address to 0-32767.

I need extended register referencing with six digits Modicon notation. Can someone give me a hint if there is an Arduino Modbus library capable to do so?

That seems to be a quirk of Modicon, so every library should support it, you just have to calculate the correct first digit.

Hi Pylon, thanks a lot for your support!

Sorry, just saw, that the library I used is called arduino-modbus-slave, which is proposed in this topic: MODBUS Slaves with Arduino - Networking, Protocols, and Devices - Arduino Forum

using the library from:

[/pre]http://code.google.com/p/arduino-modbus-slave/downloads/detail?name=MODBUS.zip&can=2&q=

when setting register 9999 (regBank.set(49999,(word)12593)) it works fine
when setting register 10000 (regBank.set(410000,(word)12593)) this error pops up during compilation:

warning: large integer implicitly truncated to unsigned type [-Woverflow]

  • regBank.set(410000,(word)12593); *

Did you read the page behind the link I posted? Modbus doesn't support register addresses of 410000 as the address must be hold in a 16bit integer. If your Modicon PLC thinks the address must have 6 digits, just configure there 410000 but use 10000 on the slave.

Yes, thanks, I have read the page behind the link.

In my project the arduino uno runs as a modbus slave. It has to respond to the modbus master requesting the holding register 20481 at function code 4, which corresponds to a Modicon address 420481.

I know, that the 2 byte address can cover up to 32767 registers. But when using the mentioned Lib I have to add the function code (4) in front of the 16 bit address. The results is a Modicon address which is bigger than an integer.

My problem is, that this is not compatible with the Modbus lib I mentioned above (it allows only Word data type for register definitions including function code (see above warning [-Woverflow]). Unfortunately I do not know how to correct the lib in such a way, that it will work.

My question is, if there is a Modbus Slave Lib which can handle 16 bit register definitions plus function code.

But when using the mentioned Lib I have to add the function code (4) in front of the 16 bit address. The results is a Modicon address which is bigger than an integer.

Why? The library doesn't need that. It simply follows strictly to the Modbus standard and defines addresses below 20000 as digital I/Os while addresses greater than 20000 are analog registers. You can simply define a register with the address 20481 and it will be a holding register as you intend.

My question is, if there is a Modbus Slave Lib which can handle 16 bit register definitions plus function code.

The one you chose does support that. Please understand that just the Modicon has a rather strange way to handle Modbus, don't try to follow that concept on the Arduino, implement it there as you would do on any other Modbus compatible device.
You won't find a Modbus library that can handle addresses bigger than 16bit as that doesn't exist. A Modbus register address is 16bit even if you PLC puts another label on it, behind the label it will also send 16bit addresses to the bus.

You can simply define a register with the address 20481 and it will be a holding register as you intend.

I can define a register with the address 20481, but unfortunately this Modbus Lib interprets the leading "2" as function code. This register will not be addressed when a master requests 20481 with function code 4- I have tried it. I could access it as register 0481 with a function code 2.

I guess the lib could be adapted by changing the address in Struct modbusAnaReg from word to long. But unfortunately I am yet not really familiar with C.

I can define a register with the address 20481, but unfortunately this Modbus Lib interprets the leading "2" as function code. This register will not be addressed when a master requests 20481 with function code 4- I have tried it. I could access it as register 0481 with a function code 2.

Not exactly but I found out what you mean. The library is actually adding strange constant numbers to the transferred register address based on the function code when it handles a message.

The change is relatively easy:

Remove the lines

	if(funcType == READ_DI)
		startreg += 10001;
	else
		startreg += 1;

from getDigitalStatus() in modbusSlave.cpp and

	if(funcType == READ_AI)
		startreg += 30001;
	else
		startreg += 40001;

from getAnalogStatus() in the same file. Also change

		_device->set(reg + 1, val);

to

		_device->set(reg, val);

and

		_device->set(reg + 40001, val);

to

		_device->set(reg, val);

in setStatus() of the modbusSlave.cpp.

Hi Pylon, did you test these changes with an Arduino and a Modbus Master like ModbusView?
I tested it, but now also communication in the register range below 10000 was not possible anymore.

Hi Pylon, did you test these changes with an Arduino and a Modbus Master like ModbusView?

No. I don't use that library myself because I have requirements quite different from yours.

It might be possible that you have to increase the address in your ModbusView program by 1 to access the register you want as I might have overlooked another part of the code that manipulated the addresses that way (that may be the reason the author used + 40001 and not + 40000).

You also can change the code at the above mentioned locations to just add 1 instead of the bigger numbers to get the same effect.