Modbus UDP communication

G

Thread Starter

gayatri

We have used the following packet format for Modbus(master) TCP/RTU implementation:

MBAP header:
TransId(2bytes),
protocol Id(2bytes)(0 for modbus),
MessageLength(2 bytes),
UnitId(1 bytes)

MB PDU :
FunctionCode(1byte),
Address(2 bytes),
Qty(qty of data to be read)

The python implementation for modbus-tcp read coil request is:

import time
import socket
import struct
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(("localhost",502))

#--ReadCoil - request
data = struct.pack('>HHHBBHH',
01, 00, 06, 00,
01, 01, 01)
#data sent will be :
'\x00\x01\x00\x00\x00\x06\x00\x01\x00\x01\x00\x01'

client_socket.send(data)
time.sleep(2)
print client_socket.recv(2056)

Here the connection is made to a software PLC which is configured as TCP server. We could get some response for this.

We tried the same for UDP just by making the connection to a Modbus UDP Slave at ('localhost',5001) as

client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_socket.connect(("localhost",5001))

It sets the error count in the PLC (which indicated that the data has been sent and there is some error) and hangs while recieving the response, at sock.recv(2056) statement. We couldn't guess the cause for the error.

Can anyone help me in making out the differences between Modbus UDP and TCP implementation?

Is the difference only in transportation of packets (taking as STREAM or DGRAM option) or is it in the packet format also? Any checksum related differences? How should we format it to get a proper response?

Any help in this regard will be greatly appreciated.

Thanks in Advance,
Gayatri
 
I don't know if there are some special requirements about the message format, but you appear to be doing UDP wrong.

You are doing:

client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
client_socket.connect(("localhost",5001))

You haven't said so explicitly, but I assume you are still trying to do this:

client_socket.send(data)

It should be more like this:

client_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
client_socket.sendto(data, ("localhost",5001))
time.sleep(2)
print(client_socket.recv(2056))

Note that you don't need to "connect", and you need to use "sendto" rather than "send".

If you want to change the time-out value from the default, then you need to

client_socket.settimeout(timeout)

right after you create "client_socket" (i.e. the next line after the call to "socket.socket").
 
Gayatri,

1. What make/model PLC are you working with?... and are you sure that the PLC you are using supports Modbus/UDP? Modbus/UDP is not an official standard, as far as I know, so I wouldn't assume that every PLC will support it.

2. Wireshark is a good program for monitoring master and slave network traffic. It is capable of recognizing and parsing Modbus requests, so I've found it to be an effective tool when I need to see the detailed network activity.

3. If you are certain that the PLC supports Modbus/TCP but uncertain that it supports Modbus/UDP, and you want to test your Modbus/UDP implementation, you could also trying this configuration...

Modbus UDP Master (PC) <-> DOIAP <-> Modbus TCP Slave (PLC)

... where a DOIAP (Digi One IAP) is set up as a protocol translator to convert Modbus/TCP to Modbus/UDP.

Hope this helps!
 
Thanks for the reply Griffin.

We tried socket.sendto (host, port) also without using connect but we couldn't get the response.

Problem here is the packet format which the target device (udp slave) is expecting. When we changed it, we could successfully send the request and get the response.

Regards,
Gayatri
 
scadametrics,

Thanks for the reply.
The device we are using supports Modbus UDP. We could communicate to the device by correcting the packet format(as expected by it).

Regargs,
Gayatri
 
What was the difference in the data format and what hardware (or software) are you talking to? There is no actual standard called "Modbus/UDP", so there is no "right" or "wrong" way to do things.

I haven't used Modbus/UDP, but I believe that the usual implementation just sends a Modbus/TCP message as UDP instead of TCP. However, some companies just tunnel Modbus/RTU in a UDP message, just like some companies tunnel RTU in a TCP message (normally for Ethernet to serial converters).
 
L

Lynn August Linse

There is no such thing as "Modbus UDP".

As M Griffin states, most clever people assume this is Modbus/TCP form in UDP. However, there are several companies which call Modbus/RTU encapsulated as UDP/IP "Modbus UDP". In fact, I know one of them tried to have this accepted by Modbus-ida.org as a standard - it was NOT accepted.

Since you say this is "Modbus(master) TCP/RTU", then I assume you need to put Modbus/RTU form into your packets, so only:
* UnitId / Slave Address(1 bytes)
* FunctionCode(1byte),
* Address(2 bytes),
* Qty(qty of data to be read)
* 2-byte CRC

The easiest solution to ALL such situations is to use WireShark and collect a trace of the "vendor product" talking to a "vendor tool". This is safer than trying to infer anything from what people call "Modbus UDP" or "Modbus Ethernet".
 
Top