Modpoll Modbus Master Simulator
modpoll is a command line based Modbus master simulator and test utility. modpoll is using the FieldTalk ™ Modbus driver.
Installation
Windows
Download archive into a folder and extract the zip archive. The modpoll.exe command must be run from a Command Prompt:
Linux
The tarball contains multiple binaries for different CPU architectures. Add the version matching your system architecture to the path. Example for ARM platforms like Raspberry Pi:
export PATH=$PWD/modpoll/linux_arm-eabihf:$PATH
Usage
Usage: modpoll [OPTIONS] SERIALPORT|HOST [WRITEVALUES. ] Arguments: SERIALPORT Serial port when using Modbus ASCII or Modbus RTU protocol COM1, COM2 . on Windows /dev/ttyS0, /dev/ttyS1 . on Linux HOST Host name or dotted IP address when using MODBUS/TCP protocol General options: -m ascii Modbus ASCII protocol -m rtu Modbus RTU protocol (default if SERIALPORT contains /, \\ or COM) -m tcp MODBUS/TCP protocol (default otherwise) -m udp MODBUS UDP -m enc Encapsulated Modbus RTU over TCP -a # Slave address (1-255 for serial, 0-255 for TCP, 1 is default)\n -r # Start reference (1-65536, 1 is default) -c # Number of values to read (1-125, 1 is default), optional for writ ing (use -c 1 to force FC5 or FC6) -t 0 Discrete output (coil) data type -t 1 Discrete input data type -t 3 16-bit input register data type -t 3:hex 16-bit input register data type with hex display -t 3:int 32-bit integer data type in input register table -t 3:mod 32-bit module 10000 data type in input register table -t 3:float 32-bit float data type in input register table -t 4 16-bit output (holding) register data type (default) -t 4:hex 16-bit output (holding) register data type with hex display -t 4:int 32-bit integer data type in output (holding) register table -t 4:mod 32-bit module 10000 type in output (holding) register table -t 4:float 32-bit float data type in output (holding) register table -i Slave operates on big-endian 32-bit integers -f Slave operates on big-endian 32-bit floats -e Use Daniel/Enron single register 32-bit mode -0 First reference is 0 (PDU addressing) instead 1 -1 Poll only once only, otherwise every poll rate interval -l Poll rate in ms, (1000 is default) -o # Time-out in seconds (0.01 - 10.0, 1.0 s is default) Options for MODBUS/TCP, UDP and RTU over TCP: -p # IP protocol port number (502 is default) Options for Modbus ASCII and Modbus RTU: -b # Baudrate (e.g. 9600, 19200, . ) (19200 is default) -d # Databits (7 or 8 for ASCII protocol, 8 for RTU) -s # Stopbits (1 or 2, 1 is default) -p none No parity -p even Even parity (default) -p odd Odd parity -4 # RS-485 mode, RTS on while transmitting and another # ms after
Usage Examples
To retrieve continuously 10 Modbus holding registers starting from reference 500 of slave ID number 5 with Modbus RTU at 9600 baud, no parity on COM1 run:
modpoll -b 9600 -p none -m rtu -a 3 -r 500 -c 10 COM1
To retrieve once 5 floating point values starting from reference 100 with Modbus/TCP from slave device with IP 10.0.0.100:
modpoll -t4:float -r 100 -c 5 -1 10.0.0.100
modpoll -r 1201 10.0.0.100 1234
modpoll -r 1201 -c 1 10.0.0.100 1234
Modbus Simulation on Linux
Modbus RTU support in Typica has always been relatively weak, but there’s enough other hardware support that I haven’t considered improving that to be a high priority. Recently someone contacted me about paying to raise the priority on a specific improvement that would allow them to use Typica with hardware they already had on their roaster and since this is a project that can always use financial support I decided to spend an evening making that change and using it as an opportunity to do some related work that I’ve wanted in Typica for a while. I’ll have another post about those changes and how to use the new build later.
When working on code that communicates with hardware, I like to have hardware set up to test that code against. For Modbus RTU hardware, a basic test rig consists of a power transformer, a panel display, a thermocouple simulator, and an RS485 to USB serial adapter along with all the wires needed to hook those things together. That works, but it’s not very portable and it’s easy to disturb. There were also a couple of different ways device manufacturers implement one of the features I would be adding so a hardware only test rig would require at least two different panel displays. Rather than expand the hardware test rig I decided to try something else: running a simulation of the bus and using that for the initial testing. I would still want to go back and make sure it works with physical hardware, but simulated hardware would make the initial work easier to do. Since I prefer to write software on my laptop computer that runs Linux, that is where I set this up. The hardware testing that came later was under Windows.
ModbusPal
ModbusPal is a free Java application that can simulate a bus with devices communicating using Modbus, though it doesn’t quite work for that out of the box. Serial port communications require additional software (RXTX, you want version 2.2pre2 if you’re on amd64; earlier versions crash as soon as you try to read from the port) and it can take a bit of searching around to find where the various files should go, especially if you don’t write software in Java on Linux often enough to be familiar with that.
tty0tty
tty0tty is a null modem emulator. It adds files like /dev/tnt0 and /dev/tnt1 and programs can connect to those like they would any other serial port, but if you have one program talking to /dev/tnt0 and another program talking to /dev/tnt1 those two programs can communicate with each other as if there were a null modem cable run between two real serial ports. This is handy because my laptop doesn’t have old style serial ports, much less two of them. I could have gone with two USB serial adapters and a null modem cable instead, but that’s not much better than just using real hardware. It probably would have taken me longer just to find a null modem cable than it would have to set this up. I haven’t needed to use one of those in decades.
Recognizing the ports
Unfortunately, a lot of programs that use serial ports don’t know that they can use the files created by tty0tty. Typica uses qextserialport for serial port communications which doesn’t enumerate those /dev/tnt* files, but getting that to work was a tiny change to one line of code and rebuilding that library. No changes were needed in Typica.
For ModbusPal I needed to launch that on the command line as:
java -Dgnu.io.rxtx.SerialPorts=/dev/tnt0 -jar ModbusPal.jar
to get that port to show up.
Getting things talking
With ModbusPal configured to use /dev/tnt0 and Typica configured to use /dev/tnt1 it’s now possible for Typica to use that simulated bus. The old code won’t work very well with that as it seems that ModbusPal doesn’t support Modbus function 4 (read input registers). It does, however, support function 3 (read holding registers) which has identical query and response structures. The only difference is that the 2nd byte contains a 3 instead of a 4.
Next, we can make things a little more interesting. The Automation section in ModbusPal allows you to set up generators that produce changing values. It’s then possible to bind those generators to addresses on a simulated device. Configuring Typica to read from those registers allows you to see the values changing.
Earlier I wrote that a test involving physical hardware would require multiple devices. This is because different devices do not agree on how to represent numbers. The Modbus RTU protocol only knows about 1 bit values (coils) and 16 bit values (registers). With temperature measurements, it’s often desirable to present those values with a fractional part. Some devices do this with a 16 bit value by presenting that as an integer and leaving it to software to divide that by a fixed power of 10 to shift the decimal point to the correct position. Another option is to use a floating point number. It’s possible to fit a half precision floating point number in 16 bits, but half precision floating point numbers weren’t standardized until a couple decades after Modbus was introduced and it’s really not a good choice for this sort of thing. I hope nobody is making devices that use that. Many devices do, however, use single precision floating point numbers (aka binary32). As you might have guessed, these require 32 bits. Modbus doesn’t have a concept of 32 bit values, but you could take two 16 bit values and just split the number in half. Since the protocol doesn’t have a concept of 32 bit values or floating point numbers, it doesn’t specify how that data should be ordered so manufacturers do what they want. That means Typica should support both options.
ModbusPal makes it easy to test that. You can take a generator and bind it to four registers. Use one order for two of them, use the other order for the other two. You can also set up registers to use an integer representation to make sure the fixed point stuff still works.
Neal Wilson is the author of Typica and roasts coffee at Wilson’s Coffee & Tea.
Diagslave Modbus Slave Simulator
diagslave is a simple command line based Modbus slave simulator and test utility. diagslave is using the FieldTalk ™ Modbus driver.
Installation
Windows
Download into a folder and extract the zip archive. The diagslave.exe command must be run from a Command Prompt:
Linux
The tarball contains multiple binaries for different CPU architectures. Run the version matching your system from the command line. Example for Raspberry Pi:
cd diagslave linux_arm-eabihf/diagslave -h
Usage
Usage: diagslave [OPTIONS] [SERIALPORT] Arguments: SERIALPORT Serial port when using Modbus ASCII or Modbus RTU protocol COM1, COM2 . on Windows /dev/ttyS0, /dev/ttyS1 . on Linux General options: -m ascii Modbus ASCII protocol -m rtu Modbus RTU protocol (default if SERIALPORT set) -m tcp MODBUS/TCP protocol (default otherwise) -m udp MODBUS UDP -m enc Encapsulated Modbus RTU over TCP -o # Master activity time-out in seconds (1.0 - 100, 3 s is default) -a # Slave address (1-255 for RTU/ASCII, 0-255 for TCP) Options for MODBUS/TCP, UDP and RTU over TCP: -p # TCP port number (502 is default) -c # Connection time-out in seconds (1.0 - 3600, 60 s is default) Options for Modbus ASCII and Modbus RTU: -b # Baudrate (e.g. 9600, 19200, . ) (19200 is default) -d # Databits (7 or 8 for ASCII protocol, 8 for RTU) -s # Stopbits (1 or 2, 1 is default) -p none No parity -p even Even parity (default) -p odd Odd parity -4 # RS-485 mode, RTS on while transmitting and another # ms after Options for Modbus RTU: -f # Tolerance for inter-frame gap detection in ms (0-20)
Usage Examples
diagslave -b 9600 -p none -m rtu COM1