en:software:qview:qview_6:qview_6:qcl_features:modbusmaster10

MODBUS MASTER

Name ModbusMaster
Version 1
Major release 0
Minor release 8
Title Unit for implement a Modbus® master communication with extended addressing.

1. DESCRIPTION

The unit implement a complete data exchange model for a Modbus master communication line. The main features are:

  • Usable with serial communication line (master) or with TCP/IP protocol (client).
  • Communication with several slaves (maximum 32) that can have inhomogeneous communication parameters.
  • Management of a process table to read and write data continuously.
  • Management of a parameter table with the possibility to perform complete read or write to or from a slave.
  • Internal state machine to clearly identify the operating status of the unit.
  • Message counters (processed successfully and error message).

2. STATE MACHINE

The large circles represent stable states. They are:

STOPPED: state where the unit does not perform any activity. It is also the initial state.

READY: state of full activity

ABORT: there is a serious error, the unit switches to the safe state and waits for a stop command. AbortCode provides an identification code of the reason that set that state.

The rectangles indicate transient states:

STARTING: state in which the unit checks all the settings data and if the values are within the limits opens the communication channel.

STOPPING: nothing do in this implementation.

ABORTING: nothing do in this implementation.

Baloons are commands that can be sent to change the state:

Prepare, commands the unit to switch into ready state. Prior to this command must be configured all the communication parameters.

Stop, commands the unit to switch into STOPPED state. The communication channel is closed if it was open.

3. OPERATION

The unit parameters are represented by the following blocks:

The following table shows the Modbus standard functions that are available.

Value Constant Description
1 READCOIL* Reads the ON/OFF status of discrete outputs (coils) in the slave.
3 READREG Reads the binary contents of holding registers in the slave.
4 READINREG Reads the binary contents of input registers in the slave.
5 FORCECOIL* Forces a single coil to either ON or OFF.
6 FORCEREG Presets a value into a single holding register.
15 FORCEMCOIL* Forces each coil in a sequence of coils to either ON or OFF.
16 FORCEMREG Presets values into a sequence of holding registers.

* These functions are currently selectable, but not yet fully developed.

It's a table that contains the communication parameters for each slave. You can enter the parameters for up to 32 slaves. Every column is a QCL global array with size 32.

For a serial communication line the table is:

SlaveId SlaveBitrate SlaveStopBits SlaveParity SlaveTimeout SlaveAddrOffset
row 1 2 38400 1 2 50 0
row 2 15 9600 2 0 200 1
row 32


For a TCPIP communication the table is:

SlaveId SlaveTcpAddr3 SlaveTcpAddr2 SlaveTcpAddr1 SlaveTcpAddr0 SlaveTcpChangeIpDly SlaveAddrOffset
row 1 1 192 168 0 20 100 0
row 2 1 192 168 0 21 200 1
row 32

SlaveId : It's the real ID of the Modbus protocol set in the slave.
SlaveBitrate : It's the baud rate (we support all values compatible with the device MODBUS).
SlaveStopBits : It's the stop bit (0,1,2).
SlaveParity : It's the parity (0 = NONE, 1 = ODD, 2 = EVEN).
SlaveTimeout : It's the maximum value of waiting for a response before reporting a timeout error.
SlaveAddrOffset : It's a value that is added to the address before sending the Modbus message. It's used for matching the numbering of the address used in the tables of this unit with the values shown in the documentation of the slave.
SlaveTcpAddr3 : It's the tcpip address position 3 [Highest] ⇒ 3.2.1.0
SlaveTcpAddr2 : It's the tcpip address position 2.
SlaveTcpAddr1 : It's the tcpip address position 1.
SlaveTcpAddr0 : It's the tcpip address position 0 [Lowest].
SlaveTcpChangeIpDly : It's a waiting time in milliseconds used at every tcpip address change [min. 1, default 500].

Once the SlaveId is entered into this table, it allows you to identify a slave with generic index which we will call from now on “Slave index” and which corresponds to the row of the table.

It's a configuration table for a communication of data process (usually called cyclic data). The process values are stored on an array (called ProcessValue) where each data element is located at a certain index value. The calculation of the index value for each data is done automatically by the unit based on the data of ProcessTable. The communication of process data can be enabled or disabled with the parameter ProcessEnable.
In order to optimize the occupation of the Modbus® channel, process table can use multiple messages. Also you can place in ProcessTable write command messages.
An example of the communication process can be a reading of the statusword inverter, writing of the motor speed, reading of the torque value of the motor, reading the temperature value by a temperature controller, etc..
The ProcessTable has a size of 100 rows that must be used for the process data exchange of all slaves; the array ProcessValue has a size of 300 elements. When the unit encounters a line with ProcessId equal to zero, it resumes scanning from beginning (row 1). To suspend temporarily a specific row communication, set ProcessId to a negative value.

ProcessTable

ProcessId ProcessAddr ProcessNum ProcessType ProcessOffset ProcessDevErr
row 1 1 100 2 3 1
row 2 2 100 3 3 3
row 100

Every column is a QCL global array.

ProcessValue

1 2 3 4 5 6 300
row 1 row 1 row 2 row 2 row 2

ProcessId : It's the slave index that indicates that you want to communicate with the slave whose parameters are represented by the row indicated by the value in SlaveTable.
ProcessAddr : It's the Modbus address.
ProcessNum : It's the number of elements (for multiple reading or writing).
ProcessType : It's the Modbus function type.
ProcessOffset : It's the ProcessValue array index where the values will start to be stored. This value is calculated automatically when you start the unit.
ProcessDevErr : It's the err parameter value of the device in the case of error communication.

