MODBUS Buffer sizes

G

Thread Starter

Gary Lynch

<pre>
Thanks to Lenore, Curt, & M for the speedy and thorough
replies to my May 12 request for a Modbus overview. Today I
try a technical question.

My company is not a Modbus anything, yet. We have a customer
asking for Modbus functionality and it is my job to
integrate it into an existing product (or prove that
implementing it is so expensive we can't possibly make a
profit).

I have read all 3 Modbus specs and am trying to specify the
maximum size for my Modbus ASCII buffers. I am condensing
what I got from the spec, which confuses me.

An intelligent system can be monitored & controlled by
access to variables I call parameters.

Parameters that can be: | I call:
------------------------+--------------------
Read only | Status parameters
Read and written | Control parameters
Expressed as 1 bit | Binary parameters
Expressed as many bits | Digital parameters

This presents a possible 4 categories of objects, which the
Modbus spec has christened (for reasons known only to it)
as:

| Binary | Digital |
--------+----------------+------------------+
Status | Discrete input | Input register |
--------+----------------+------------------+
Control | Coil | Holding register |
--------+----------------+------------------+

(In a few places, coils are called discrete outputs.)

The protocol permits reading all categories of objects and
writing the control objects. Type of access is determined by
a 1-byte 'function code'. Whereas all read requests can
access multiple objects, write requests distinguish between
'write-single' and 'write-multiple' with separate function
codes. The complete³ breakout of data access function codes
(in hex) is:

| Read | Write |
| Mlt | Sgl | Mlt |
--------+----------------------------+------+-----+-----+
| Binary | Discrete input | 02² | -- | -- |
Status |----------------------------+------+-----+-----+
| Digital | Input register | 04² | -- | -- |
--------+----------------------------+------+-----+-----+
| Binary | Coil | 01² | 05 | 0F¹|
Control |----------------------------+------+-----+-----+
| Digital | Holding register | 03² | 06 | 10¹|
--------+----------------------------+------+-----+-----+
Notes
¹ Variable-length request
² Variable-length response
³ I know I have left out lots of other function codes.
This is a first draft.

Therefore all write-multiple requests, and all responses to
read requests are variable length; while write-single
requests (& responses), read-multiple requests and
write-multiple responses are fixed length.

To size my I/O buffers I need to track down the largest
possible request and response the system will face. The MBAP
gives limits for 4 of the 6 variable length packets:

| ~~ Max objects in ~~
| Response | Request
| to read | for write
| Mlt | Mlt
--------+----------------------------+----------+----------
| Binary | Discrete input | 2000 | --
Status |----------------------------+----------+----------
| Digital | Input register | 125 | --
--------+----------------------------+----------+----------
| Binary | Coil | 2000 | ???
Control |----------------------------+----------+----------
| Digital | Holding register | ??? | 123
--------+----------------------------+----------+----------

But the Conformance Test Specification for Modbus TCP
implies values for all 6:
| ~~ Max objects in ~~
| Response | Request
| to read | for write
| mlt | mlt
--------+----------------------------+----------+----------
| Binary | Discrete input | 2000 | --
Status |----------------------------+----------+----------
| Digital | Input register | 125 | --
--------+----------------------------+----------+----------
| Binary | Coil | 2000 | 1968
Control |----------------------------+----------+----------
| Digital | Holding register | 125 | 123
--------+----------------------------+----------+----------

I don't think my system will have 100 of anything, so I may
be able to reduce this further.

If I divide the bit counts by 8, and multiply the register
counts by 2, I have the maximum number of data bytes in each
ADU category:
| Response | Request
| to read | for write
| mlt | mlt
--------+----------------------------+----------+----------
| Binary | Discrete input | 250 | --
Status |----------------------------+----------+----------
| Digital | Input register | 250 | --
--------+----------------------------+----------+----------
| Binary | Coil | 250 | 246
Control |----------------------------+----------+----------
| Digital | Holding register | 250 | 246
--------+----------------------------+----------+----------

To that I must add (for all ADUs):
- 1 byte of node address,
- 1 byte of function code, &
- 1 byte of LRC

for both write-multiple requests:
- 2 bytes of starting address
- 2 bytes of number of objects
- 1 byte of number of data bytes

and for all 4 read responses:
- 1 byte of number of data bytes

This adds up to:
| Response | Request
| to read | for write
| mlt | mlt
--------+----------------------------+----------+----------
| Binary | Discrete input | 254 | --
Status |----------------------------+----------+----------
| Digital | Input register | 254 | --
--------+----------------------------+----------+----------
| Binary | Coil | 254 | 254
Control |----------------------------+----------+----------
| Digital | Holding register | 254 | 254
--------+----------------------------+----------+----------

