Difference between revisions of "Modbus Communication API"

From SoftMC-Wiki
Jump to: navigation, search
(added error codes)
(Added valid input parameters and error codes)
Line 30: Line 30:
 
## Modbus.lib
 
## Modbus.lib
 
#* '''Notice:''' From now on, in our examples, we'll use the X86 configuration.<br>[[File:modbus;newAPI-upload.jpg|850px]]
 
#* '''Notice:''' From now on, in our examples, we'll use the X86 configuration.<br>[[File:modbus;newAPI-upload.jpg|850px]]
# Load the files to memory, by typing (in the Terminal):
+
# Access the file CONFIG.PRG and modify the program by adding the following two lines:
 
#:<pre>
 
#:<pre>
#::Oload mb_x86.O
+
#::Program
#::loadglobal Modbus.lib</pre>
+
#:: Oload mb_x86.O
 
+
#:: Load modbus.lib
 +
#::...
 +
#::...
 +
#::End Program</pre>
 +
# Upload CONFIG.PRG to the softMC.
 +
# Use the ControlStudio Terminal to enter the following:
 +
#:<pre>
 +
#::reset all
 +
#::?tasklist</pre>
 +
#: The system's response: <pre>GlobalLibraryName=MODBUS.LIB</pre>
 +
#:This indicates that library MODBUS.LIB has been loaded globally.
 +
# That's it! You're now ready to configure the Modbus system.
 
== Initializing a Modbus Server ==
 
== Initializing a Modbus Server ==
 
To initialize the Modbus server address space, call:
 
To initialize the Modbus server address space, call:
Line 166: Line 177:
 
=== Server Components ===
 
=== Server Components ===
 
==== Reading ====
 
==== Reading ====
 +
* The following functions read variables from the different types of registers and return them.
 +
* When a read error occurs, the functions will write [function name] + "ERROR" + [error code] in the Message Log.
 
===== Reading from Holding registers =====
 
===== Reading from Holding registers =====
 
<pre>
 
<pre>
 
Val = MB_SERVER_READ_REG_LONG([index], [byte_swap], [word_swap])
 
Val = MB_SERVER_READ_REG_LONG([index], [byte_swap], [word_swap])
 
Val = MB_SERVER_READ_REG_SHORT([index], [byte_swap])
 
Val = MB_SERVER_READ_REG_SHORT([index], [byte_swap])
Val = MB_SERVER_READ_REG_FLOAT()
+
Val = MB_SERVER_READ_REG_FLOAT([index], [byte_swap], [word_swap])
Val = MB_SERVER_READ_REG_DOUBLE()
+
Val = MB_SERVER_READ_REG_DOUBLE([index], [byte_swap], [word_swap], [long swap])
 
</pre>
 
</pre>
 
===== Reading from Bits registers =====
 
===== Reading from Bits registers =====
<pre>val = MB_SERVER_READ_BIT([addr])</pre>
+
<pre>val = MB_SERVER_READ_BIT([index])</pre>
 
===== Reading from Input registers =====
 
===== Reading from Input registers =====
 
<pre>
 
<pre>
Val = MB_SERVER_READ_INREG_LONG()
+
Val = MB_SERVER_READ_INREG_LONG([index], [byte_swap], [word_swap])
Val = MB_SERVER_READ_INREG_SHORT()
+
Val = MB_SERVER_READ_INREG_SHORT([index], [byte_swap])
Val = MB_SERVER_READ_INREG_FLOAT()
+
Val = MB_SERVER_READ_INREG_FLOAT([index], [byte_swap], [word_swap])
Val = MB_SERVER_READ_INREG_DOUBLE()
+
Val = MB_SERVER_READ_INREG_DOUBLE([index], [byte_swap], [word_swap], [long swap])
 
</pre>
 
</pre>
 
===== Reading from Input Bits registers =====
 
===== Reading from Input Bits registers =====
<pre> val = MB_SERVER_READ_INBIT([addr])</pre>
+
<pre> val = MB_SERVER_READ_INBIT([index])</pre>
 +
===== Valid Parameters =====
 +
{| class="wikitable" border="1"
 +
|-
 +
! Parameter
 +
! Valid Input
 +
|-
 +
| Index
 +
| From 0 to the number of registers available.
 +
|-
 +
| Byte_swap
 +
| 1 or 0 (True/False)
 +
|-
 +
| Word_swap
 +
| 1 or 0 (True/False)
 +
|-
 +
| Long_swap
 +
| 1 or 0 (True/False)
 +
|}
 
==== Writing ====
 
==== Writing ====
 +
* The following functions write data into the different types of registers.
 +