It manages communication used to perform operations on slave configuration registers (call parameters). This table includes all the information needed to identify these parameters. It 'a single table for all slaves. This table can be included only the data manipulated by the message Modbus® 3 (read holding register) or 6 (force holding register). Are not possible communications using coils, inputs, inputs registers and multiple operations.

The size of this table is 200 rows.
To start communication with the Param table you must use the LowMailBox described below.

ParamId ParamAddr ParamNum ParamOptions ParamValue
row 1 1 200 1 0 11
row 2 2 201 1 0 22
row 200

ParamId : It's the slave index that indicates that you want to communicate with the slave whose parameters are represented by the line indicated by the value in SlaveTable.
ParamAddr : It's the Modbus address.
ParamNum : Normally set to 1, the value is set 2 to treat certain 32bit data which are composed of two words Modbus®.
ParamOptions : You can specify some details about communication (shown below).
ParamValue : It's the read value or the value to be written.

ParamOptions
The ParamOptions is used to set certain communication characteristics. It runs with the following bit masks:

Constant Bit Description
OPTION_SIZE 0 If true, it allows to perform writing parameter as a COIL.
FORCECOIL (5) instead of FORCEREG (6)
FORCEMCOIL (15) instead of FORCEMREG (16)
OPTION_MULTI 1 If true, it allows to perform writing parameters with size (num) 1 with Modbus multiple functions FORCEMCOIL (15) and FORCEMREG (16).
OPTION_ROUND 2 If true, it allows to tolerate differences of 1 unit during check parameters commands (the value in the slave can be less by one compared to the value in the table).
Some slaves execute internal roundings processing of numerical values received via Modbus.

It's a technique of traffic light system for communication between the various units. This unit includes two Mailbox, the HighMbox and LowMbox. This Mailboxes allows to various units of the Qview project to share Modbus® communication.
Here's an example:

Both HighMbox and LowMbox are an array of 38 elements, that will be explained subsequently.

In HighMbox[1] and LowMbox[1], there are states and commands to mailboxes:

Value Constant Desciption
0 MBOX_FREE Mailbox is free to be used.
1 MBOX_REPLY Mailbox reply.
2 MBOX_SINGLE_REQUEST Mailbox single request.
3 MBOX_PARAM_CHECK Mailbox command to check all parameters of a single slave.
Only for LowMbox.
4 MBOX_PARAM_CHECK_ALL Mailbox command to check all parameters of all slaves.
Only for LowMbox.
5 MBOX_PARAM_READ Mailbox command to read all parameters of a single slave.
Only for LowMbox.
6 MBOX_PARAM_WRITE Mailbox command to write all parameters of a single slave.
Only for LowMbox.

The variable LowMboxProgress is updated during LowMbox commands and takes values from 0 to 100 to indicate the progress of the operation. It can be used in hmi progressbar.


Now we explain all the activities that can be done with the mailboxes:

HighMbox[1] 0 → MBOX_FREE
1 → MBOX_REPLY
2 → MBOX_SINGLE_REQUEST
HighMbox[2..38] The meaning depends on the content of the element [1] in the following way:
HighMbox[1] = MBOX_REPLY HighMbox[1] = MBOX_SINGLE_REQUEST
HighMbox[2] slave index
HighMbox[3] address
HighMbox[4] type
HighMbox[5] num
HighMbox[6] return value
0 = OK
1 = error in communication
4 = error in opening or closing the COM port
5 = slave index out of range
6 = modbus type not valid
tout
(it can be put to zero, in which case it will use the value in the slave table SlaveTimeout. If this were zero then it uses a default value equal to 100 msec)
HighMbox[7..38] values of the registers (in the case of reading) values of the registers (in the case of writing)

This is a sample code for a read request:

WAIT MDBMAST1.HighMbox[1] EQ MDBMAST1.MBOX_FREE        ; wait for empty mailbox
MDBMAST1.HighMbox[2] = 1                               ; first slave in configuration table
MDBMAST1.HighMbox[3] = 100                             ; address
MDBMAST1.HighMbox[4] = MDBMAST1.READINREG              ; type
MDBMAST1.HighMbox[5] = 5                               ; num
MDBMAST1.HighMbox[6] = 0                               ; tout (use default)
MDBMAST1.HighMbox[1] = MDBMAST1.MBOX_SINGLE_REQUEST    ; start request
WAIT MDBMAST1.HighMbox[1] EQ MDBMAST1.MBOX_REPLY       ; wait for reply
IF MDBMAST1.HighMbox[6] EQ 0                           ; successfully ?
    Myvar = MDBMAST1.HighMbox[7]
ENDIF
MDBMAST1.HighMbox[1] = MDBMAST1.MBOX_FREE              ; mailbox is now free for other units

We can do the same function with LowMbox (the difference between High and Low will be explained subsequently).

LowMbox[1] 0 → MBOX_FREE
1 → MBOX_REPLY
2 → MBOX_SINGLE_REQUEST
LowMbox[2..38] The meaning depends on the content of the element [1] in the following way:
LowMbox[1] = MBOX_REPLY LowMbox[1] = MBOX_SINGLE_REQUEST
LowMbox[2] slave index
LowMbox[3] address
LowMbox[4] type
LowMbox[5] num
LowMbox[6] return value
0 = OK
1 = error in communication
4 = error in opening or closing the COM port
5 = slave index out of range
6 = modbus type not valid
tout
(it can be put to zero, in which case it will use the value in the slave table SlaveTimeout. If this were zero then it uses a default value equal to 100 msec)
LowMbox[7..38] values of the registers (in the case of reading) values of the registers (in the case of writing)

The function checks the parameters of a slave if they match with the values contained in ParamValue.

