[MAT logo][Prev][Up][Next]

Modbus I/O

Modbus master

The modbus master is actually three modules, one each for Modbus/RTU, Modbus/ASCII and Modbus/TCP. When you're running the demo, don't forget to select the correct module in the [PLC] section of the config.

[PLC]
# Uncomment the modbus protocol version you wish to run...
module modbus_m "../../io/modbus/modbus_m_rtu"
#module modbus_m "../../io/modbus/modbus_m_asc"
#module modbus_m "../../io/modbus/modbus_m_tcp"

Configuration

The configuration consists of three tables:
network
connection information (serial port or TCP address)
node
the devices connected to each network (modbus ID)
map
the usual mapping of actual I/O to MatPLC points (registers)

Network configuration table

This specifies the connection information - serial port or TCP address, and any associated settings. There can be any number of these - one module may talk to several serial ports or several TCP slaves; on the other hand, having a separate module for each port or each TCP address will allow the slaves to be contacted simultaneously rather than one by one.

The format of the table is:
network <network_name> <protocol> <parameters>

<network_name>
The name used to refer to this network in the rest of this config.
<protocol>
{rtu | ascii | tcp}
This must agree with the module being used.
<parameters>
These depend on the type of network:
For rtu and ascii networks
[device <filename>]
[baudrate <x>]
[parity {even|odd|none}]
[data_bits <x>]
[stop_bits <x>]
[ignore_echo {true|false}]
[timeout <x>]
[send_retries <x>]
For tcp networks
[host <x>]
the IP address or DNS name of the slave
[port <x>]
x is either the port number on which the slave is listening, or the service name, which will be mapped onto the port number according the configuration in the /etc/services file (FIXME - what is the default?)
[timeout <x>]
(FIXME - what does this do? what is the default?)
[send_retries <x>]
(FIXME - what does this do? what is the default?)
[TCP_close {true | false}]
true
(default) Close the connection after each scan. This is slightly slower, as the connection must be re-established at the beginning of the next scan.
false
Keep the connection open between scans. However, some slaves may only support a limited number of simultaneous masters, and this will keep one of those limited slots occupied for as long as this module is running, potentially blocking out other masters.

The openmodbus specification sugests that all TCP connections should be closed if they are going to stay idle for longer than 1 second, so that you should set TCP_close to true if the scan time for this module is longer than a second, and false if it's shorter. In practice, the important consideration will be how many masters are accessing this slave, compared with the slave's "maximum simultaneous masters" specification, and the relative priority between those masters.

# Sample network configurations...
network rtu_net         rtu   device /dev/ttyS1 baudrate 9600 parity none data_bits 8 stop_bits 1 ignore_echo false timeout 1.5 send_retries 2
network asc_net         ascii device /dev/ttyS1 baudrate 9600 parity none data_bits 8 stop_bits 1 ignore_echo false timeout 1.5 send_retries 2
network tcp_net         tcp   host   localhost  port 502  timeout .1 send_retries 1 TCP_close true

Node address table

This is a fairly simple table, giving names to all the nodes based on their Modbus ID. Each line has the form:
node <slave_name> <network_name> <slave_addr>
<slave_name>
The name used to refer to this slave node in the rest of the config.
<network_name>
The name of the network, as declared in the network table (above).
<slave_addr>
The modbus slave ID, 0..255
# Sample slave configurations...
node speed_drive    tcp_net 34
node digital_IO     rtu_net 0
node analog_IO      asc_net 23

Mapping table

Each line has the form:
map [inv | invert] {in | out} <slave>.<reg_type>.<reg_addr> <matplc point>
inv
invert
(optional) invert the value being read from/writen to physical IO
in
copy from the Modbus device to the MatPLC point
out
copy the state of the MatPLC point to the Modbus device
<slave>
the name of the slave node, as it appears in the node address table.
<reg_type>
Which register type (data table) to access, according to this table:
typedata tablelong addressin/outModbus fn. usedAmount of data read/written
inout
in_bitDiscrete Input1xxxx must be mapped in0x02-The number of bits transfered is the same as the number of bits in the MatPLC point being mapped. The address given in the mapping is the adress of the first bit.
out_bitCoil0xxxxmay be mapped in or out0x010x0F (15)
in_wordInput Register3xxxx must be mapped in0x04-If MatPLC point being mapped has 16 or less bits, 1 word will be trnsferred. If it has between 17 and 32, 2 words will be transferred. The address given in the mapping is the adress of the first word.
out_wordHolding Register4xxxx may be mapped in or out0x030x10 (16)
<reg_addr>
1..10000
Note that, as per the standard, <reg_addr> is 1-based. If your documentation lists Modbus addresses starting with 0, you will have to add 1 to each of them.
<matplc point>
the MatPLC point to map

