Librer铆a Modbus RTU Master para automatizaci贸n industrial
Learn what Modbus RTU is and its applications
18 marzo, 2020 por
Librer铆a Modbus RTU Master para automatizaci贸n industrial
Boot & Work Corp. S.L., Fernandez Queralt Martinez



Introducci贸n de Librer铆a Modbus RTU Master para automatizaci贸n industrial

Introducci贸n


En el 谩rea de automatizaci贸n de Arduino, el protocolo Modbus RTU es un medio de comunicaci贸n que permite el intercambio de datos entre controladores l贸gicos programables (controlador PLC Arduino) y computadoras.

Los dispositivos electr贸nicos pueden intercambiar informaci贸n a trav茅s de l铆neas en serie utilizando el protocolo Modbus.

In this blog, you are going to learn how Modbus RTU works!

Index

1- What is Modbus RTU?

2- How does Modbus RTU work?

3- Modbus general frame structure

4-聽Modbus Function Code

5- Modbus Object Types

6- Modbus Data Format

聽 聽 6.1- 01 (0x01) Read Coils聽

聽 聽 6.2- 02 (0x02) Read discrete inputs

聽 聽 6.3- 03 (0x03) Read Holding Registers

聽 聽 6.4- 04 (0x04) Read Input Register

聽 聽 6.5- 05 (0x05) Write Single Coil

聽 聽 6.6- 06 (0x06) Write Single Register

聽 聽 6.7- 15 (0x0F) Write Multiple Coils

聽 聽 6.8- 16 (0x10) Write Multiple Holding Register聽聽聽聽

7- Creating our Modbus RTU message

8- Software

1- What is Modbus RTU?

Modbus is a communication protocol located at levels 1, 2 and 7 of the OSI Model, based on the master/slave architecture, designed in 1979 by Modicon for its range of PLCs.

Converted into a de facto standard communications protocol in the industry, let鈥檚 see some of the main features:

  1. Designed with its use in industrial applications in mind

  2. It is public and free

  3. It is easy to implement and requires little development.

  4. Handles blocks of data without assuming restrictions

  5. Each of the messages includes redundant information that ensures its integrity at reception.

  6. The basic Modbus commands allow you to control an RTU device to modify the value of any of its registers or to request the content of these registers.

2-聽How does MODBUS RTU work?

Modbus RTU is the most common implementation available for Modbus.

Modbus RTU is used in serial communication and makes use of a compact, binary representation of the data for protocol communication.

Modbus messages are divided by idle periods as you can see in the picture below.

Odoo 鈥 Image and Text

Cada dispositivo en una comunicaci贸n Modbus tiene una direcci贸n 煤nica.聽

El Modbus RTU funciona mediante RS-485, que es una red multipunto de un solo cable, solo el nodo asignado como maestro puede iniciar un comando. Todos los dem谩s dispositivos son esclavos y responden a solicitudes y comandos.

A Modbus command contains the Modbus address of the device it is intended for. Only the addressed device will respond and act on the command, even though other devices might receive it.

Also, it is important to say that all Modbus commands contain checksum information to allow the recipient to detect transmission errors.

Let's give an example! Imagine that we have a Modbus serial network, where there is a master and up to 31 slaves, each with a unique slave address.

The master only wants to send a message to slave number 2 requesting the value of 6 input registers.

So, the master would send a message and all the slaves would receive the message, but only the slave number 2 will聽respond and act on the command, even though other devices might receive it.

With this example, we are going to create a Modbus RTU message along this post.聽
Modbus message at the moment: 02 (slave address)

Odoo 鈥 Text and Image

3- Modbus general frame structure

聽聽聽聽The Modbus RTU Application Data unit (ADU) consists of the shown elements:

Address: We set the slave address for the device which we want to send the message to.
Function Code: The number of the function code. You can see the table of the function codes in the "Modbus function codes" section.
Data: The message itself. This can vary depending on the function code.
CRC: The number of the cyclic redundancy check. It must be calculated.

Of these, The Function Code and Data constitue the Protocol Data unit (PDU)


4- Modbus Function Code

MODBUS is a request/reply protocol and offers services specified by function codes. MODBUS function codes are elements of MODBUS request/reply PDUs.聽

