0

I am doing some testing with Modbus TCP and I am struggling to understand the theoretical speed limit calculated here regarding maximum number of registers scanned per second.

My test is using a beaglebone to host a modbus server (slave) which I poll from my laptop. Both devices are on a private subnet and they are the only two devices on that subnet. The server and client are implemented in python with pymodbus. As a test I used block reads to poll 6000 holding registers (125 registers in each of 48 block reads), and it took 0.17163 seconds. This translates to a scan rate of about 35,000 registers/second. This a fast, but it is no where near the theoretical limit for the Base100T interface as calculated in the page linked above.

According to that page, the theoretical limit for Base100T connection should be somewhere around 3,600,000 registers/second. I realize that there will be some losses due to the throughput of the python program etc, however it's so much lower than the theoretical that I am having a hard time understanding where those major losses are. Where could the throughput be limited?

Below is a listing of the code I used for this test:

Server (Beaglebone)

from pymodbus.server.sync import StartTcpServer
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext

def run_server():
    holding_registers = ModbusSequentialDataBlock(0,[i for i in range(15000)])
    store = ModbusSlaveContext(hr = holding_registers)
    context = ModbusServerContext(slaves=store, single=True)

    StartTcpServer(context, address=("localhost", 5020))

if __name__ == "__main__":
    run_server()

Client (Laptop)

import time
import math
from pymodbus.client.sync import ModbusTcpClient as ModbusClient

modbus = ModbusClient('192.168.0.10', port=5020)
modbus.connect()

def timeit(f):

    def timed(*args, **kw):

        ts = time.time()
        result = f(*args, **kw)
        te = time.time()

        print('func: {} took: {} sec'.format(f.__name__, te-ts))

        return result

    return timed

@timeit
def block_read_arbitrary(bus, n):
    last_read = n % 125
    if last_read > 0:
        nreads = int(math.ceil(n/125))
    else:
        nreads = int(n/125)

    print("Reading {} Blocks...".format(nreads))

    data = []
    for i in range(nreads):
        if i == nreads - 1 and last_read > 0:
            rr = bus.read_holding_registers(i*125, last_read)
            data.extend(rr.registers)
        else:
            rr = bus.read_holding_registers(i*125,125)
            data.extend(rr.registers)

    return data

block_read_arbitrary(bus, 6000)
Alex
  • 1,172
  • 11
  • 31

1 Answers1

0

I think, there is and error here: http://www.modbus.org/faq.php

When it is said this:

"What sort of performance can I expect from a Modbus TCP/IP system?

The performance depends on the network and the hardware. If you are running Modbus TCP/IP over the Internet, you won't get better than typical Internet response times. However, when communicating for debug and maintenance purposes, this may be perfectly adequate and save you from having to catch a plane or go to site on a Sunday morning!

For a high-performance intranet with high-speed Ethernet switches guaranteeing performance, the situation is completely different. In theory Modbus TCP/IP carries data at up to 250/(250+70+70) or about 60 percent efficiency when transferring registers in bulk. Since 10BaseT Ethernet carries about 1.25 Mbps raw, the theoretical throughput is 1.25M/2 * 60% = 360000 registers per second and the 100BaseT speed is 10 times greater.

If we calculate 1.25/2= 625000. 625000*0,06 (60%) = 37500, and not 360.000. Is it?