LowMbox[1] 0 → MBOX_FREE
1 → MBOX_REPLY
3 → MBOX_PARAM_CHECK
LowMbox[2..38] The meaning depends on the content of the element [1] in the following way:
LowMbox[1] = MBOX_REPLY LowMbox[1] = MBOX_PARAM_CHECK
LowMbox[2] slave index
LowMbox[6] return value
0 = OK
1 = error in communication
2 = error in parameter verification
3 = no parameter of selected slave found in the table
4 = error in opening or closing the COM port
5 = slave index out of range
tout
(it can be put to zero, in which case it will use the value in the slave table SlaveTimeout. If this were zero then it uses a default value equal to 100 msec)
LowMbox[7] In the case of LowMbox [6] = 2, is shown the address of the first parameter that has generated the error
LowMbox[8] In the case of LowMbox [6] = 2, is shown the value read from the slave of the parameter that caused the error
LowMbox[9] In the case of LowMbox [6] = 2, is shown the value in table of the parameter that caused the error

The function checks the parameters of all slaves if they match with the values contained in ParamValue.

LowMbox[1] 0 → MBOX_FREE
1 → MBOX_REPLY
4 → MBOX_PARAM_CHECK_ALL
LowMbox[2..38] The meaning depends on the content of the element [1] in the following way:
LowMbox[1] = MBOX_REPLY LowMbox[1] = MBOX_PARAM_CHECK_ALL
LowMbox[2] slave index
LowMbox[6] return value
0 = OK
1 = error in communication
2 = error in parameter verification
3 = no parameter of selected slave found in the table
4 = error in opening or closing the COM port
5 = slave index out of range
tout
(it can be put to zero, in which case it will use the value in the slave table SlaveTimeout. If this were zero then it uses a default value equal to 100 msec)
LowMbox[7] In the case of LowMbox [6] = 2, is shown the address of the first parameter that has generated the error
LowMbox[8] In the case of LowMbox [6] = 2, is shown the value read from the slave of the parameter that caused the error
LowMbox[9] In the case of LowMbox [6] = 2, is shown the value in table of the parameter that caused the error
LowMbox[10] In the case of LowMbox [6] = 2, is shown the slave index of the parameter that caused the error

The function reads the parameters of a slave and stores them in ParamValue.

LowMbox[1] 0 → MBOX_FREE
1 → MBOX_REPLY
5 → MBOX_PARAM_READ
LowMbox[2..38] The meaning depends on the content of the element [1] in the following way:
LowMbox[1] = MBOX_REPLY LowMbox[1] = MBOX_PARAM_READ
LowMbox[2] slave index
LowMbox[6] return value
0 = OK
1 = error in communication
3 = no parameter of selected slave found in the table
4 = error in opening or closing the COM port
5 = slave index out of range
tout
(it can be put to zero, in which case it will use the value in the slave table SlaveTimeout. If this were zero then it uses a default value equal to 100 msec)
LowMbox[7] In the case of LowMbox [6] = 1, is shown the address of the parameter that caused the error in communication
LowMbox[8] In the case of LowMbox [6] = 1, is shown the last word read by the device MODBUS
LowMbox[9] In the case of LowMbox [6] = 1, is shown the error code of the device MODBUS

The function writes the parameters of a slave with the values stored in ParamValue.

LowMbox[1] 0 → MBOX_FREE
1 → MBOX_REPLY
6 → MBOX_PARAM_WRITE
LowMbox[2..38] The meaning depends on the content of the element [1] in the following way:
LowMbox[1] = MBOX_REPLY LowMbox[1] = MBOX_PARAM_WRITE
LowMbox[2] slave index
LowMbox[6] return value
0 = OK
1 = error in communication
3 = no parameter of selected slave found in the table
4 = error in opening or closing the COM port
5 = slave index out of range
tout
(it can be put to zero, in which case it will use the value in the slave table SlaveTimeout. If this were zero then it uses a default value equal to 100 msec)
LowMbox[7] In the case of LowMbox [6] = 1, is shown the address of the parameter that caused the error in communication
LowMbox[8] In the case of LowMbox [6] = 1, is shown the last word written by the device MODBUS
LowMbox[9] In the case of LowMbox [6] = 1, is shown the error code of the device MODBUS

The difference between HighMbox and LowMbox is that he HighMbox has the possibility of entering during a multiple request commanded on LowMbox, in order to have always the possibility of fast action on variables of high priority.

Let's see how the priority of requests are menaged. Denote by:
P = request regarding the ProcessTable
H = request regarding the HighMbox
L = request regarding the LowMbox

  1. With process active, it is required a high priority reading:

    The request is immediately inserted between each ProcessData request.

  2. The LowMbox requests are inserted alternating with the ProcessData so the unit meets alternately one row of the ProcessTable and a row of the ParamTable (in the example it is assumed that the LowMbox requests an operation of read parameters of a slave, via the command LowMbox [1] = MBOX_PARAM_READ):


  3. In the last example with the ProcessData active, a write parameters operation is requested, via the command LowMbox [1] = MBOX_PARAM_WRITE), and at the same time it is required a high priority reading:

4. PUBLIC SYMBOLS

Below there are some tables with an explanation of the public symbols.

Name Type Size Access Type Description
Prepare GLOBAL F IN Command to set STARTING state, after all configuration tables were compiled.
Stop GLOBAL F INOUT Command to set STOPPING state.
ProcessEnable GLOBAL F INOUT Enable for process requests.
ProcessErrReset GLOBAL F INOUT Command to reset all the errors of ProcessTable.
StatReset GLOBAL F INOUT Command to reset all the values concerning statistics.
HighMbox[1]
LowMbox[1]
ARRGBL W INOUT Commands to mailboxes :
(2) MBOX_SINGLE_REQUEST
(3) MBOX_PARAM_CHECK
(4) MBOX_PARAM_CHECK_ALL
(5) MBOX_PARAM_READ
(6) MBOX_PARAM_WRITE