* When a write error occurs, the functions will write [function name] + "ERROR" + [error code] in the Message Log.
 
===== Writing to holding registers =====
 
===== Writing to holding registers =====
 
<pre>
 
<pre>
Val = MB_SERVER_WRITE_REG_LONG()
+
Val = MB_SERVER_WRITE_REG_LONG([index],[new value],[byte swap], [word swap])
Val = MB_SERVER_WRITE_REG_SHORT()
+
Val = MB_SERVER_WRITE_REG_SHORT([index],[new value],[byte swap])
Val = MB_SERVER_WRITE_REG_FLOAT()
+
Val = MB_SERVER_WRITE_REG_FLOAT([index],[new value],[byte swap], [word swap])
Val = MB_SERVER_WRITE_REG_DOUBLE()
+
Val = MB_SERVER_WRITE_REG_DOUBLE([index],[new value],[byte swap], [word swap], [long swap])
 
</pre>
 
</pre>
 
===== Writing to Bits registers =====
 
===== Writing to Bits registers =====
<pre>val = MB_SERVER_WRITE_BIT([addr],[value])</pre>
+
<pre>val = MB_SERVER_WRITE_BIT([index],[new value])</pre>
 
===== Writing to Input registers =====
 
===== Writing to Input registers =====
 
<pre>
 
<pre>
Val = MB_SERVER_WRITE_INREG_LONG()
+
Val = MB_SERVER_WRITE_INREG_LONG([index],[new value],[byte swap], [word swap])
Val = MB_SERVER_WRITE_INREG_SHORT()
+
Val = MB_SERVER_WRITE_INREG_SHORT([index],[new value],[byte swap])
Val = MB_SERVER_WRITE_INREG_FLOAT()
+
Val = MB_SERVER_WRITE_INREG_FLOAT([index],[new value],[byte swap], [word swap])
Val = MB_SERVER_WRITE_INREG_DOUBLE()
+
Val = MB_SERVER_WRITE_INREG_DOUBLE([index],[new value],[byte swap], [word swap], [long swap])
 
</pre>
 
</pre>
 
===== Writing to Input Bits registers =====
 
===== Writing to Input Bits registers =====
<pre>val = MB_SERVER_WRITE_INBIT([addr],[value])</pre>
+
<pre>val = MB_SERVER_WRITE_INBIT([index],[value])</pre>
 
+
===== Valid Parameters =====
 +
{| class="wikitable" border="1"
 +
|-
 +
! Parameter
 +
! Valid Input
 +
|-
 +
| Index
 +
| From 0 to the number of registers available.
 +
|-
 +
| New value
 +
| The value to write, must be from the appropriate type.
 +
|-
 +
| Byte_swap
 +
| 1 or 0 (True/False)
 +
|-
 +
| Word_swap
 +
| 1 or 0 (True/False)
 +
|-
 +
| Long_swap
 +
| 1 or 0 (True/False)
 +
|}
 +
==== Error codes ====
 +
{| class="wikitable" border="1"
 +
|-
 +
! Error
 +
! Meaning
 +
|-
 +
| -1
 +
| Invalid index.
 +
|-
 +
| -2
 +
| Local server's address space isn't mapped yet.
 +
|-
 +
| -3
 +
| Failed to catch the register mutex.
 +
|-
 +
| -4
 +
| Failed to release the register mutex.
 +
|}
 
=== Client Components ===
 
=== Client Components ===
 
==== Reading ====
 
==== Reading ====

Revision as of 07:14, 17 April 2016

Overview

Basic Overview

  • This describes how to set up Modbus communication for the softMC, and how to generate softMC scripts to handle Modbus communication.
  • It is assumed you are familiar with the principles of Modbus communication, although some of them will be described in this page.
  • It is also assumed your are familiar with the softMC, ControlStudio and MC-Basic programming.

Modbus Communication Background

  • A Motion Controller (MC) can act as a server (slave), a client (master) or both at the same time.
  • Each MC connection (TCP/RTU) can be used either as a server component (if the connection is used by the MC’s server-side) or as a client component (if the connection is used by the MC’s client-side).
  • Each component has its own parameters that defines it.
  • When the MC acts as a server, all server components share the same memory address space, thus acting as one server with multiple connections.
  • Each server (slave) on a Modbus network has its own deviceID, which is a number between 1 and 247.

The Modbus server registers

  • There are 4 types of registers in the Modbus Server address space:
    1. Bits (1-bit registers)
    2. Input Bits (1-bit READ-ONLY registers)
    3. Holding Registers (16-bit registers)
    4. Input Registers (16-bit READ-ONLY registers)
  • Servers can read and write their own address space.
  • Clients can read and write a remote server’s address space.