So I need 254 bytes in both buffers before ASCII encoding,
and 254 x 2 + 3 (adding ':', '\r', and '\n') = 511 for the
I/O buffers.

If this is correct, would somebody just nod?

If not, could you correct my math?

Thanks.
============================================================
Gary Lynch To send mail change my lynchg@no$pam.com
domain name to stacoenergy
============================================================
</pre>
 
It appears your company services the electrical power users/market. I'm not sure what all kinds of data values your device is providing, but if any of the values are totals/totalizers (KWH), you might want to consider floating point (FP) format for values can grow to be big numbers over time.

And, if you consider FP values, you should be aware that floating point format uses twice the number of registers as integer format does (since you are carefully counting your memory bytes).

I know that one product that I work with maps all of its values in both integer and FP in different parts of memory. That's nice because one doesn't have to fuss with conversion on the master, it's just a matter reading the format that's easiest to work with. Then there's another Process Automation Controller whose slave map contains only floating point (FP) values. No integer values. Even for digital zero or one status! A whole FP value for a zero or a one. There are some HMI panels that just can't handle FP-only.

The spectrum of Modbus masters is as varied as slaves. One I know has so little in the way of math functions that I am unable to decode a bitpacked integer word with it. So making your data available in formats your customers can actually use, might be a consideration.

In the past couple months I recall reading a statement on this forum to effect of, "I'm not sure if anyone actually uses the 04 instruction to read data at 3xxxxx registers. I've thought the same thing. I can't recall that I've ever used the 04 command to read 3xxxx input registers. But I can say it freaks me out when a common, well documented function that I do use is eliminated in model upgrades. So I'm sure that there are those who appreciate statements in slave documentation like, "all data in 3xxxx registers is mirrored in 4xxxx" because they do, in fact, ready the 3xxxx registers.
 
With regards to the size of the message, the "MODBUS Application Protocol Specification V1.1b" states on page 5:

"The size of the MODBUS PDU is limited by the size constraint inherited from the first MODBUS implementation on Serial Line network (max. RS485 ADU = 256 bytes). Therefore: MODBUS PDU for serial line communication = 256 - Server address (1 byte) - CRC (2 bytes) = 253 bytes.

Consequently: RS232 / RS485 ADU = 253 bytes + Server address (1 byte) + CRC (2 bytes) = 256 bytes. TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes."

The "MODBUS over serial line specification and implementation guide V1.02" states on page 17:

"Remark : Each data byte needs two characters for encoding. Thus, to ensure compatibility at MODBUS application level between ASCII mode and RTU mode, the maximum data size for ASCII data field (2x252) is the double the maximum data size for RTU data field (252). Consequently, the maximum size of a MODBUS ASCII frame is 513 characters."

There is more detail on the message sizes on the pages that I have referenced.
 
I am not sure what is your definition of MODBUS Data Buffering. MODBUS does not support Data Buffering. When the Master issue a read request(Query), it include number on registers to read from. The slave reply (response) with the current value available at the specified Memory Register. in other words, all process values changed between two consecutive polls are lost. It may be possible to use custom code to store values in specific registers but this will lead to customized implementation unique to your application and thus the tram Modified MODBUS.
 
G
On 20 May, 2010 - 8:52 pm; Dan wrote:

> It appears your company services the electrical power users/market. <

I think I deleted that from my original post because it was getting too wordy. My employer makes uninterruptible power supplies and the product is a 3-phase unit that I helped design (shipping for 3 years) which already has a serial port with SNMP support built in. Thus the 'hooks' for Modbus support are already in place.

> I'm not sure what all kinds of data values your device is providing, but if any of the values are totals/totalizers (KWH), you might want to consider floating point (FP) format for values can grow to be big numbers over time. <

We don't store anything that accumulates like that (except a real-time clock that rolls over every 60 years) but if I did I would probably stipulate in the manual where it rolls over before I thought about floating point.

> And, if you consider FP values, you should be aware that floating point format uses twice the number of registers as integer format does (since you are carefully counting your memory bytes). <

I couldn't remember reading anything about floating point in the Modbus spec at all, so I pulled up the MBAP under Acrobat and searched for 'float', 'point', 'FP', and 'real', all to no avail. Where did you hear about this?

> So making your data available in formats your customers can actually use, might be a consideration. <

So is sticking with integers a safe format? I was going to report most of the voltages & current in decivolts and deciamps; both for precision purposes and because that's the way they are stored internally anyway.