Commands 3,4,5,6 are available only for LowMbox.
It should be set to (0) MBOX_FREE when a request is completed.
HighMbox[2]
LowMbox[2]
ARRGBL W INOUT Slave index.
HighMbox[3]
LowMbox[3]
ARRGBL W INOUT Modbus address (only for MBOX_SINGLE_REQUEST).
HighMbox[4]
LowMbox[4]
ARRGBL W INOUT Modbus function (only for MBOX_SINGLE_REQUEST).
1, 3, 4, 5, 6, 15, 16
HighMbox[5]
LowMbox[5]
ARRGBL W INOUT Modbus elements number (only for MBOX_SINGLE_REQUEST).
HighMbox[6]
LowMbox[6]
ARRGBL W INOUT Timeout modbus reply.
HighMbox[7..38]
LowMbox[7..38]
ARRGBL W INOUT Data area (in MBOX_SINGLE_REQUEST).
Name Type Size Access Type Description
State GLOBAL B OUT Actual state. The values can be STOPPED (0), STARTING (1), READY (2), ABORTING (3), ABORTED (4), STOPPING (5)
ProcessError GLOBAL F OUT Modbus error during a request of process loop; it remains active until it is set to 0 by the command ProcessErrReset.
LowMboxProgress GLOBAL B OUT Rate of progression in parameters LowMbox functions.
HighMbox[1]
LowMbox[1]
ARRGBL W INOUT Mailboxes states.
(0) MBOX_FREE
(1) MBOX_REPLAY
(2..6) active request
HighMbox[6]
LowMbox[6]
ARRGBL W INOUT Return value.
0 = OK
1 = error in communication
2 = error in parameter verification
3 = no parameter of selected slave found in the table
4 = error in opening or closing the COM port
HighMbox[7..38]
LowMbox[7..38]
ARRGBL W INOUT Data area in requests without errors (in MBOX_SINGLE_REQUEST).
LowMbox[7] ARRGBL W INOUT MBOX_SINGLE_REQUEST → not used

MBOX_PARAM_CHECK and MBOX_PARAM_CHECK_ALL
In the case of LowMbox [6] = 2, is shown the address of the first parameter that has generated the error.

MBOX_PARAM_READ and MBOX_PARAM_WRITE
In the case of LowMbox [6] = 1, is shown the address of the parameter that caused the error in communication.
LowMbox[8] ARRGBL W INOUT MBOX_SINGLE_REQUEST → not used

MBOX_PARAM_CHECK and MBOX_PARAM_CHECK_ALL
In the case of LowMbox [6] = 2, is shown the value read from the slave of the parameter that caused the error.

MBOX_PARAM_READ and MBOX_PARAM_WRITE
In the case of LowMbox [6] = 1, is shown the last word read or written by the device MODBUS.
LowMbox[9] ARRGBL W INOUT MBOX_SINGLE_REQUEST → not used

MBOX_PARAM_CHECK and MBOX_PARAM_CHECK_ALL
In the case of LowMbox [6] = 2, is shown the value in table of the parameter that caused the error.

MBOX_PARAM_READ and MBOX_PARAM_WRITE
In the case of LowMbox [6] = 1, is shown the error code of the device MODBUS.
LowMbox[10] ARRGBL W INOUT MBOX_SINGLE_REQUEST, MBOX_PARAM_CHECK, MBOX_PARAM_READ and MBOX_PARAM_WRITE → not used