The function code field of a MODBUS data unit is coded in one byte. Valid codes are in the range of 1 to 255 decimal (the range 128 鈥 255 is reserved and used for exception responses). When a message is sent from a Client to a Server device the function code field tells the server what kind of action to perform. Function code "0" is not valid. Sub-function codes are added to some function codes to define multiple actions.聽

Below you can find the list of function codes and their functions:

Odoo 鈥 Image and Text

5- Modbus Object Types

In Modbus, the data types can be divided majorly in two types: Coils and Registers. The coils can be understood as digital as can only be either ON (1) or OFF (0). Some coils can represent inputs and some as outputs.

The Registers are of 16 bits ( 2 bytes) unsigned registers and therefore can have values from 0 to 65535 (0 to FFFF). Though it has its limitations such as it cannot represent negative numbers , floating point numbers or values with representation greater than 65535. The below table summarises the object types.

The four primary tables are the following:

PRIMARY TABLESOBJECT TYPETYPE OFCOMMENTS
Discrete inputs (Inputs)
Single bitRead-OnlyThis type of data be provided by an I/O system.
Coils
(Outputs)
Single bitRead-WriteThis type of data can be alterable by an application.
Input Registers
(Inputs)
16-bit wordRead-OnlyThis type of data can be provided by an I/O system.
Holding Registers
(Outputs)
16-bit wordRead-WriteThis type of data can be alterable by an application program.

6- Modbus Data Format

Function codes descriptions


Modbus requests and responses contain an Application Data Unit (ADU) which contains a Protocol Data Unit (PDU).
Let's see how they are.

Odoo 鈥 Image and Text

01 - (0x01) Read Coils

This function code is used to read from 1 to 2000 contiguous status of coils in a remote device.

The coils in the response message are packed as one coil per bit of the data field. Status is indicated as 1: ON and 0: OFF. The LSB of the first data byte contains the output addressed in the query. The other coils follow toward the high order end of this byte, and from low order to high order in subsequent bytes.

Request

Function Code1 Byte0x01
Starting Address2 Bytes0x0000 to 0xFFFF
Quantity of coils2 Bytes1 to 2000 (0x7D0)

Response

Function Code1 Byte0x01
Byte count1 ByteN*
Coil statusn Bytesn = N or N+1

*N = Quantity of Outputs / 8, if the remainder is different of 0 => N = N+1


Example of a request to read discrete outputs 20 鈥38:

Request
Response
Field NameHexField NameHex
Function01Function01
Starting Address Hi00Byte Count03
Starting Address Lo13Outputs status 27-20CD
Quantity of Outputs Hi00Outputs status 35-286B
Quantity of Outputs Lo13Outputs status05

*The CRC must be calculated.


02 - (0x02) Read Discrete Inputs

聽This function code is used to read from 1 to 2000 contiguous status of discrete inputs in a聽remote device.

The Request PDU specifies the starting address, i.e. the address of the first聽input specified, and the number of inputs. In the PDU Discrete Inputs a re addressed starting聽at zero. Therefore Discrete inputs numbered 1-16 are addressed as 0-15.

The discrete inputs in the response message are packed as one input per bit of the data field.聽Status is indicated as 1= ON; 0= OFF. The LSB of the first data byte contains the input聽addressed in the query. The other inputs follow toward the high order end of this byte, and聽from low order to high order in subsequent bytes.

Request

Function Code1 Byte0x02
Starting Address2 Bytes0x0000 to 0xFFFF
Quantity of Inputs2 Bytes1 to 2000 (0x7D0)


Response

Function Code1 Byte0x02
Byte count1 ByteN*
Input statusN* x 1 Byte


Example of a request to read discrete inputs 197 鈥 218:

Petici贸n

Response
Field NameHexField NameHex
Function02Function02
Starting Address Hi00Byte Count03
Starting Address LoC4Outputs status 27-20AD
Quantity of Outputs Hi00Outputs status 35-28DB
Quantity of Outputs Lo16Outputs status35



03 - (0x03) Read Holding Registers

聽This function code is used to read the contents of a contiguous block of holding registers in a聽remote device. The Request PDU specifies the starting register address and the number of聽registers. In the PDU Registers are addressed starting at zero. Therefore registers numbered聽1-16 are addressed as 0-15.

