modbusOpenX (Function)

Top  Previous  Next

Architecture:

X32 / NX32 / NX32L

Device support:

All devices with RS485 or LAN

Firmware version:

4.50 / 1.00.00


This function will open a connection to a MODBUS network.

The connection uses either the RTU, ASCII or TCP protocol.

 

The device supports both master mode, where the device controls the MODBUS network and polls the slaves, and slave mode, where the device waits for commands from the master.

Please note that the TCP protocol can only be used via the LAN network interface, which must be opened before communication is possible.

 

For NX32L devices, all interfaces can be used with the TCP protocol (from firmware version 1.08.00).

 

 

Input:

mode : SINT

1

- RTU protocol

2

- ASCII protocol

3

- TCP protocol

 

unit_id : INT (0..247)

The address of the RTCU device on the MODBUS network.

If this parameter is set to zero, the RTCU device will be the master on the network.

 

port : DINT (default -1)

When port is set to -1, the default port for the selected mode is used.

 

mode = 1

Selects which serial port to use (see serial port enumeration, default is port 0).

 

mode = 2

Selects which serial port to use (see serial port enumeration, default is port 0).

 

mode = 3

Selects which IP port to listen for connections from Masters on. (default is port 502)

 

iface : SINT (default 0)

The network interface from which incoming TCP connections are accepted. (See Network)

The network interface must be present and connected, when modbusOpenX is called if set.

This parameter is ignored if mode != 3 or if the RTCU device is the master.

(from firmware version 1.32.00).

 

con_timeout : UINT (0..30000) (default 1000)

The number of milliseconds to try to connect to a slave before timing out.

This parameter is ignored if mode != 3 or if the RTCU device is not the master.

 

baud : DINT (9600,19200,38400,57600,115200) (default 115200)

Selects the desired baud rate.

This parameter is ignored if mode 3 is selected.

 

bit : SINT (7/8) (default 8)

Selects the number of bits per character.

This parameter is ignored if mode 3 is selected.

Note:  7 bit without parity bit only works on LX devices.

 

parity : SINT (0..2) (default 1)

Selects the desired parity, 0 is none, 1 is even, and 2 is odd.

This parameter is ignored if mode 3 is selected.

 

stopbit : SINT (1/2) (default 1)

Selects number of stop bits.

This parameter is ignored if mode 3 is selected.

 
Note: Only 1 stop bit is supported on the RS485 ports on NX devices.

 

rs485 : SINT (-1..1) (default -1)

-1

- Auto detect. First try to use RS485 then RS232.

0

- Use RS232

1

- Use RS485

This parameter is ignored if mode 3 is selected.

 

allow1 : DINT (default 0)

Remote IP address accepted. 0 if all is allowed.

This parameter is ignored if mode != 3 or if the RTCU device is the master.

 

allow2 : DINT (default 0)

Remote IP address accepted. 0 if all is allowed.

This parameter is ignored if mode != 3 or if the RTCU device is the master.

 

allow3 : DINT (default 0)

Remote IP address accepted. 0 if all is allowed.

This parameter is ignored if mode != 3 or if the RTCU device is the master.

 

allow4 : DINT (default 0)

Remote IP address accepted. 0 if all is allowed.

This parameter is ignored if mode != 3 or if the RTCU device is the master.

 

allow5 : DINT (default 0)

Remote IP address accepted. 0 if all is allowed.

This parameter is ignored if mode != 3 or if the RTCU device is the master.

 

allow6 : DINT (default 0)

Remote IP address accepted. 0 if all is allowed.

This parameter is ignored if mode != 3 or if the RTCU device is the master.

 

allow7 : DINT (default 0)

Remote IP address accepted. 0 if all is allowed.

This parameter is ignored if mode != 3 or if the RTCU device is the master.

 

allow8 : DINT (default 0)

Remote IP address accepted. 0 if all is allowed.

This parameter is ignored if mode != 3 or if the RTCU device is the master.

 

allow9 : DINT (default 0)

Remote IP address accepted. 0 if all is allowed.

This parameter is ignored if mode != 3 or if the RTCU device is the master.

 

allow10 : DINT (default 0)

Remote IP address accepted. 0 if all is allowed.

This parameter is ignored if mode != 3 or if the RTCU device is the master.

 

 

Returns: INT

ID of the MODBUS connection.

-1

- All MODBUS connections are in use.

-2

- Illegal unit_id selected.

-5

- Illegal serial port.

-6

- Failed to open connection.