MBOX_PARAM_CHECK_ALL
In the case of LowMbox [6] = 2, is shown the slave index of the parameter that caused the error.
Statistics
TotalStatCommOk GLOBAL L OUT Counter all requests completed without errors.
TotalStatAttempt GLOBAL L OUT Counter all attempts performed in completed requests without errors.
TotalStatCommKo GLOBAL L OUT Counter all requests not completed for exceeding the maximum number of attempts.
TotalStatWrong GLOBAL L OUT Counter all requests not completed for a Modbus request error.
UpdateProcessTime GLOBAL L OUT Current update time of all process table.
Stat table
StatCommOk ARRGBL L OUT Counter of requests completed without error for each Modbus node.
StatAttempt ARRGBL L OUT Counter all attempts performed in completed requests without errors for each Modbus node.
StatCommKo ARRGBL L OUT Counter all requests not completed for exceeding the maximum number of attempts for each Modbus node.
StatWrong ARRGBL L OUT Counter all requests not completed for a Modbus request error for each Modbus node.
StatMaxReplyTime ARRGBL W OUT Maximum time (msec) for requests completed without attempts for each Modbus node.
Name Type Size Access Type Description
Protocol GLOBAL B IN Device MODBUS protocol selection.
(0) = DEVICE_PROT_ASCII
(1) = DEVICE_PROT_RTU
(2) = DEVICE_PROT_TCPIP)
TcpIpPort GLOBAL W INOUT TCPIP communication port. Used only with Protocol = DEVICE_PROT_TCPIP, defines the communication port for messages.
If this parameter is left to zero, the unit uses the default value of the Modbus protocol (502).
MaxAttempts GLOBAL B INOUT Maximum number of attempts.
RelaxTime GLOBAL L INOUT Waiting time (msec) between an attempt and another (default = 200)
Slave table
SlaveId ARRGBL W INOUT The real ID of the Modbus protocol set in the slave.
SlaveBitrate ARRGBL L INOUT The baud rate (we support all values compatible with the device MODBUS).
SlaveStopBits ARRGBL B INOUT The stop bit (0,1,2).
SlaveParity ARRGBL B INOUT The parity (0 = NONE, 1 = ODD, 2 = EVEN).
SlaveTimeout ARRGBL W INOUT The maximum value of waiting for a response before reporting a timeout error.
SlaveAddrOffset ARRGBL B INOUT A value that is added to the address before sending the Modbus message. It's used for matching the numbering of the address used in the tables of this unit with the values shown in the documentation of the slave.
SlaveTcpAddr3 ARRGBL W INOUT Tcpip address position 3 [Highest] ⇒ 3.2.1.0
SlaveTcpAddr2 ARRGBL W INOUT Tcpip address position 2.
SlaveTcpAddr1 ARRGBL W INOUT Tcpip address position 1.
SlaveTcpAddr0 ARRGBL W INOUT Tcpip address position 0 [Lowest].
SlaveTcpChangeIpDly ARRGBL L INOUT A waiting time in milliseconds when the new request is for another tcpip slave [min. 1, default 500].
Param table
ParamId ARRGBL W INOUT The slave index that indicates that you want to communicate with the slave whose parameters are represented by the line indicated by the value in SlaveTable.
ParamAddr ARRGBL W INOUT The Modbus address.
ParamNum ARRGBL W INOUT Normally set to 1, the value is set 2 to treat certain 32bit data which are composed of two words Modbus®.
ParamOptions ARRGBL B INOUT You can specify some details about communication (shown in relative chapter).
ParamValue ARRGBL L INOUT The value read or the value to be written.
Process table
ProcessId ARRGBL W INOUT The slave index that indicates that you want to communicate with the slave whose parameters are represented by the line indicated by the value in SlaveTable.
ProcessAddr ARRGBL W INOUT The Modbus address.
ProcessNum ARRGBL W INOUT The number of elements (for multiple reading or writing).
ProcessType ARRGBL W INOUT The Modbus function type.
ProcessOffset ARRGBL W INOUT The ProcessValue array index where the values will start to be stored. This value is calculated automatically when you start the unit.
ProcessDevErr ARRGBL B OUT The err parameter value of the device in the case of error communication.
ProcessValue ARRGBL L INOUT In this area is stored the value read or to be written.
Name Value Description
States
STOPPED 0 State where the unit does not perform any activity. It is also the initial state.
STARTING 1 State in which the unit checks all the settings data and if the values are within the limits opens the communication channel.
READY 2 State of full activity.
ABORTING 3 Nothing do in this implementation.
ABORTED 4 There is a serious error, the unit switches to the safe state and waits for a stop command. AbortCode provides an identification code of the reason that set that state.
STOPPING 5 Nothing do in this implementation.
Modbus protocol
DEVICE_PROT_ASCII 0 MODBUS ASCII protocol.
DEVICE_PROT_RTU 1 MODBUS RTU protocol.
DEVICE_PROT_TCPIP 2 MODBUS TCPIP protocol.
Modbus functions types
READCOIL 1 Reads the ON/OFF status of discrete outputs (coils) in the slave.
READREG 3 Reads the binary contents of holding registers in the slave.
READINREG 4 Reads the binary contents of input registers in the slave.
FORCECOIL 5 Forces a single coil to either ON or OFF.
FORCEREG 6 Presets a value into a single holding register.
FORCEMCOIL 15 Forces each coil in a sequence of coils to either ON or OFF.
FORCEMREG 16 Presets values into a sequence of holding registers.
Param table request options
OPTION_SIZE &H01 If checked, it allows you to perform writing parameter as a COIL.
FORCECOIL (5) instead of FORCEREG (6)
FORCEMCOIL (15) instead of FORCEMREG (16)
OPTION_MULTI &H02 If checked, it allows you to perform writing parameters with size (num) 1 with Modbus multiple functions FORCEMCOIL (15) and FORCEMREG (16).
OPTION_ROUND &H04 If this option is set, it allows to tolerate during the commands of check parameters differences of 1 unit (the value in the slave can be less by one unit spite the value in the table).
It has been seen that some slaves execute internal roundings processing of numerical values received via Modbus for which a value previously written does not match the value reread.
Mailboxes states and commands
MBOX_FREE 0 Mailbox is free to be used.
MBOX_REPLY 1 Mailbox reply.
MBOX_SINGLE_REQUEST 2 Mailbox single request.
MBOX_PARAM_CHECK 3 Mailbox command to check all parameters of a single slave.
Only for LowMbox.
MBOX_PARAM_CHECK_ALL 4 Mailbox command to check all parameters of all slaves.
Only for LowMbox.
MBOX_PARAM_READ 5 Mailbox command to read all parameters of a single slave.
Only for LowMbox.
MBOX_PARAM_WRITE 6 Mailbox command to write all parameters of a single slave.
Only for LowMbox.

5. EXAMPLES OF USE

To better understand the operation of this unit, we explain a real case.

The qmove controller must communicate with two servo drives. The connection media is a serial cable.

We want the processTable that continuously read/write the following parameters:

  • Read the current speed of the drive No. 1
  • Write the set speed of the drive No. 1
  • Read the actual current of the drive No. 1
  • Read the current speed of the drive No. 2
  • Write the set speed of the drive No. 2
  • Read the actual current of the drive No. 2

We also want to manage the parameters nr.1070, 1071 of the drive 1 and 2. When you powerup the controller may be useful to verify the parameters value. If qmove control change values than may be useful to write new values to drives.

Acyclic (for example every 10 seconds) we want to read the temperatures of the engine reading registers from 00A4 to 00A7 (with lowMbox).