Getting Started

In order to get started in using the Modbus features:

  1. Download the required files, according to your system's type:
    1. Required files for modbus_X86.ZIP.
    2. Required files for ARM systems.
  2. Using the ControlStudio File Manager, Upload the following files to your MC:
    1. mb_x86.O (for X86 Systems) / mb_armA9.O (for ARM Systems)
    2. Modbus.lib
    • Notice: From now on, in our examples, we'll use the X86 configuration.
      modbus;newAPI-upload.jpg
  3. Access the file CONFIG.PRG and modify the program by adding the following two lines:
    Program
    Oload mb_x86.O
    Load modbus.lib
    ...
    ...
    End Program
  4. Upload CONFIG.PRG to the softMC.
  5. Use the ControlStudio Terminal to enter the following:
    reset all
    ?tasklist
    The system's response:
    GlobalLibraryName=MODBUS.LIB
    This indicates that library MODBUS.LIB has been loaded globally.
  6. That's it! You're now ready to configure the Modbus system.

Initializing a Modbus Server

To initialize the Modbus server address space, call:

?init_multi_server([bits],[input_bits],[holding registers],[input_registers])
  • The function prints "success" and returns 0 on success, or return an error code on failure.
  • Notice:
    1. This is NOT required when softMC does not run a modbus server.
    2. You can call this method only if no servers are running.

Error codes:

Error Meaning
-1 Memory allocation failure.
-2 Some servers are still running and using an already mapped address space.
-3 Failed to create a modbus mapping.

Server Components

Adding server components

  • Each time you'll add a component, you will receive a handle, which is the component's identifier (for later use).
  • It is best to keep this handles in variables inside your program.

Creating a TCP server component

handle = mb_tcp_server_create([port],[deviceID])
  • This opens a TCP connection to the server on port [port] with deviceID [deviceID], and starts the created server immediately.
  • Returns a handle on success, or an error code on failure.

Error codes:

Error Meaning
-1 Server address spaces isn't initialized yet, please call "init_multi_server(...) and try again.
-2 Failed to create main socket.
-3 Failed to connect.
-4 Failed to create server thread.

Creating an RTU server component

handle = mb_rtu_server_create([type],[port],[baudrate],[data bits],[stop bits],[parity],[deviceID])
  • This opens an RTU connection with the given parameters, and starts the created server immediately.
  • Returns a handle on success, or an error code on failure.

Error codes:

Error Meaning
-1 Server address spaces isn't initialized yet, please call "init_multi_server(...) and try again.
-2 Invalid device string.
-3 Invalid parity.
-4 Failed opening RTU.
-5 Failed allocating query buffer memory.
-6 Failed to set RTU mode.
-7 Unable to connect.
-8 Failed to create server thread.
-9 The device is already in use by another system component.

Stopping Server Components

Stopping a specific server component

You can stop a specific server component by passing its handle to:

result = mb_server_stop([handle])
  • Given a handle, this will stop and free the memory of the appropriate server component.
  • Returns 0 on success, -1 on failure.

Stopping all server components

You can stop all server components with a single call to:

result = mb_server_stop_all

This function will:

  • Stop and free all server components.
  • Free the shared address space.
  • Return 0 on success, -1 on failure.

Client Components

Adding client components

  • Each time you'll add a component, you will receive a handle, which is the component's identifier (for later use).
  • It is best to keep this handles in variables inside your program.

Adding a TCP Client component

handle = mb_tcp_client_create([ip],[port])
  • This will opens a TCP connection to the client on the given ip and port, and start the client immediately.
  • Returns a handle on success, -1 on failure.

Adding an RTU Client component

handle = mb_rtu_client_create([type],[port],[baudrate],[data bits],[stop bits],[parity])
  • This will open an RTU connection to the client with the given parameters, and start the client immediately.
  • Returns a handle on success, -1 on failure.

Stopping client components

A specific client can be stopped by calling:

result = mb_client_stop([handle])
  • Given a handle, this will stop and free the memory of the appropriate client component.
  • Returns 0 on success, -1 on failure.

Reset the Modbus System

Sometimes, a user may wish to stop all server and client components at once, and reset the Modbus system (for example, when a user want to initialize a different Modbus system). To do that, call:

result = mb_reset

This function:

  • Stops all running servers and clients.
  • Frees their memory.
  • Frees the shared address space.
  • Reset the handle counter.
  • Returns 0 on success, -1 on failure.

Reading and Writing

  • Servers can read and write their own address space.
  • Clients can read and write a remote server’s address space.
  • Therefore, Servers and clients use different functions to read/write data from the address space.