The register data in the response message are packed as two bytes per register, with the聽binary contents right justified within each byte. For each register, the first byte contains the聽high order bits and the second contains the low order bits.

Request

Function Code1 Byte0x03
Starting Address2 Bytes0x0000 to 0xFFFF
Quantity of Registers2 Bytes1 to 125 (0x7D0)

Response

Function Code1 Byte0x03
Byte count1 Byte2 x N*
Register valueN* x 2 Bytes

*N = Quantity of Registers


Example of a request to聽read registers 108 鈥 110:

Request
Response
Field NameHexField NameHex
Function03Function03
Starting Address Hi00Byte Count06
Starting Address Lo6BRegister value Hi (108)
Register value Lo (108)
02

2B
No. of Registers Hi00Register value Hi (109)
Register value Lo (109)
00

00
No. of Registers Lo03Register value Hi (110)
Register value Lo (110)
00

64




04 - (0x04) Read Input Registers

This function code is used to read from 1 to 125 contiguous input registers in a remote device. The Request PDU specifies the starting register address and the number of registers. In the聽PDU Registers are addressed starting at zero. Therefore input registers n umbered 1-16 are聽addressed as 0-15.聽

The register data in the response message are packed as two bytes per register, with the聽binary contents right justified within each byte. For each register, the first byte contains the聽high order bits and the second contains the low order bits.

Request

Function Code1 Byte0x04
Starting Address2 Bytes0x0000 to 0xFFFF
Quantity of Input Registers2 Bytes0x0001 to 0x007D

Response

Function Code1 Byte0x04
Byte count1 Byte2 x N*
Input RegistersN* x 2 Bytes

*N = Quantity of Input Registers


Example of a聽request to read input register 9:

Request
Response
Field NameHexField NameHex
Function04Function04
Starting Address Hi00Byte Count02
Starting Address Lo08Input Reg. 9 Hi00


Quantity of Input Reg. Hi00Input Reg. 9 Lo
0A
Quantity of Input Reg. Lo
01



05 - (0x05) Write Single Coil

This function code is used to write a single output to either ON or OFF in a remote device.

The requested ON/OFF state is specified by a constant in the request data field. A value of FF00 hex requests the output to be ON. A value of 00 00 requests it to be OFF. All other values聽are illegal and will not affect the output.聽

The Request PDU specifies the address of the coil to be forced. Coils are addressed starting聽at zero. Therefore coil numbered 1 is addressed as 0. The requested ON/OFF state is聽specified by a constant in the Coil Value field. A value of 0XFF00 requests the coil to be ON.聽A value of 0X0000 requests the coil to be off. All other values are illegal and will not affect the coil.

The normal response is an echo of the request, returned after the coil state has been written.

Request

Function Code1 Byte0x05
Output Address2 Bytes0x0000 to 0xFFFF
Output value2 Bytes0x0000 to 0xFF00

Response

Function Code1 Byte0x05
Byte count2 Byte0x0000 to 0xFFFF
Input Registers2 Bytes0x0000 or 0xFF00


Example of聽聽a request to write Coil 173 ON:

Request
Response
Field NameHexField NameHex
Function05Function05
Starting Address Hi00Output Address Hi
00
Starting Address LoACOutput Address Lo
AC


Quantity of Input Reg. HiFFOutput Value HiFF
Quantity of Input Reg. Lo
00Output Value Lo
00



06 - (0x06) Write Single Register

This function code is used to write a single holding register in a remote device.

The Request PDU specifies the address of the register to be written. Registers are addressed starting at zero. Therefore register numbered 1 is addressed as 0.

The normal response is an echo of the request, returned after the register contents have been written.

Request

Function Code1 Byte0x06
Register Address2 Bytes0x0000 to 0xFFFF
Register value2 Bytes0x0000 to 0xFFFF

Response

Function Code1 Byte0x06
Register Address2 Byte0x0000 to 0xFFFF
Register value2 Bytes0x0000 or 0xFF00


Example of a聽request to聽write register 2 to 00 03 hex:

Request
Response
Field NameHexField NameHex
Function06Function06
Starting Address Hi00Output Address Hi
00
Starting Address Lo01Output Address Lo
01