Lastly, we want to perform a high priority write to disable the drive in case of emergency. The writing will be done using register 0474 (with highmbox).

  1. Create a new project with QView-6
  2. Add a unit type configuration. Edit BUS section according with your product name. In the section INTDEVICE insert the declaration of a device MOSBUS:
    INTDEVICE 
        MdbDevice  MODBUS  0008  1

    Pay attention to the last field number of the declaration (1) that is used to select the communication port. Usually it is 0 for PROG port, 1 for USER port, 2 for aux1, 3 for aux2 port and 43 for ethernet port (modbus tcpip). Check hardware manual for assurance.

  3. In the REFERENCES section (always in the unit configuration) add the following code:
    REFERENCES
        MDBMAST1.modbus = MdbDevice
  4. Add a unit QCL with a name (for example, MAIN).
  5. Add to the project the QCL Feature unit ModbusMaster10 and name MDBMAST1
  6. Proceed on the task init of MAIN unit with the protocol setting and slaves setting:
        MDBMAST1.Protocol = MDBMAST1.DEVICE_PROT_RTU    ; modbus rtu
     
        ; setting unit ModbusMaster10 slave table    
        ; node 1
        MDBMAST1.SlaveId[1] 	= 1     
        MDBMAST1.SlaveBitrate[1]    = 9600
        MDBMAST1.SlaveStopBits[1]   = 1
        MDBMAST1.SlaveParity[1]     = 0
        MDBMAST1.SlaveTimeout[1]    = 200
        MDBMAST1.SlaveAddrOffset[1] = 0
        ; node 2
        MDBMAST1.SlaveId[2] 	= 3     
        MDBMAST1.SlaveBitrate[2]    = 57600
        MDBMAST1.SlaveStopBits[2]   = 2
        MDBMAST1.SlaveParity[2]     = 1
        MDBMAST1.SlaveTimeout[2]    = 100
        MDBMAST1.SlaveAddrOffset[2] = 1

    Our network is RTU and consists of 2 drives, one with id 1 and the other with id 3, with different communication settings.

  7. Simple process values for the two drives can be the current speed and the set speed. We add these two values also a value of the drive that can identify a working state (stopped, moving, alarm, etc.). Then set the process table:
        ; setting unit ModbusMaster10 process table
        ; read current speed of slave index 1
        MDBMAST1.ProcessId[1]   = 1                      ; slave index (in slave table)
        MDBMAST1.ProcessAddr[1] = &H102B                 ; exadecimal address value
        MDBMAST1.ProcessNum[1]  = 1                      ; number of elements
        MDBMAST1.ProcessType[1] = MDBMAST1.READINREG     ; type of modbus request
        ; write set speed of slave index 1
        MDBMAST1.ProcessId[2]   = 1
        MDBMAST1.ProcessAddr[2] = &H0060
        MDBMAST1.ProcessNum[2]  = 1
        MDBMAST1.ProcessType[2] = MDBMAST1.FORCEREG
        ; read current state of slave index 1
        MDBMAST1.ProcessId[3]   = 1
        MDBMAST1.ProcessAddr[3] = &H00A8
        MDBMAST1.ProcessNum[3]  = 1
        MDBMAST1.ProcessType[3] = MDBMAST1.READINREG
        ; read current speed of slave index 2
        MDBMAST1.ProcessId[4]   = 2
        MDBMAST1.ProcessAddr[4] = &H102B
        MDBMAST1.ProcessNum[4]  = 1
        MDBMAST1.ProcessType[4] = MDBMAST1.READINREG
        ; write set speed of slave index 2
        MDBMAST1.ProcessId[5]   = 2
        MDBMAST1.ProcessAddr[5] = &H0060
        MDBMAST1.ProcessNum[5]  = 1
        MDBMAST1.ProcessType[5] = MDBMAST1.FORCEREG
        ; read current state of slave index 2
        MDBMAST1.ProcessId[6]   = 2
        MDBMAST1.ProcessAddr[6] = &H00A8
        MDBMAST1.ProcessNum[6]  = 1
        MDBMAST1.ProcessType[6] = MDBMAST1.READINREG
  8. We also want to use the features of the mailbox to manage a short list of parameters. Then set the param table:
        ; setting unit ModbusMaster10 param table
        ; first parameter of the list (slave index 1)
        MDBMAST1.ParamId[1]      = 1                      ; slave index (in slave table)
        MDBMAST1.ParamAddr[1]    = &H1070                 ; exadecimal address value
        MDBMAST1.ParamNum[1]     = 1                      ; number of elements (maximum 2, to manage double word parameters)
        MDBMAST1.ParamOptions[1] = MDBMAST1.OPTION_MULTI  ; parameter option (use multiple modbus write function)
        ; second parameter of the list (slave index 1)
        MDBMAST1.ParamId[2]      = 1
        MDBMAST1.ParamAddr[2]    = &H1071
        MDBMAST1.ParamNum[2]     = 1
        MDBMAST1.ParamOptions[2] = 0
        ; third parameter of the list (slave index 2)
        MDBMAST1.ParamId[3]      = 2
        MDBMAST1.ParamAddr[3]    = &H1070
        MDBMAST1.ParamNum[3]     = 1
        MDBMAST1.ParamOptions[3] = MDBMAST1.OPTION_MULTI
        ; fourth parameter of the list (slave index 2)
        MDBMAST1.ParamId[4]      = 1
        MDBMAST1.ParamAddr[4]    = &H1071
        MDBMAST1.ParamNum[4]     = 1
        MDBMAST1.ParamOptions[4] = 0
  1. After these configuration settings, prepare the feature unit to work:
        ; execute unit command Prepare
        MDBMAST1.Prepare = 1
        WAIT (MDBMAST1.State EQ MDBMAST1.READY) OR (MDBMAST1.State EQ MDBMAST1.ABORTED)
        IF MDBMAST1.State EQ MDBMAST1.ABORTED
            MDBMAST1.Stop = 1                    ; in case of error return to STOPPED state
            ...                                  ; insert the code to notify the error
        ELSE
            MDBMAST1.ProcessEnable = 1           ; process requests can start
        ENDIF

