Search code examples
modbusttynetcatrs485

Send Modbus RTU request to temperature controller over TCP/IP using Netcat


I'm trying to send a Modbus RTU message over over a wireless network to a temperature controller (PID), via a device that accepts an incoming TCP/IP packet and then forwards its data over an RS455 connection (lets call this device a "converter"):

PC --(WiFi)--> router --(RJ45)--> converter --(RS485)--> PID

The converter was marketed as a Modbus TCP to RTU converter, which it is not. This caused some confusion and setback. However, I have decided to keep using the device and rewrite my HMI code to send Modbus RTU messages to it, instead of Modbus TCP ones.

Before I go about rewriting the code, I want to make sure I know what I am doing, and that I can successfully send a request to the temperature controller and receive a response. I decided (perhaps naively) that sending this message via the command line using netcat would be the best way to do this.

The Modbus RTU message I am sending contains the following request:

  • device address: 1
  • function code: 3
  • memory address: 1000
  • number of registers: 1
  • CRC: 51840

The socket on the converter is to be made for:

  • IP address: 192.168.0.5
  • port: 2000

The netcat command I am sending is thus:

echo -e -n '\x01\x03\x10\x00\x00\x01\x80\xCA' | nc 192.168.0.5 2000 -p 42998

In another terminal I am listening for:

nc -l 42998

I am also capturing the traffic with Wireshark so I can see what's going across the network.

What is going across the network is:

  • a good, firm handshake
  • the Modbus request from my machine
  • a window resize notification from the converter
  • an ack for the window resize from my machine
  • an ack for the Modbus request from the converter
  • as many keep-alives as I could ever want

I'm getting nothing showing up on my netcat listen, obviously.

So I'm trying to figure out what's happening to the response from the temperature controller. Assuming that the error lies with me and not the hardware (and at the risk of making an ass out of u and me), here's what I think might be going wrong - or at least here's the question that I have, because I am completely out of my depth at this point:

  • Modbus RTU messages are made up of 11-bit bytes - a start bit, eight data bits, a stop bit and a parity bit
  • what if I am only sending 8-bit bytes out with netcat, so that the temperature controller is receiving the message but then simply dropping it as garbage?
  • or what if netcat is sending out 11 bytes, but the parity is different, or even the stop and start bits are different?

I looked into this idea a little, and tried:

stty cs8 parenb -parodd

and then sent out the netcat command again, but it didn't make any difference and I really feel like I'm just flopping about like a fish on a river bank now, and I'm struggling to find information on tty, terminal emulators and the like that make it all click for me.

Brits' answer to this SO question states that the drivers of this kind of device present themselves as serial ports, and my device does indeed have such a driver - do such drivers add start, stop and parity bit information, or do they require it to be present at their input?

Any ideas what might be going on, based on your greater experience in this kind of matter? And any suggestions how I might fix it?


Solution

  • In the end, everything worked fine just with:

    sudo echo -e -n '\x01\x03\x10\x00\x00\x01\x80\xCA' | nc 192.168.0.5 2000
    

    The problem turned out to be that the data I/Os on the TCP device are using RS485 A for high and B for low, which is opposite to the standard but apparently not uncommon.

    Annoying, but there you go. Watch out for that, I guess.