MODBUS memory-map requirements


Thread Starter


Hello all:

As a beginner in Modbus development, I am putting together a memory-map and would like people's input on it. My understanding is that there is no rule in the spec that mentions "the min. number of function-codes to be supported" as it is device specific. With that assumption in mind, I have developed my memory-map with the following:

a)Our device supports Modbus RTU through RS-485 with a fixed baud-rate of 9600. Any known issues due to hard-coded baud rate?

b)Currently the device supports ONLY 3 function codes, Read-holding registers, write-single register, and write-multiple registers (FC: 3,6,and 16).

c) Memory-map provides a location of reading and writing slave-id.

d) Memory-map talks of various errors supported: Illegal-data-address, Illegal-data-value, Illegal-function.

e) Memory-map discusses access to various memory locations (read-write, read-only) with descriptions of the format of the data (floating point, integer etc).

Is "Diagnostic function" or "report slave-id" usually expected to be supported?

Anything else that is missing as a "minimum"?

Feedback is appreciated.

Lynn August Linse

Fixed baud of 9600 should be fine - if it were 1200 or 115kbps, you'd have trouble. A fixed parity can be a problem - most tools support None parity & despite the standard, some master devices can't support (or rather give no option) for even or odd parity.

The minimum I'd suggest is to read (func 0x03) the first holding register (so offset 0 or notated as 4x00001).

I suggest this because some tools 'ping' a Modbus device by reading the first holding register - use it as an online test.

Beyond that, what you suggest is fine. I'd make sure ALL of your data exists in the holding-register space ... there is nothing more annoying that a device with 7 bits in 'coil space', 13 bits in 'input bits' space, 3 words in 'input register space', and 17 words in hold-register so one needs to issue 4 (four) tiny commands to read all the data, when 1 read of 22 words to holding register space could return all the data!

I'm not saying to NOT use the func 0x01/0x02, just to mirror data into the 0x03 space to make bulk polling more efficient.
Do you have some means of configuring the slave address? DIP switch?

One thing that's missing - what is number format for each register?
signed integer? unsigned integer? 32 bit floating point? 32 bit long integers? bit packed?

What are the engineering units for the register values?

Is there any scaling applied?

Like when a value has two digits to the right of the decimal point, but since there's no decimal point the value in the register has to be divided by 100. For instance, the actual value 877.43 would be an integer value 87743 which needs to be divided by 100.

I like the memory maps that list one column of registers in decimal, the adjacent column with indexed addresses in hex, and a column for a description

like this:<pre>
ref (dec) index(hex) description type/format
40001 0000 setpoint signed integer/100, range 20,000 to -20,000 in eng units
40002 0001 total 1 floating point in Tot1 eng units</pre>
Hello Lynn/David:

Thanks for your feedback!

I do have most of the data as contiguous; so the Master can do a bulk-poll and get all the information they need.

A)Configuring slave-id: I keep reading about this DIP-Switch. I haven't used any and don't know much about it. What is this DIP-Switch thingie...

Currently we use our own GUI which sends a Write-single-register command to a location. For example: to configure slave-id 0x10 to a device, we send a write-single-register command at location "x" with a value of 0x10. This location "x" will be described in the memory-map as a read/write variable which stores the slave-id. Would that suffice?

b) Format of the data: All data is "signed integer format" and will have appropriate units (Fahrenheit, for example). Where appropriate the format will be scaled and will be mentioned in the remarks column (signed-integer/100), just like you have mentioned in the example.