To manage the process values, use the array ProcessValue:

Drive1Vel = MDBMAST1.ProcessValue[MDBMAST1.ProcessOffset[1]]       ; reading current speed
MDBMAST1.ProcessValue[MDBMAST1.ProcessOffset[2]] = Drive1SetVel    ; writing set speed
Drive1State = MDBMAST1.ProcessValue[MDBMAST1.ProcessOffset[3]]     ; reading current state
 
Drive2Vel = MDBMAST1.ProcessValue[MDBMAST1.ProcessOffset[4]]
MDBMAST1.ProcessValue[MDBMAST1.ProcessOffset[5]] = Drive2SetVel
Drive2State = MDBMAST1.ProcessValue[MDBMAST1.ProcessOffset[6]]

ProcessOffset automatically calculates the position of the process element on the array.

In our example, we imagine to use the ParamTable once the drives are fully configured and ready to use. We decide the parameters that we could modify through our application. At this point at least the first time we go to read these parameters, and we have to save them in our retentive area.

The next code example shows how to read all parameters from second drive:

WAIT MDBMAST1.LowMbox[1] EQ MDBMAST1.MBOX_FREE     ; wait until the mailbox is free
MDBMAST1.LowMbox[2] = 2                            ; select slave index 2
MDBMAST1.LowMbox[1] = MDBMAST1.MBOX_PARAM_READ     ; read parameters function
WAIT MDBMAST1.LowMbox[1] EQ MDBMAST1.MBOX_REPLY    ; wait until the function ends and replies
IF MDBMAST1.LowMbox[6] EQ 0
    ...                                            ; read parameters successfully (message, change page, etc.)
    slDrive2Par1 = MDBMAST1.ParamValue[3]          ; store the read value on ritentive variable
    slDrive2Par2 = MDBMAST1.ParamValue[4]
ELSE
    ...                                            ; insert the code to menage errors
ENDIF
MDBMAST1.LowMbox[1] = MDBMAST1.MBOX_FREE           ; release mailbox

Normally at power, when you enable the connection of a Modbus network drives it is sometimes useful to analyze whether the parameters in the memory are aligned with those on the drives. To do this, we can use the corresponding commands of the mailbox:

MDBMAST1.ParamValue[1] = slDrive1Par1              ; load ritentive value on ParamValue array
MDBMAST1.ParamValue[2] = slDrive1Par2
 
WAIT MDBMAST1.LowMbox[1] EQ MDBMAST1.MBOX_FREE     ; wait until the mailbox is free
MDBMAST1.LowMbox[2] = 1                            ; select slave index
MDBMAST1.LowMbox[1] = MDBMAST1.MBOX_PARAM_CHECK    ; check parameters function
WAIT MDBMAST1.LowMbox[1] EQ MDBMAST1.MBOX_REPLY    ; wait until the function ends and replies
IF MDBMAST1.LowMbox[6] EQ 0
    ...                                            ; check parameters successfully (message, change page, etc.)
ELSE
    ...                                            ; insert the code to menage errors
ENDIF
MDBMAST1.LowMbox[1] = MDBMAST1.MBOX_FREE           ; release mailbox

You can also use the function MBOX_PARAM_CHECK_ALL to check all parameters of all slaves with a single command.

Finally, we use the write command to set the parameters on the first and on the second drive:

WAIT MDBMAST1.LowMbox[1] EQ MDBMAST1.MBOX_FREE     ; wait until the mailbox is free
 
MDBMAST1.ParamValue[1] = slDrive1Par1              ; load ritentive value on ParamValue array
MDBMAST1.ParamValue[2] = slDrive1Par2
MDBMAST1.ParamValue[3] = slDrive2Par1
MDBMAST1.ParamValue[4] = slDrive2Par2
 
MDBMAST1.LowMbox[2] = 1                            ; select slave index 1
MDBMAST1.LowMbox[1] = MDBMAST1.MBOX_PARAM_WRITE    ; write parameters function
WAIT MDBMAST1.LowMbox[1] EQ MDBMAST1.MBOX_REPLY    ; wait until the function ends and replies
IF MDBMAST1.LowMbox[6] EQ 0
    ...                                            ; write parameters successfully (message, change page, etc.)
ELSE
    ...                                            ; insert the code to menage errors
ENDIF
 
MDBMAST1.LowMbox[2] = 2                            ; select slave index 2
MDBMAST1.LowMbox[1] = MDBMAST1.MBOX_PARAM_WRITE    ; write parameters function
WAIT MDBMAST1.LowMbox[1] EQ MDBMAST1.MBOX_REPLY    ; wait until the function ends and replies
IF MDBMAST1.LowMbox[6] EQ 0
    ...                                            ; write parameters successfully (message, change page, etc.)
ELSE
    ...                                            ; insert the code to menage errors
ENDIF
 
MDBMAST1.LowMbox[1] = MDBMAST1.MBOX_FREE           ; release mailbox

Some parameters cannot be written in certain drive states.
See the drive documentation.

In our example, each unit of a project has the possibility of using single requests for information, to set reference values, or force states of the drives. For these applications we offer 2 mailbox. Why 2 mailbox?

Basically to have two priorities for intervention.

If we use the HighMbox (high priority), we are going to intervene immediately after the current request, which is a read/write process, which is a request to check/read/write parameters, or other demands on LowMbox (low priority) from other units.
This feature was implemented considering the fact that some information must travel as quickly as possible, in our case we can say that in the event of an alarm condition must intervene immediately disabling drives.