# Sample IO table
map out digital_IO.out_bit.1 L1
map out digital_IO.out_bit.2 L2
map out digital_IO.out_bit.3 L3
map out digital_IO.out_bit.4 L4


Error logging

The first time an error occurs (timeout, received invalid response frame, received error frame, etc...) when communicating with a device, this will be logged as an error at level 2. All subsequent errors for the same device will be logged as an error at level 3. When a device comes back up, this will be logged as an error at level 2.

Modbus slave

The modbus slave module is partially implemented and has not undergone serious testing. Currently, it supports TCP/IP transport only. Furthermore, functions 0x03, 0x04, and 0x06 only are available.

Access control of MatPLC points through Modbus slave is based on the standard MatPLC architectural concept: in order to write to a point the Modbus slave must be the owner of this point.

The modbus slave module, whose default name is "modbus_s", should be enabled in the MatPLC configuration with a "module" keyword and the path to the module's executable. Note that the ASCII AND RTU versions are not implemented yet and their instances below are for illustration only.

[PLC] 
# Uncomment the modbus protocol version you wish to run... 
module modbus_s "../../io/modbus/modbus_s_tcp"
#module modbus_s "../../io/modbus/modbus_s_asc"
#module modbus_s "../../io/modbus/modbus_s_tru"

Configuration

The configuration consists of two tables:
endpoint
connection information
map
the mapping of actual I/O to MatPLC points (registers)

Endpoint configuration table

This configures endpoints that MatPLC will listen on for incoming requests - TCP address and any associated settings. There can be any number of these - one module may listen on several interfaces.

The format of the table is:
endpoint <network_name> <protocol> <parameters>

<network_name>
The name used to refer to this network in the rest of this config.
<protocol>
{rtu | ascii | tcp}
This must agree with the module being used (tcp is the only option currently supported).
<parameters>
These depend on the type of network:
For tcp networks
[host <x>]
the IP address or DNS name of the interface to listen on. 0.0.0.0 stands for INADDR_ANY.
[port <x>]
x is either the port number on which the slave is listening, or the service name, which will be mapped onto the port number according the configuration in the /etc/services file (FIXME - what is the default?)
[address <x>]
Modbus slave address.
[connections <x>]
The number of simultaneous incomming connections to accept.
[mode <x>]
The mode in which the slave is run: 0 - async, 1 - sync. The default value is 0
# Sample endpoint configuration...
endpoint tcp_net  tcp   host 0.0.0.0 port 5502  address 34 mode 0 connections 1

Mapping table

The object data size is determined by the invoked modbus function. For instance, if a coil reading is requested a single bit of the mapped MatPLC point will be transmitted. Likewise, in register operations, the data object size is 16 bits. Therefore, in order to transmit an entire MatPLC point of maximum size (32 bits) two register operations are needed. Alternatively, a multiple register function may be utilized (currently not supported). Each line has the form:
map slave <shift>.<matplc point>

<shift>
The number of bits to shift a MatPLC point right before mapping it to a modbus type on reading or the number of bits to shift a modbus type right before mapping it to a MatPLC point on writing. The following aliases are available: "high" for 16 and "low" for 0.
<matplc point>
the MatPLC point to map

Useful links

Modbusfw - Modbus/TCP Filtering on Linux Firewalls
A set of kernel patches for Linux Netfilter to allow firewall policy decisions (DROP, DENY, ALLOW, etc.) to be made based on Modbus/TCP header values including modbus function code, providing better access control than simply blocking port 502. However, as of Sep 2003 this is an initial prototype release and they've done only limited testing so any feedback, new feature requests, and/or help with development is appreciated. See http://modbusfw.sourceforge.net for details.
[Prev][Up][Next]

$Date: 2004/12/28 05:32:11 $