AN0502 - Connecting your GUI as a Modbus Slave

From Serious Documentation
Revision as of 06:11, 8 November 2013 by Admin (talk | contribs)
Jump to: navigation, search

This application note covers the setup and initialization a SHIP GUI on a SIM of a simple Modbus slave virtual device. For more information on Modbus, consult this list of resources.


UIs developed in SHIPTide and running in SHIPEngine need to communicate with the outside world. Typically, your GUI needs to turn things on/off, find the status of things in the outside world, and generally exchange information.

System Topology

Modbus is traditionally operated over point-to-point RS232 or multi-drop RS485. It is designed to be operated in half-duplex mode, with one device, and one device only, designated the master that is responsible for polling and directing all the slaves. Slaves cannot spontaneously initiate data messages: they must be polled by the masters. Similarly, slaves cannot talk peer-to-peer to another slave. The master must poll one slave, gather data, and re-send it to another.

Every slave on a given network must have a unique identification number (slave ID). Slaves may occupy more than one slave ID (acting as multiple slaves in one physical device), but no slave IDs can overlap. Typically slaves can be very simple devices, like sensors or actuators, with a tiny DIP switch to manually select from a range of slave IDs.

The master has no id (although in some networks 0 is reserved for the master). This is because the slaves do not need to address the master explicitly, they always just respond to requests from the master.

Modbus Slave RTU and Modbus Slave ASCII Protocols

Modbus is a very simple set of packet protocol. There are 2 different Modbus transmission methods for each packet:

The network is either designated ASCII or RTU. You cannot mix packet types. There is no negotiation process or autobauding capabilities. The type must be set by the network/system designer once and all devices on the network must be manually set to the correct speed.

MODBUS_SLAVE_ASCII is a human-readable ASCII transmission format and is easy to debug on a sniffer terminal device (a device that only listens but does not drive the RS232 or RS485 cable) since a terminal program would display the packets . It is very easy to parse in software, with a unique start character (':') and end sequence (CR-LF), but because every byte is sent as a hex-ascii value (for example, an 'a' is sent as two bytes '2' and '1', representing hex 0x21 which is an 'a'), it is half the speed of a binary transmission protocol.

For more information on the protocol, see the list of modbus references.



As a Modbus slave, the SIM (and the GUI within the SIM) is polled by a Master on the network.

Creating a Communications Link

Communications links are described by a set of tree-structured nodes in the link resource area. The three main node types are:

  • the <link> node, which binds a protocol to a communications node, for instance the Modbus Master RTU protocol bound to the UART0 port,
  • the <linkset> node, which encompasses all the traffic between two endpoints in the <link>, and,
  • the <linkvar> node, which describes a shared variable between the two endpoints in a <linkset>.

<link> Nodes

A <link> node binds a protocol to a physical communications channel. The only properties of a link are:

Property Description
name A unique link name
protocol The protocol bound to the channel (e.g. MODBUS_MASTER_RTU)
channel A port name (e.g. UART0)

For example, the following link binds a MODBUS_SLAVE_ASCII protocol to UART0 on a SIM110:

Property Value
name myModbusSlave
protocol MODBUS_SLAVE_ASCII
channel platform.UART0

Each channel in a platform may only be bound once to a single protocol. For example, UART0 can only be bound to a single protocol (e.g. MODBUS_MASTER_RTU).

<linkset> Nodes

Within a given link, there may be one or more <linkset> nodes. Each linkset encompasses all the traffic between two endpoints in a link. The properties of a linkset are:

Property Name Description
name A unique linkset name within the link
id Some protocols require the endpoint to have an ID number assigned
channel A port name (e.g. UART0)

On the slave side of master/slave protocols (for example the MODBUS_SLAVE_RTU), the link may be representing one or more Modbus slaves within the SHIPEngine environment. Even though the protocol is running on a single physical communications channel (e.g. UART0), each linkset within the link can act as one of a number of independent virtual slaves.

On the master side of master/slave protocols (for example MODBUS_MASTER_ASCII) you may want to address multiple slaves on the channel. Each slave would be identified by a linkset with the slave ID set appropriately.

Adding two linksets to our prior example might look like this:

Example link with two linksets

In this example, our GUI is acting as a Modbus Slave attached to UART0, potentially one of many on the communications channel. This physical channel could be, for instance, a multi-drop RS485 network with many slaves of which our Sim is only one. Our GUI, because it has the two linksets at ID #1 and #13 created, will respond as if it were two of those slaves on the network.

<linkvar> Nodes

<linkvar> nodes describe shared variables on the given linkset. The linkvar properties available depend on the protocol selected.

The following are normal properties of a linkvar:

Property Name Description
name A unique variable name within the linkset
datatype The data type of this link variable; may be limited depending on the protocols
address Most protocols require each variable to have a unique address/location/id number assigned
direction Most protocols need to understand if this is an input or output variable
enabled Defaults to true, but can be set false in SHIPTide. Only enabled variables participate in polling (if applicable).

The direction can be a bit confusing: it is always with respect to SHIPEngine. So an "output" direction means the data is supplied by SHIPEngine to the remote end of the linkset, regardless of whether the linkset is a master or slave in a master/slave environment. Similarly, an "input" direction means that the data is coming into the variable from the remote end of the linkset. Remember that "in" and "out" are with respect to your GUI in SHIPEngine.

The datatypes are protocol dependent, and, in the Modbus case, may be limited to the basic Modbus data types of Boolean and Short.

Expanding the example above with four linkvars looks like this:

Example linkset with four link variables (linkvars)

Our example here is, perhaps, a hypothetical GUI controlling a pump. Our GUI (in a Sail script) could turn on the pump by setting the pumpOnRequest output Boolean linkvar to "true". Since Modbus masters poll their slaves, the next time the master polls slave #1 address 0x4000 ("pumpOnRequest", a Boolean), it will read a "true" at that shared variable location, indicating to the master (the pump) to turn on. It may also poll slave #1 address 0x2000 ("pumpRPMRequest", a Short) to determine the requested RPM before turning the pump on. It may continue to poll these two locations to watch for a request to stop the pump or change the RPM. Also, as the pump turns on and off, and its actual RPM changes, it may send those values to slave#1 address 0x4001 ("pumpOn", a Boolean) and 0x2002 ("pumpRPM", a Short) respectively.

Note that just because the GUI "requests" that a remote device performs some action does not mean the remote device actually does it. The GUI (in a Sail script) might request the pump turn on, but it may not happen for whatever reason (the pump is overheated, for example). Timeouts and other mechanisms can be done in the GUI to watch for these conditions.

A good practice is to have visual indicators on the GUI reflect the actual remote state, rather than the requested state. For example, an RPM reading in the GUI should reflect the value of "pumpRPM", not "pumpRPMRequest".

Starting a Communications Link

Events and Polling