Server Components

Reading

  • The following functions read variables from the different types of registers and return them.
  • When a read error occurs, the functions will write [function name] + "ERROR" + [error code] in the Message Log.
Reading from Holding registers
Val = MB_SERVER_READ_REG_LONG([index], [byte_swap], [word_swap])
Val = MB_SERVER_READ_REG_SHORT([index], [byte_swap])
Val = MB_SERVER_READ_REG_FLOAT([index], [byte_swap], [word_swap])
Val = MB_SERVER_READ_REG_DOUBLE([index], [byte_swap], [word_swap], [long swap])
Reading from Bits registers
val = MB_SERVER_READ_BIT([index])
Reading from Input registers
Val = MB_SERVER_READ_INREG_LONG([index], [byte_swap], [word_swap])
Val = MB_SERVER_READ_INREG_SHORT([index], [byte_swap])
Val = MB_SERVER_READ_INREG_FLOAT([index], [byte_swap], [word_swap])
Val = MB_SERVER_READ_INREG_DOUBLE([index], [byte_swap], [word_swap], [long swap])
Reading from Input Bits registers
 val = MB_SERVER_READ_INBIT([index])
Valid Parameters
Parameter Valid Input
Index From 0 to the number of registers available.
Byte_swap 1 or 0 (True/False)
Word_swap 1 or 0 (True/False)
Long_swap 1 or 0 (True/False)

Writing

  • The following functions write data into the different types of registers.
  • When a write error occurs, the functions will write [function name] + "ERROR" + [error code] in the Message Log.
Writing to holding registers
Val = MB_SERVER_WRITE_REG_LONG([index],[new value],[byte swap], [word swap])
Val = MB_SERVER_WRITE_REG_SHORT([index],[new value],[byte swap])
Val = MB_SERVER_WRITE_REG_FLOAT([index],[new value],[byte swap], [word swap])
Val = MB_SERVER_WRITE_REG_DOUBLE([index],[new value],[byte swap], [word swap], [long swap])
Writing to Bits registers
val = MB_SERVER_WRITE_BIT([index],[new value])
Writing to Input registers
Val = MB_SERVER_WRITE_INREG_LONG([index],[new value],[byte swap], [word swap])
Val = MB_SERVER_WRITE_INREG_SHORT([index],[new value],[byte swap])
Val = MB_SERVER_WRITE_INREG_FLOAT([index],[new value],[byte swap], [word swap])
Val = MB_SERVER_WRITE_INREG_DOUBLE([index],[new value],[byte swap], [word swap], [long swap])
Writing to Input Bits registers
val = MB_SERVER_WRITE_INBIT([index],[value])
Valid Parameters
Parameter Valid Input
Index From 0 to the number of registers available.
New value The value to write, must be from the appropriate type.
Byte_swap 1 or 0 (True/False)
Word_swap 1 or 0 (True/False)
Long_swap 1 or 0 (True/False)

Error codes

Error Meaning
-1 Invalid index.
-2 Local server's address space isn't mapped yet.
-3 Failed to catch the register mutex.
-4 Failed to release the register mutex.

Client Components

Reading

Reading from Holding registers
Val = MB_CLIENT_READ_REG_LONG([handle],[deviceID],[addr],[dest ptr])
Val = MB_CLIENT_READ_REG_SHORT(…)
Val = MB_CLIENT_READ_REG_FLOAT(…)
Val = MB_CLIENT_READ_REG_DOUBLE(…)
Reading from Bits registers
val = MB_CLIENT_READ_BITS ([handle],[deviceID],[addr],[num of bits],[dest arr ptr])
Reading from Input registers
Val = MB_CLIENT_READ_INREG_LONG ([handle],[deviceID],[addr],[dest ptr]) 
Val = MB_CLIENT_READ_INREG_SHORT(…)
Val = MB_CLIENT_READ_INREG_FLOAT(…)
Val = MB_CLIENT_READ_INREG_DOUBLE(…)
Reading from Input Bits registers
val = MB_CLIENT_READ_INBITS ([handle],[deviceID],[addr],[num of bits],[dest arr ptr])

Writing

Writing to Holding registers
Val = MB_CLIENT_WRITE_REG_LONG([addr],[val ptr],[deviceID])
Val = MB_CLIENT_WRITE_REG_SHORT(…)
Val = MB_CLIENT_WRITE_REG_FLOAT(…)
Val = MB_CLIENT_WRITE_REG_DOUBLE(…)
Writing to Bits registers
val = MB_CLIENT_WRITE_BIT([addr],[val ptr],[deviceID])

Reading and Writing Summary

modbus;newAPI-readwriteSummary.jpg