Quantity of Input Reg. Hi00Output Value Hi00
Quantity of Input Reg. Lo
03Output Value Lo
03



15 - (0x0F) Write Multiple Coils

This function code is used to force each coil in a sequence of coils to either ON or OFF in a聽remote device. The Request PDU specifies the coil references to be forced. Coils are聽addressed starting at zero. Therefore coil numbered 1 is addressed as 0.

The requested ON/OFF states are specified by contents of the request data field. A logical ' 1'聽in a bit position of the field requests the corresponding output to be ON. A logical '0' requests聽it to be OFF.

The normal response returns the function code, starting address, and quantity of coils forced.聽


Request

Function Code1 Byte0x0F
Starting Address2 Bytes0x0000 to 0xFFFF
Quantity of Outputs2 Bytes0x0001 to 0x07B0
Byte Count1 ByteN*
Outputs ValueN* x 1 Byte聽

*N = Quantity of Outputs / 8, if the remainder is different of 0 => N = N+1


Response

Function Code1 Byte0x0F
Starting Address2 Byte0x0000 to 0xFFFF
Quantity of Outputs2 Bytes0x0001 or 0x07B0


Example of a request to write register 2 to 00 03 hex:

Petici贸n

聽Response
Field NameHexField NameHex
Function0FFunction0F
Starting Address Hi00Starting Address Hi00
Starting Address Lo13Starting Address Lo13
Quantity of Outputs Hi00Quantity of Outputs Hi00
Quantity of Outputs Lo0AQuantity of Outputs Lo0A
Byte Count02

Outputs Value HiCD

Outputs Value Lo01



16 - (0x10) Write Multiple Registers

This function code is used to write a block of contiguous registers (1 to 123 registers) in a聽remote device.

The requested written values are specified in the request data field. Data is packed as two聽bytes per register.

The normal response returns the function code, starting address, and quantity of registers聽written.


Request

Function Code1 Byte0x10
Starting Address2 Bytes0x0000 to 0xFFFF
Quantity of Registers2 Bytes0x0001 to 0x007B
Byte Count1 Byte2 x N*
Registers聽 ValueN* x 2 Bytesvalue

*N = Quantity of Registers


Response

Function Code1 Byte0x10
Starting Address2 Byte0x0000 to 0xFFFF
Quantity of Registers2 Bytes0x123 or (0x7B)


Example聽of a request to write two registers starting at 2 to 00 0A and 01 02 hex:

Request
聽Response
Field NameHexField NameHex
Function10Function10
Starting Address Hi00Starting Address Hi00
Starting Address Lo01Starting Address Lo01
Quantity of Registers Hi00Quantity of Outputs Hi00
Quantity of Registers Lo
02Quantity of Outputs Lo02
Byte Count04

Registers Value Hi00

Registers Value Lo
0A

Registers Value Hi
01

Registers Value Lo

02





7- Creating our Modbus RTU message

Now we already know a little bit more about Modbus RTU and its frame format, let's finish our Modbus message from the example we gave at the beginning of this blog post.

We wanted the master to send a message to slave number 2 requesting the value of 6 input registers.

Our Modbus RTU message looks like this at the moment: 0204 (聽02 (Slave Address) + 04 (Function Code) )

As our function code is number 04: Read Input Register, the data must contain:聽Starting Address Hi +聽Starting Address Lo + Quantity of Input Reg. Hi +聽Quantity of Input Reg. Lo + CRC.

So, let's fill the request ADU in order to get all the message:聽

Request ADU
Field NameHEX
Slave Address02
Function Code04
Starting Address Hi00
Starting Address Lo
00
Quantity of Input Reg. Hi00
Quantity of Input Reg. Lo
06
CRC-
CRC-


To calculate the CRC, just type the Modbus message:聽020400000006 in this website. Select HEX input type and get the CRC-16 (Modbus) number.

As it is LSB, we will reverse it. If the result of the CRC is:聽0x3B70, now it will be: 703B.

Finally, this is how our Modbus message looks like:聽

020400000006703B

8- Software

Modbus RTU Master con Arduino IDE


El m贸dulo maestro Modbus RTU implementa las capacidades del Modbus RTU Master. Vamos a trabajar con la funci贸n modbusrtumaster.h:

#include <ModbusRTUMaster.h>


Es posible utilizar cualquier secuencia de hardware Serial Arduino:

  • RS-485

#include <RS485.h>

ModbusRTUMaster聽master(RS485);


  • RS-232

#include <RS232.h>

ModbusRTUMaster聽master(RS232);


Antes de usarlo, es necesario llamar a la funci贸n de inicio en la configuraci贸n tanto para la variable serial como para la variable Modbus. Es una buena pr谩ctica establecer la velocidad de transmisi贸n (valor predeterminado: 19200 bps) tambi茅n en la variable Modbus para definir los tiempos de espera internos de Modbus.

RS485.begin(9600, HALFDUPLEX, SERIAL_8E1);
master.begin(9600);


The functions to read and write slave values are:

readCoils(slave_address, address, quantity);
readDiscreteInputs(slave_address, address, quantity);
readHoldingRegisters(slave_address, address, quantity);
readInputRegisters(slave_address, address, quantity);
writeSingleCoil(slave_address, address, value);
writeSingleRegister(slave_address, address, value);
writeMultipleCoils(slave_address, address, values, quantity);
writeMultipleRegisters(slave_address, address, values, quantity);


Where :

  • slave_address聽es la direcci贸n del esclavo Modbus RTU.

  • address es la bobina, entrada digital, registro de retenci贸n o direcci贸n de registro de entrada. Por lo general, esta direcci贸n es la bobina, la entrada digital, el registro de retenci贸n o el n煤mero de registro de entrada menos 1: el n煤mero de registro de retenci贸n聽40009聽tiene la direcci贸n聽8.
    quantity聽is the number of coils, digital, holding registers or input registers to read/write.
  • valuees el valor dado de la bobina o los registros de retenci贸n en una operaci贸n de escritura. Dependiendo de la funci贸n, el tipo de datos cambia. Una bobina est谩 representada por un valor bool y un registro de retenci贸n est谩 representado por un valor
    uint16_t.

En una funci贸n de lectura/escritura m煤ltiple, el argumento de聽address聽es la primera direcci贸n. En una funci贸n de escritura m煤ltiple, el argumento聽values聽es una matriz de valores para escribir.

It is important to say that these functions are non-blocking, so they do not return the read value. They return聽true聽or聽false聽depending on the current module state. If there is a pending Modbus request, they return聽false.聽聽

// Read 5 holding registers from address 0x24 of slave with address 0x10
if聽(master.readHoldingRegisters(0x10,聽0x24,聽5)) {
	// OK, the request is being processed
}聽else聽{
	// ERROR, the master is not in an IDLE state
}

Existe la funci贸n聽vailable()para verificar las respuestas del esclavo

ModbusResponse response = master.available();
if聽(response) {
	// Process response
}


ModbusResponse聽implementa algunas funciones para obtener la informaci贸n de respuesta:

hasError();
getErrorCode();
getSlave();
getFC();
isCoilSet(offset);
isDiscreteInputSet(offset);
isDiscreteSet(offset);
getRegister(offset);
ModbusResponse response = master.available();
if聽(response) {
	if聽(response.hasError()) {
		// There is an error. You can get the error code with response.getErrorCode()
	}聽else聽{
		// Response ready: print the read holding registers
		for聽(int聽i =聽0; i <聽5; ++i) {
			Serial.println(response.getRegister(i));
		}
	}
}

The possible error codes are:

0x01 ILLEGAL FUNCTION
0x02 ILLEGAL DATA ADDRESS
0x03 ILLEGAL DATA VALUE
0x04 SERVER DEVICE FAILURE


Source

Check out for more >>>

Librer铆a Modbus RTU Master para automatizaci贸n industrial
Boot & Work Corp. S.L., Fernandez Queralt Martinez
18 marzo, 2020
Compartir
Archivar

驴En busca de tu PLC ideal?

Echa un vistazo a esta comparativa de producto de varios controladores industriales basados en Arduino.

Comparamos entradas, salidas, comunicaciones y otras especificaciones con las de los equipos de otras marcas destacadas.


Comparativa PLC industrial >>

驴Quieres m谩s informaci贸n?

隆Rellena el formulario!

隆Cu茅ntame m谩s!