Instead, the single requests on LowMbox are used for information that can wait for a while to be completed.

UNIT 1 - low priority request
For example, read some temperatures.

WAIT MDBMAST1.LowMbox[1] EQ MDBMAST1.MBOX_FREE     ; wait until the mailbox is free
MDBMAST1.LowMbox[2] = 1                            ; select slave index
MDBMAST1.LowMbox[3] = &H00A4                       ; address (&H = hexadecimal)
MDBMAST1.LowMbox[4] = MDBMAST1.READREG             ; read holding register modbus function
MDBMAST1.LowMbox[5] = 4                            ; number of elements (read from &H00A4 to &H00A7)
MDBMAST1.LowMbox[1] = MDBMAST1.MBOX_SINGLE_REQUEST ; single request function
WAIT MDBMAST1.LowMbox[1] EQ MDBMAST1.MBOX_REPLY    ; wait until the function ends and replies
IF MDBMAST1.LowMbox[6] EQ 0
    temperature[1] = MDBMAST1.LowMbox[7]           ; store the read values on array
    temperature[2] = MDBMAST1.LowMbox[8]
    temperature[3] = MDBMAST1.LowMbox[9]
    temperature[4] = MDBMAST1.LowMbox[10]
ELSE
    ...                                            ; insert the code to menage errors
ENDIF
MDBMAST1.LowMbox[1] = MDBMAST1.MBOX_FREE           ; release mailbox

UNIT 2 - high priority request
For example, disable drive for an alarm condition.

IF Alarm
    WAIT MDBMAST1.HighMbox[1] EQ MDBMAST1.MBOX_FREE       ; wait until the mailbox is free
    MDBMAST1.HighMbox[2] = 2                              ; select slave index
    MDBMAST1.HighMbox[3] = &H0009                         ; address (&H = hexadecimal)
    MDBMAST1.HighMbox[4] = MDBMAST1.FORCEREG              ; write holding register modbus function
    MDBMAST1.HighMbox[5] = 1                              ; number of elements
    MDBMAST1.HighMbox[7] = &0474                          ; example value in state register to disable drive    
    MDBMAST1.HighMbox[1] = MDBMAST1.MBOX_SINGLE_REQUEST   ; single request function
    WAIT MDBMAST1.HighMbox[1] EQ MDBMAST1.MBOX_REPLY      ; wait until the function ends and replies
    IF MDBMAST1.HighMbox[6] EQ 0
        NOP                                               ; not operation
    ELSE
        ...                                               ; insert the code to menage errors
    ENDIF
ENDIF

UNIT 3 - low priority request
For example, write a new setpoint on drive.

WAIT MDBMAST1.LowMbox[1] EQ MDBMAST1.MBOX_FREE     ; wait until the mailbox is free
MDBMAST1.LowMbox[2] = 1                            ; select slave index
MDBMAST1.LowMbox[3] = &H88AF                       ; address (&H = hexadecimal)
MDBMAST1.LowMbox[4] = MDBMAST1.FORCEREG            ; write holding register modbus function
MDBMAST1.LowMbox[5] = 1                            ; number of elements
MDBMAST1.LowMbox[7] = 5600                         ; new setpoint value
MDBMAST1.LowMbox[1] = MDBMAST1.MBOX_SINGLE_REQUEST ; single request function
WAIT MDBMAST1.LowMbox[1] EQ MDBMAST1.MBOX_REPLY    ; wait until the function ends and replies
IF MDBMAST1.LowMbox[6] EQ 0
    NOP                                            ; not operation
ELSE
    ...                                            ; insert the code to menage errors
ENDIF
MDBMAST1.LowMbox[1] = MDBMAST1.MBOX_FREE           ; release mailbox

6. LIMITATIONS

  • The unit currently handles only Modbus messages type 3 (holding register read), 4 (read input register), 6 (force register) , 16 (force multiple registers). It does not handle modbus messages 1 (read coil) , 5 (force coil), 15 (force multiple coils). These functions are currently selectable, but not yet fully developed.
  • It's not possible to configure slaves RTU and TCPIP with the same master. And in that case you need to enter 2 device MODBUS and 2 ModbusMaster10 and divide the network, one for serial slaves and one for tcpip slaves.
  • The maximum number of configurable slaves is fixed at 32.
  • The maximum number of configurable parameters in Param table is fixed at 200.
  • The maximum number of configurable process requests in Process table is fixed at 100.
  • The maximum number of configurable process values in ProcessValue array is fixed at 300.
  • The maximum number of registers readable or writable with a single message is fixed at 32.
  • Mailbox requests relative to parameters, can read/write only one parameter at time (not multiple elements).
  • Not all qmove product supports baud rate of 115200 baudrate. Check product documentation.

7. NOTES

  • For a good use of the unit, it is good to remember to always wait for the mailbox is free before using it, and remember, once you have completed the request, to make it free so that they can be met other requests.
    WAIT MDBMAST1.LowMbox[1] EQ MDBMAST1.MBOX_FREE    ; wait until the mailbox is free
    ...                                               ; request
    MDBMAST1.LowMbox[1] = MDBMAST1.MBOX_FREE          ; at the end release the mailbox

8. CHANGE LOG

QCL feature release Description Note Date
1.0.8 - Add constants for mailbox status and commands
- Public constants for modbus protocol
- Minor bugs fix
- Add new example projects
23/09/2015

9. DOWNLOAD

Click here to download unit and examples.

Zip contents:

File and folder name Description
MDBMAST1.UNT Qcl feature file
MODBUS_MASTER_SERIAL_EXAMPLE Example for serial communication
MODBUS_MASTER_TCPIP_EXAMPLE Example for client TCPIP communication
  • Last modified: 2019/08/29 17:01