spec

Software for Diffraction

Fieldbus

Fieldbus Interfaces: CAN, Modbus

DESCRIPTION

Fieldbus encompasses a range of communication protocol families for real-time distributed control. spec currently has support for two such protocols, CAN and Modbus.

The CAN controllers spec currently supports are:

MEN M51 (VME module)
Trinamic CANnes (PCI card)
Lawicel CANUSB (USB dongle)

These motor controllers can be used over a CAN interface:

Mclennan PM595
Trinamic QUADpack/SIXpack
Trinamic TMCL

Modbus defines several protocols. spec supports using Modbus RTU, Modbus ASCII and Modbus TCP. The first two use serial communications, the latter uses ethernet. No special controller is needed.

User level access to both interfaces is available via the built-in fbus_put() and fbus_get() functions.

BUILT-IN FUNCTIONS

The following functions are for generic access to spec's built-in support for fieldbus devices.

fbus_put(unit, d0 [, d1, ...])

Sends a message to the fieldbus device specified as controller number unit in the hardware config file.

CAN

Bits 0 through 28 of d0 hold the CAN ID when in PeliCAN mode. Bits 0 through 10 of d0 hold the CAN ID when in BasiCAN mode. Bit 31 of d0 indicates whether to set CAN RTR (the Remote Transmission Request bit). The CAN message is contained in d1 through d8, which are interpreted as 8-bit byte values. Any missing values are interpreted as zero.

Modbus

d0 is the Modbus function code, where codes 5, 6, 15, 16, 21 and 22 use fbus_put(). Remaining arguments vary depending on the particular function code. See MODBUS FUNCTIONS below.

fbus_get(unit [, d0, d1, ...])

Reads a message from the field-bus device specified as controller number unit in the hardware config file.

CAN

Returns an eight-element data array of long (32-bit) integers. Only the low order byte of each element of the returned array contains data. No arguments beyond the unit number are used.

Modbus

d0 is the Modbus function code, where codes 1, 2, 3, 4, 7, 8, 11, 12, 17, 20, 23, 24 and 43 use fbus_get(). Remaining arguments vary depending on the particular function code. See MODBUS FUNCTIONS below. Returns a scaler if the arguments specify a single value. Otherwise, returns an unsigned short integer data array sized to accommodate the values requested.

For Modbus controllers, arguments d0 and following may be passed as scalers, data arrays or associative arrays in any combination. With arrays, each element is considered an additional argument to the function. Associative array values must be indexed by consecutive integers starting with zero. All values (scalers or array elements) are converted to integers.

Modbus devices over serial interfaces require an address, which can be passed in the unit argument to fbus_put() and fbus_get() using "0.1", 0.10, 0.43, etc., where the first digit is the field bus unit number from the config file, and the digits right of the decimal point form the device address. Quote marks are optional. The syntax "0:1", "0:10", "0:43", etc., is also recognized.

MODBUS FUNCTIONS

A Modbus message consists of a function code and possibly additional parameters. Address arguments are 16 bits with values from 0 to 0xFFFF (0 to 65535). The Modbus message size is limited to 256 bytes, which limits how many values may be passed in a single message.

See the Modbus Application Protocol Specification available at modbus.org for details on the specific syntax of the Modbus functions.

Read functions that return multiple values may return either scalers or arrays. If the function arguments specify the number of values to be returned, fbus_get() will return a scaler if only one value is requested. Otherwise an array will be returned. The functions that can return an indefinite number of values (functions 12, 17, 24 and 43) will always return an array with the value of the first element of the array being the number of elements that follow.

A particular device will likely only support a subset of the functions. The function codes supported by spec are:

Bit Access
"Physical Discrete Inputs", "Internal Bits" and "Physical Coils"
1 "Read Coils"

Bit access to read/write values. Requires an address and a count:

data = fbus_get(0, 1, 0x0100, 100)

Can read up to 2000 contiguous values per call. Returns an array if multiple values are requested. Returns a scaler value if only one value is requested.

2 "Read Discrete Inputs"

Bit access to read-only values. Requires an address and a count:

data = fbus_get(0, 2, 0x0100, 100)

Can read up to 2000 contiguous values per call. Returns an array if multiple values are requested. Returns a scaler value if only one value is requested.

5 "Write Single Coil"

Writes a single bit value. Requires an address and a value. The value must be specified as 0 or 0xFF00 (65280):

fbus_put(0, 5, 0x100, 0xFF00)
15 "Write Multiple Coils"

Write up to 2000 bit values. Requires a starting address, a count and sufficient values. The values can be passed in an array:

byte array bits[2000]
bits = 1
fbus_put(0, 15, 0x100, 2000, bits)
16-Bit Access
"Physical Input or Output Registers" and "Internal Registers"
3 "Read Holding Registers"

Reads 16-bit read/write values. Requires an address and a count:

data = fbus_get(0, 3, 0x0100, 100)

Can read up to 125 contiguous values per call. Returns an array if multiple values are requested. Returns a scaler value if only one value is requested.

4 "Read Input Registers"

Reads 16-bit read-only values. Requires an address and a count:

data = fbus_get(0, 4, 0x0100, 100)

Can read up to 125 contiguous values per call. Returns an array if multiple values are requested. Returns a scaler value if only one value is requested.

6 "Write Single Register"

Writes a single 16-bit value. Requires an address and a value:

fbus_put(0, 6, 0x100, 0x1234)
16 "Write Multiple Registers"

Write up to 123 16-bit registers. Requires a starting address, a count and sufficient values. The values can be passed in an array:

ushort array data[64]
array_op("fill", data, 100)
fbus_put(0, 16, 0x100, 64, data)
23 "Read/Write Multiple Registers"

Read up to 125 16-bit registers. Write up to 121 16-bit registers. Arguments are the read start address, the read count, the write start address, the write count and then the data to write. The write data can be passed in an array:

ushort array wdata[100], rdata[100]
...
rdata = fbus_get(0, 23, 0x200, 100, 0x300, 100, wdata)

Returns an array if multiple values are requested. Returns a scaler value if only one value is requested.

22 "Mask Write Register"

Modifies a holding register using an AND mask, an OR mask and the register's contents. Used to set or clear individual bits. Requires an address, the AND mask and the OR mask, as in:

fbus_put(0, 22, 0x100, 0x00F2, 0x0025)
24 "Read FIFO Queue"
Reads the contents of a first-in-first-out (FIFO) queue of a register in a remote device. The argument after the function code is the register address. Returns a data array where the value of the the first element is the count of values that follow.
File Record Access
A "file" can have up to 10000 records
20 "Read File Record"

The arguments after the function code are in one or more sets of three that specify a file number, a record number and a record length, as in:

fbus_get(0, 20,  4, 1, 2,  3, 9, 2)

which reads two registers from from file 4 starting at address 1 and two registers from file 3 starting at register 9. Returns an array packed with the requested values.

21 "Write File Record"

The arguments after the function code are in one or more sets that specify a file number, a record number, the number of registers to write and the register data (as 16-bit unsigned integers). For example:

fbus_put(0, 21, 4, 7, 3, 0x06AF, 0x04BE, 0x100D)

writes 3 registers starting at register 7 in file 4 with the values shown.

Diagnostics
Mainly for serial line protocols
7 "Read Exception Status"
Returns the value of the exception status register. Serial line only.
8 "Diagnostic"
Returns the value of a diagnostic register or performs a diagnostic function. Takes two arguments after the function code: a sub-function code and a data value. Serial line only.
11 "Get Com Event Counter"
Returns a two-element data array containing a status word and the remote device's event counter. Serial line only.
12 "Get Com Event Log"
Returns an array of events. The first element of the array is the number of events that follow. Serial line only.
17 "Report Server ID"
Returns an array of ID information. The first element of the array is the number of values that follow. Serial line only.
43 "Read Device Identification"
Refer to Modbus documentation for more information. This command will send the arguments as bytes and return an array containing the response. The first element of the array will be the count of the values that follow.

MODBUS ERRORS

If there is an error with fbus_put() or fbus_get(), spec will assign a nonzero value to the built-in global variable HDW_ERR. (See the HDW_ERR help file.) Possible errors include:

3 - A timeout reading a response
5 - An illegal argument to a Modbus function
6 - Trying to access unconfigured hardware
7 - Illegal device address (with serial protocols)
8 - Lost connection (with TCP protocol)
13 - Using fbus_put() for a read command
14 - Using fbus_get() for a write command
15 - Error reading hardware
16 - Error writing to hardware
17 - Checksum error (with serial protocols)
18|(code<<16) - Modbus exception

Modbus exceptions are defined by the standard. Possible values for HDW_ERR are:

0x010012 Illegal function
0x020012 Illegal data address
0x030012 Illegal data value
0x040012 Server device failure
0x050012 Acknowledge
0x060012 Server device busy
0x080012 Memory parity error
0x0A0012 Gateway path unavailable
0x0B0012 Gateway target device failed to respond

Some of the possible exceptions will be caught by spec before a packet is sent to the Modbus device so no Modbus exception will be generated.