> In the past couple months I recall reading a statement on this forum to effect of, "I'm not sure if anyone actually uses the 04 instruction to read data at 3xxxxx registers. <

Now that you mention it, I've seen specs in other vendors' data sheets that talk about 3xxxxx registers and 4xxxxx registers, but I can't find any mention of it in the Modbus spec. What does it mean?

============================================================
Gary Lynch To send mail change my lynchg@no$pam.com
domain name to stacoenergy
============================================================
 
G
On 21 May, 2010 - 7:37 am; AHK wrote:

> I am not sure what is your definition of MODBUS Data Buffering. MODBUS does not support Data Buffering. <

This was a linguistic glitch.

My embedded device uses an interrupt service routine (ISR)
to handle all data going in and out of the serial port/UART.
The main() function handles interpreting requests and
creating responses. I have separate arrays for serial data
in and serial data out that (with a couple of control bits)
form the interface between these two functions. These two
arrays are what I called 'data buffers.'

I didn't know 'data buffering' had another meaning on this
forum.
============================================================
Gary Lynch To send mail change my lynchg@no$pam.com
domain name to stacoenergy
============================================================
 
G
On 21 May, 2010 - 1:53 am; M Griffin wrote:

> With regards to the size of the message, the "MODBUS Application Protocol Specification V1.1b" states on page 5:

"The size of the MODBUS PDU is limited by the size ... <

You are right. If I had noticed that I could have avoided a
lot of work. But it is encouraging that my answers agree
(within a byte at least).
============================================================
Gary Lynch To send mail change my lynchg@no$pam.com
domain name to stacoenergy
============================================================
 
Modbus doesn't define any meaning to the contents of the registers. They're just 16 bit words. That means you can pack a single precision floating point number (4 bytes) into 2 consecutive registers. It is up to the application program to decide what that data means however. It's the same convention that most PLCs use (a PLC data table is usually just an array of memory).

I don't know what your customers will be hooking up to your systems, but not every PLC can handle floating point numbers, and when they do, they don't always use the same format. If you can do everything with 16 bit integers both you and your customers will be much happier. Just be sure to define whether the registers represent signed or unsigned integers.

If you need bigger numbers, then try to use 32 bit integers or else split the number between registers along engineering unit lines. For example, year in one register, day of year in another, etc.

3xxxxx and 4xxxxx are common numbering conventions, but they are not part of the actual Modbus specification. They are actually a PLC addressing scheme used by one of the larger PLC vendors and Modbus registers correspond to those parts of the PLC's data table. All it means is that if you buy brand 'X' PLC, then device vendor 'Y' is just telling you how to use their device with the standard data table mapping for that brand of PLC. The leading digit is a "type" indicator, not part of the actual address. Some other PLC vendors use letters for the same purpose (e.g. X, Y, C, I, Q, M, V, etc.).

The prefix convention is as follows:

0xxxx - Coils.
1xxxx - Discrete inputs.
3xxxx - Input registers.
4xxxx - Holding registers.

When you are documenting your device interface you can use the 3xxxx/4xxxx convention if you wish, but be sure to include the standard Input/Holding register terms as well. The 3xxxx/4xxxx convention seems to cause no end of confusion with people who are always wondering what it means. People are never sure whether register 4123 means address 4123, or whether it means holding register 123.

To add to the confusion, different models of PLC had different sizes of memory, so with some PLCs the PLC address was 4123, while with another the exact same address would be 40123. If you just say "holding register" and give the actual address, then it is a lot clearer.

Another point to document is whether you number your registers starting from 0 or 1. The Modbus *protocol* always calls the first register "0". However, some PLC vendors call their first data table address "1". The end result is that some people document their register maps starting from 0 (to correspond to what Modbus calls it), or they document the registers starting from 1 (to correspond to the PLC their users are hooking the device up to). When the message goes through the wire it is alway numbered from 0. The offset of 1 only comes about from what people see on their computer screens when they run their PLC configuration or programming software.

If your documentation lists the registers starting from 0, just be sure to say "the first register is 0" (or 1, if that is how you choose to describe it). I prefer to use 0, as that corresponds to the actual protocol.

The thing to note with the above is that these are device documentation issues, not protocol issues. The actual protocol is exactly the same in each case. The differences are just in how the vendor wrote his manuals. Just make sure you specify clearly what you mean in each case and you shouldn't have any problems.
 
Hi,

My understanding of Data Buffering offered by a communication protocol is the ability to buffer and store process variable for a period of time during communication interruption with the Master Station.

My apology for any "linguistic glitch"
 
Top