This is a command line tool for experimenting with modbus. Please note that this is a work in progress.
If you have Go installed on your system you can fetch the latest version of this utility using:
go install github.com/lab5e/mtool/cmd/mtool@latest
The mtool
utility has several subcommands. You can list these, and the global command line options, by runnig mtool -h
.
$ mtool -h
Usage:
mtool [OPTIONS] <command>
Application Options:
--device= serial device [$MTOOL_DEVICE]
--baud= baud rate (default: 9600) [$MTOOL_BAUD]
--databits= data bits (default: 8) [$MTOOL_DATABITS]
--parity=[N|E|O] parity (default: N) [$MTOOL_PARITY]
--stop=[1|2] stop bits (default: 1) [$MTOOL_STOPBITS]
--id= device id (default: 1) [$MTOOL_DEVICE_ID]
--timeout= timeout (default: 5s)
--debug enable debug output
Help Options:
-h, --help Show this help message
Available commands:
doc print documentation
rc read coils
rd read discrete input
rh read holding register
ri read input register
scan scan modbus for devices
wh write holding register
Note that some of the command line options have default values (which the help -h
option will list). The idea is to cut down on the number of command line options you have to specify by hopefully providing sensible defaults. For instance the modbus device ID defaults to 1 since a lot of devices have this ID right out of the box.
For the global (application) options we have provided environment variables which can make using mtool
a bit more convenient. For instance it may be preferable to at least set the MTOOL_DEVICE
to the serial device you are speaking to so you don't have to clutter the command line by having to include this every time. The -h
help output will list the other command line parameters that have environment variables you can set.
The device ID (-id
) is the (hopefully) unique device ID on the modbus loop. Before hooking up your devices, please make sure that each device is given a unique ID and that you have noted these somewhere.
Note that modbus addresses (specified by the --addr
flag) are one-based while the protocol itself is zero-based. This means that the documentation will give an address as 10, while what is expected by the device is 9. mtool
subtracts 1 from the address you give it before putting it on the wire.
Sometimes you may want the values returned expressed in some other base than base 10. To do this you can specify the --base
option with 2
(binary), 8
(octal), 10
(decimal) or 16
(hexadecimal) as the base.
All of the reading commands support the --repeat
flag. When this flag is not specified the read command will be executed only once. If it is set to a value it will repeat the read operation every time unit specified.
Time is expressed as a number followed by a unit. Valid units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
This example reads holding register with address 1 every 500 milliseconds:
$ bin/mtool rh --addr 1 --repeat 500ms
2023-02-01T13:17:06Z [holding_register] deviceID=1 addr=1 count=1 data={230}
2023-02-01T13:17:07Z [holding_register] deviceID=1 addr=1 count=1 data={230}
2023-02-01T13:17:08Z [holding_register] deviceID=1 addr=1 count=1 data={230}
2023-02-01T13:17:08Z [holding_register] deviceID=1 addr=1 count=1 data={230}
If you want to see the messages that are sent and received on the bus, you can add the --debug
flag. This will print out messages prefixed with modbus:
showing the bytes that are being transmitted and received. The debug output is not affected by the --base
option.
The mtool command itself does nothing. To make it do things you have to specify subcommands. The following sections specify the subcommands. In order to list the options available to each subcommand you should use the built-in help for each subcommand. You can do this by issuing a command of the form
mtool <subcommand> -h
Scan the bus for devices by trying to read data from it. Per default it will try to read holding register 1. You can change what to read by setting the --type
command line option to one of holding
, discrete
, input
or coil
. You can change the address used for scanning by setting the --addr
command line option.
Depending on the devices you may have to configure how long the scanning process should wait for response from each device. This can be done with the --scan-timeout
option. The default timeout is 100ms. If you don't find any devices during a scan, try to increase the timeout value.
Read the holding register identified by --addr
.
This example reads holding register 1
$ mtool rh --addr 1
2023-02-01T13:05:28Z [holding_register] deviceID=1 addr=1 count=1 data={230}
Write holding register identified by --addr
.
This example writes the int16
value 230
to holding register 1
$ mtool wh --addr 1 --value 230
deviceID=1 addr=1 res={230}
You can check that the value has indeed been changed by reading the holding register back using the rh
subcommand.
Read input register identified by --addr
.
This example reads input register 4:
$ mtool ri --addr 4
2023-02-01T13:03:50Z [input_register] deviceID=1 addr=4 count=1 data={2574}
Read discrete input identified by --addr
. Note that this is a bit field.
This example reads discrete input 4. Note that the output is in binary per default. You can change the base with the --base
command line option.
$ mtool rd --addr 1
2023-02-01T13:06:48Z [discrete_input] deviceID=1 addr=1 count=1 data={11111011, 0000000000011101}
Read coils identified by -addr
. Note that this is a bit field. You can change the output base with the --base
command line flag.
For convenience sake this README.md file is included in the binary. You can spit it out as original markup or as HTML.