modbusOpen (Function)

Top  Previous  Next

Architecture:

X32 / NX32 / NX32L

Firmware version:

1.50 / 1.00.00


This function will open a connection to a MODBUS RTU network.

 

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.

 

 

Input:

mode : SINT (0/1)

0

- The RTCU device is master on the MODBUS network.

1

- The RTCU device is a slave on the MODBUS network.

 

unit_id : INT (1..247)

The address of the RTCU device on the MODBUS network.

Note: this parameter is ignored if mode is set to master.

 

port : DINT (0..2) (default 0)

Selects which serial port to use (see serial port enumeration).

 

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

Selects the desired baud rate.

 

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

Selects the number of bits per character.

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.

 

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

Selects number of stop bits.

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

 

Returns: INT

ID of the MODBUS connection.

-2

- Illegal unit_id selected.

-5

- Illegal serial port.

-6

- All MODBUS connections are in use.

-7

- Illegal serial port parameters.

 

Declaration:

FUNCTION modbusOpen : INT;
VAR_INPUT
   mode    : INT;
   unit_id : INT;
   port    : DINT := 0;
   baud    : DINT := 115200;
   bit     : SINT := 8;
   parity  : SINT := 1;
   stopbit : SINT := 1;
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 := modbusOpen(port := 2, baud := 19200, parity := 0, mode := 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;