AN0500: Using Modbus in SHIP – A Step-by-Step Tutorial

Abstract

A step-by-step guide on how to set up a Modbus link in SHIPTide so you can easily communicate with remote devices.

Tutorial

First Steps: SHIP Communications Concept

You’ll want to review the Communications in SHIP Overview first to get acquainted with the how communications work via link, linksets, and linkvars within SHIPTide projects. These same concepts are used for the various protocols supported in SHIP, including Modbus.

You’ll also want to review the Modbus protocol itself and some more specifics about how it’s used in SHIP.

Function Codes

As described in the Modbus protocol, each “command” issued by the master to the slave (and each response from the slave) has a command (or “function”) code: a single byte that uniquely identifies the command (or response to the command) type.

The function code used for messages by SHIPEngine depends on the configuration of each individual link and how its linkvar’s are setup. Here are two tables showing how the datatype/direction used when defining a linkvar maps to the Modbus protocol data concepts and function codes used depending on if the SIM is acting as a master or slave.

Standard Function Codes

When your GUI configures a link as a Modbus Master link (or as a Slave and receiving Master commands), the following standard Master function codes are used by the underlying communications engine in SHIPEngine to issue (or recognize) Master commands:

SHIP Modbus Master Used Function Code Table
SHIP DatatypeDirectionReadRead MultipleWriteWrite MultipleModbus Type
BooleanInput0x02N/AN/AN/ADiscrete Input
BooleanOutput0x01N/A0x05N/ACoil
ShortInput0x04N/AN/AN/AInput Register
ShortOutput0x03N/A0x06N/AHolding Register

When your GUI configures a link as a Modbus Slave, (or as a Master and expecting a Slave response), the following standard function codes are used by the underlying communications engine in SHIPEngine to issue (or recognize) Slave commands:

SHIP Modbus Slave Response Function Code Table
SHIP DatatypeDirectionReadRead MultipleWriteWrite MultipleModbus Type
BooleanInput0x020x02N/AN/ADiscrete Input(s)
BooleanOutput0x010x010x050x0FCoil(s)
ShortInput0x040x04N/AN/AInput Register(s)
ShortOutput0x030x030x060x10Holding Register(s)

Extended Function Codes

While the above only deals with standard Modbus datatypes, SHIP also supports the transfer of Integer and Float types via both (a) a standard approach using the write/read multiple functions and (b) the Daniel/Enron modbus extensions approach using those functions in a different way. For more information, see:

SHIP also support String and even generic Buffer transfers via custom function codes and payload formats

 

Setting up the SIM as a Modbus Master or Slave

On the GUI side, you set a Modbus link in SHIPTide, the GUI Development tool.

To create a Modbus link you create a link node in the resources area and “bind” that link to a communications port (e.g. UART0 or USB_CDC). The link node also has all the properties to configure the Modbus protocol specifics, including choosing Master or Slave mode, ASCII or RTU, and which (if any) extensions are enabled.

There are two application notes that deal specifically with the basics of setting up and using the SIM as a Modbus Master or Slave:

 

Example Projects

There are two example projects in the .zip file attached to this Application Note: one for ASCII Master and one for ASCII slave. Download the .zip and unpack it; install the project of your choice to a directory on your PC. Launch SHIPTide and open the project.

Defaults in the Examples

The SubProtocol: ASCII

The projects come configured for Modbus ASCII. It is easy to modify them for RTU mode by changing the link node property from ASCII to RTU in SHIPTide, but ASCII mode can be very helpful in debugging. It is also better “framed” than RTU mode, as every ASCII message starts with a “:” and synchronization is easier.

The Comms Link: USB CDC

The example projects are also set up to use USB CDC as the communications link, making it easy to connect the SIM to a PC and (using a terminal program) see the traffic coming out of the SIM. You can even use the Modbus simulators such as at [1] for standard mode commands to simulate the device side on your PC. You can easily change the binding of the link to (say) a UART by changing the link node properties.

The Platform

Check the platform the example project is configured for using the Project->Change Platform/Variant menu and set the example to the platform you are using.

The Projects in Detail

The ASCII Master demo has 4 buttons to interact with. The buttons and their descriptions are listed below. • “SEND COIL” : Sends out a Modbus RTU set coil packet to slave ID 0x01 at address 0x0003. Value sent flips from 0 to 1 repeatedly. • “SEND HOLDING REGISTER” : Sends out a Modbus RTU set holding register packet to slave ID 0x01 at address 0x0000. Value sent increments with each press. • “MANUAL SLAVE POLL” : Triggers a single polling sequence on addresses 0x0000, 0x0001, 0x0003, 0x0004 at slave ID 0x01. • “AUTO POLLING ENABLED”/ “AUTO POLLING DISABLED” : Enables auto polling of addresses 0x0000, 0x0001, 0x0003, 0x0004 at slave ID 0x01 every 1/10th of a second.

Additionally, there are various fields in the table below the buttons showing what data (not full packet contents) had last been sent or received as a result of a polling/sends.

The ASCII Slave demo is basically setup to be driven and polled by the ASCII Master demo and has a few buttons to interact with polled values and display values sent to it.

When either are loaded onto your SIM, you should be able (assuming drivers installed etc) to plug it in via USB to your PC and verify you see a device labelled “Serious CDC/ACM Device (COM#)” in the “Ports (COM & LPT)” section of your device manager.

If you connect to that COM port via a terminal application like Tera Term VT you can then receive and send packets manually via ASCII. Same could be done with literal bytes if switched to RTU, but ASCII is far easier.

Our SIMs connect as a composite device with VID 0x25D8, PID 0x0051 where the first interface is a vendor class interface that purely is used for SHIPBridge communications and the second interface is CDC/ACM which is what you’ll be targeting just like the terminal application.

What About on the Other End of the Wire? Free Modbus Stacks

If you’re looking for a free adaptable Modbus stack, the FreeModbus.org site includes several off-the-shelf examples in C you can easily port to your specific MCU. Even if you don’t start with that code, Modbus is a very simple protocol so writing a small bit of code to handle the particular function codes you want to use in the end is not very challenging, especially if you implement a Modbus Slave on your side of the wire. The Master is a bit trickier, so generally you’ll want to use the Master mode in the GUI if you can.

Alternatives to Modbus

Modbus is easy, cheap, and straightforward. It also allows multiple slaves. But Modbus is polled, and not all that rich when it comes to data types and communications flexibility.

See Protocols for a list of other protocols supported in SHIP.

App Note Downloads

Dive Deeper

More App Notes