-7

- Illegal serial port parameters.

-8

- Illegal mode selected.

-9

- The network interface is not connected.

 

Declaration:

FUNCTION modbusOpenX : INT;
VAR_INPUT
  mode   : SINT;
  unit_id : INT;
  port   : DINT := -1;
  iface   : SINT := 0;
  con_timeout : UINT := 1000;
  baud   : DINT := 115200;
  bit     : SINT := 8;
  parity : SINT := 1;
  stopbit : SINT := 1;
  rs485   : SINT := -1;
  allow1 : DINT := 0;
  allow2 : DINT := 0;
  allow3 : DINT := 0;
  allow4 : DINT := 0;
  allow5 : DINT := 0;
  allow6 : DINT := 0;
  allow7 : DINT := 0;
  allow8 : DINT := 0;
  allow9 : DINT := 0;
  allow10 : DINT := 0;
END_VAR;

 

Example:

INCLUDE rtcu.inc
 
VAR
  mbNet : INT;
  mbRcv : modbusReceive;
END_VAR;
 
FUNCTION setINT;
VAR_INPUT
  adr : PTR;
  v   : INT;
END_VAR;
  memcpy(dst := adr + 1, src := ADDR(v)   , len := 1);
  memcpy(dst := adr   , src := ADDR(v) + 1, len := 1);
END_FUNCTION;
 
FUNCTION_BLOCK modbusReadDiscreteInputs;
VAR_INPUT
  net_id : INT;
  unit_id : INT;
  index   : INT;
  length : INT;
END_VAR;
VAR_OUTPUT
  status : INT;
  size   : INT;
  input : ARRAY[1..32] OF BOOL;
END_VAR;
VAR
  rc, i : INT;
  buf   : ARRAY[1..253] OF SINT;
  mask   : SINT;
END_VAR;
 
  // Check length
  IF length < 1 OR length > 32 THEN
     status := 1;
    RETURN;
  END_IF;
  IF index < 1 THEN
     status := 2;
    RETURN;
  END_IF;
 
  // Build command
  buf[1] := 16#02;
  setINT(adr := ADDR(buf[2]), v := index - 1);
  setINT(adr := ADDR(buf[4]), v := length);
 
  // Send command
  rc := modbusSend(net_id := net_id, unit_id := unit_id, frame := ADDR(buf), size := 5);
  IF rc <> 0 THEN
     status := 3;
    RETURN;
  END_IF;
 
  // Wait for reply
  IF NOT modbusWaitData(net_id := net_id, timeout := 5000) THEN
     status := 4;
    RETURN;
  END_IF;
 
  // Read reply
  mbRcv(net_id := net_id, frame := ADDR(buf), maxsize := SIZEOF(buf));
  IF mbRcv.status <> 0 THEN
     status := 5;
    RETURN;
  END_IF;
  IF mbRcv.unit_id <> unit_id THEN
     status := 6;
    RETURN;
  END_IF;
  IF buf[1] <> 16#02 THEN
     status := 7;
    RETURN;
  END_IF;
 
  // Parse reply
  mask := 1;
  FOR i := 1 TO length DO
     input[i] := BOOL(buf[3 + ((i - 1) / 8)] AND mask);
     mask := shl8(in := mask, n := 1);
    IF mask = 0 THEN mask := 1; END_IF;
  END_FOR;
  size   := length;
  status := 0;
END_FUNCTION_BLOCK;
 
PROGRAM ModbusExample;
VAR
  dinRead : modbusReadDiscreteInputs;
  linsec : DINT;
  i       : INT;
END_VAR;
 
  DebugMsg(message := "Initializing...");
  mbNet := modbusOpenX(mode := 1, unit_id := 0, port := 2, baud := 19200, parity := 0);
  DebugFmt(message := "modbus...\1", v1 := mbNet);
 
BEGIN
  IF clockNow() > linsec THEN
    DebugMsg(message := "------------------------------");
    DebugMsg(message := "Reading inputs:");
     dinRead(net_id := mbNet, unit_id := 9, index := 1, length := 4);
    DebugFmt(message := "-status=\1", v1 := dinRead.status);
    IF dinRead.status = 0 THEN
        FOR i := 1 TO dinRead.size DO
          DebugFmt(message := "-input[\1]=\2", v1 := i, v2 := INT(dinRead.input[i]));
        END_FOR;
    END_IF;
    // Set next reading
     linsec := clockNow() + 5;
  END_IF;
END;
END_PROGRAM;