Control Solutions is your source for LonWorks I/O.
PL/i Programming Language (click here to return to PL/i help index)

The following summary provides an overview of PL/i extensions for local network communications such as Modbus RTU and LonWorks.

LonWorks Local Bound Network Variables

The local LonWorks processor holds 36 network variable outputs or NVO's (defined as sensor function blocks) and 20 network variable inputs or NVI's (defined as actuator function blocks). These may be bound to other nodes by any external network management tool that supports standard LonWorks objects. The network types may be dynamically changed to any standard variable type (SNVT). The variables may be read or written from the PL/i program using the following statements:

nv_read ( <index> , <var> );
nv_write ( <index> , <var> );

<var> = nv_isnew ( <index> );
nv_info ( <index> , <var> );

The <index> in each of the above statements is the network variable index, which must be in the range of 5 to 61. Any valid expression may be used as the index (constant, variable, etc.). The network variable will be read into the variable named by <var> in nv_read, and written from <var> in nv_write. The nv_isnew function will return TRUE if the indexed network variable input (NVI) has received an update since the last call, or false otherwise. The NVO's will always return false (they do not "receive" data).

The variable types read or written should match the expected data type on the network. A large number of SNVT's are 2-byte integer values, and a large number are 4-byte floating point. Several SNVT's are also structures. Use a PL/i record defined in the same format as the SNVT to read or write structured network variables. The following simple example shows the definition of SNVT_switch and a program that turns the switch "on" at 100% (value is scaled x2 in SNVT_switch). In this case, we have made the assumption that the external network management tool has changed the type of the NV at index 5 to SNVT_switch.

program nvtest
declare
type SNVT_switch = record
value: uint8;
state: int8;
end;
netvar: SNVT_switch;

begin
netvar.state = 1;
netvar.value = 200;
nv_write (5, netvar);
end

It may be desirable to find out from within your PL/i program what type (SNVT) the network variable has been configured to. You cannot reconfigure network variable types from a PL/i program. Due to the fact that the Neuron Chip is not allowed to self-modify its code, network variable type changes can only be made from outside the device via the network using a network management tool. However, once reconfigured, you can retrieve the configuration information to see what type you have been given.

You must define a record which is an abbreviated form of SNVT_nv_type. It is defined in PL/i as shown in the following example. The call to nv_info then retrieves this information record for NV index 5.

program nvinfo
declare
type nvInfo = record
nvIndex: uint8;
nvSnvtIndex: uint16;
nvSnvtTypeCat: uint8;
nvSnvtTypeSize: uint8;
nvSnvtScaleA: int16;
nvSnvtScaleB: int16;
nvSnvtScaleC: int16;
end;
infovar: nvInfo;

begin
nv_info (5, infovar);
end

The nv_info function is only applicable to the local bound network variables.

LonWorks Remote Polled Network Variables     

Variables in remote devices may be polled without binding. Up to 20 devices may be identified in the device table of the server. Up to 62 network variables per device may be polled. The functions for accessing remote network variables are:

nv_update ( <node> , <index> , <var> );
nv_fetch ( <node> , <index> , <var> );

The nv_update function reads data from the given variable and sends it to the remote device. The nv_fetch function retrieves data from a remote device and writes it into the given variable. The <node> refers to the device number in the device table, 1 through 20. The <index> is the network variable index 0..61. The <var> is the variable that data will be read from or written into.

The variable type must match the network variable being accessed in the remote device. Data type declarations would be the same as noted above with the SNVT_switch example.

Use the LON Devices page to set up the device table. This table is included in the XML configuration file stored in the server. Once set up and saved, it will be restored each time the server is restarted.

Modbus RTU Holding Register Read/Write

Holding registers in remote Modbus RTU devices connected via the RS-485 port may be read or written. These procedures are independent of any register mapping defined in the server mapping tables. The syntax for Modbus read/write is:

mod_read ( <uint> , <register> , <var> );
mod_write ( <uint> , <register> , <var> );
mod_swap ( <var> );

The <unit> is also referred to as Slave ID, and must be 1 to 247. Register numbers count up from 1. The variable may be a single variable, and array, or a structure. Modbus registers are defined by that protocol as 16-bit data entities. The number of registers that will be read or written, starting at <register>, will be the variable size divided by 2. To read a single 16-bit register, you must use either int16 or uint16 as the data type. To read a double register, use int or float. To read multiple registers, use an array.

The order of registers in double register pairs, as used to make up a floating point value, is not standardized. Therefore, the mod_swap function will swap the two registers contained in the 4-byte variable named to compensate for differences between the devices.

Host to Network Conversion (and Network to Host Conversion)

Modbus and LonWorks protocols are by definition "big endian" meaning the most significant byte of a multi-byte data element comes first. Some processors are "little endian", sometimes also referred to as "Intel style", including the AddMe III co-processor. Therefore data must be converted from "host" to "network" format before being sent, and converted from "network" to "host" format when received. The following functions are used to convert 2-byte and 4-byte data elements:

htonl ( <var> );
hton ( <var> );
ntohl ( <var> );
ntoh ( <var> );

The "hton" functions convert host to network. The "htonl" converts a "long" or 4-byte value (either integer or floating point), and "hton" converts a 2-byte value (int16 or uint16). The "ntoh" functions convert network to host, 4-byte or 2-byte. The content of the named variable is converted and left stored in the same variable.

Host/network conversion is done automatically by PL/i for single variables. However, any time you use an array or structure as the target of network access (either Modbus or LonWorks), you must manually convert the fields as necessary. Double Modbus registers may require both hton/ntoh and mod_swap.

Remember: Call "hton" before network calls, and call "ntoh" after network calls.

In the following example, the first four assignment statements will work, but the last one will cause an "Unexpected types" error. The target of the assignment may be any type, but the operands of the expression must be integer or floating point.

Error Codes

PL/i traps a number of errors while your program is running. Generic PL/i error codes are listed at the bottom of the main help page. Additional error codes specific to local network communications are listed here. Runtime error codes are accessible in a phantom local register #0. To get the most recent error, read register zero as shown here:

<var> = geti (0);

The following runtime errors are specific to communications.

403 = LonWorks NV index out of bounds
404 = LonWorks NV request timeout
405 = Resource contention, already in use

The following error codes are returned by the LonWorks gateway processor:

421 = No response to NV query (usually means addressed node is off-line)
422 = LonWorks NV update failed
423 = LonWorks NV fetch returned mismatch in NV index or size
424 = LonWorks NV fetch failed/timed out (node off-line)
425 = Invalid NV index (check your program)
426 = Invalid node address, NID for node is zero
427 = No LonWorks support on this device

The following error codes are returned by the Modbus communications processor:

431 = Modbus transaction ID out of sync
432 = Modbus exception code returned
433 = Modbus returned function code does not match code sent
434 = Modbus got too few data bytes back
435 = Modbus RTU timeout, no response from slave
436 = CRC error in Modbus response
437 = Modbus response not formatted as expected
438 = Modbus function not supported