Master library functions

Configuring the master

The configuration of the master is very important before starting the communication with the slaves. Be sure that your devices can be used with the Waspmote Modbus protocol. For example, the baud rate must be in the available range of Waspmote and the communication must be 8N1 (8 bits, 1 stop bit, no parity).

Library constructor

Before using the library, an object of the library must be created. This object will assign the physical address of the slave. This address can take values from 0 to 255 (address 0 is normally for broadcast mode). In a network, this address must be unique for each device. In this example we are going to communicate RS-485 devices, so the master must be configured to use this protocol of communication when creating an object.

Example of use:

// Instantiate ModbusMaster object as slave ID 1
ModbusMaster node(RS485_COM, 1);

You can create an object for managing several slaves in an easy way.

Example of use:

// Instantiate ModbusMaster object as slave ID 1  
ModbusMaster temperatureSensor(RS485_COM, 1);  
// Instantiate ModbusMaster object as slave ID 2  
ModbusMaster co2Sensor(RS485_COM, 2);

Begin function

In the begin() function, the baud rate communication must be configured. This baud rate must be one of the standard values mentioned in the RS-485 and RS-232 guides. If the value is not a standard value, the device will be configured at 1200 bps.

We suggest to study the RS-232 or RS-485 Communication Guides to know how to configure these modules.

Modbus master library and function

The Modbus library for Waspmote implements the next functions. Maybe the terminology can change depending on documentation, but the code functions must be the same in all Modbus devices. The Modbus standard includes more functions, but these are the most used and important ones.

Code function

Function name

0x01

Read Coils

0x02

Read Discrete Inputs

0x05

Write Single Coil

0x0F

Write Multiple Coils

0x03

Read Holding Registers

0x04

Read Input Registers

0x06

Write Single Register

0x10

Write Multiple Registers

0x16

Mask Write Register

0x17

Read Write Multiple Registers

The Modbus library receives and analyzes the response that the slaves send back to the master. This way, the user can know if the frame was correctly processed by the slave.

Read coils

This function requests the on/off status of discrete coils from the slave device. When receiving a Modbus query message with function readCoils() (code 0x01 in the "field" function of the Modbus frame), the slave collects the necessary output values and constructs an answer message. The length of this message is dependent on the number of values that have to be returned.

Example of use:

{  
    // This variable will store the result of the communication  
    // result = 0: no errors  
    // result = 1: error occurred  
    int result = node.readCoils(address, bitQty);  
    
    if (result != 0)  
    {
        // If no response from the slave, print an error message
        USB.println(“Communication error”);
        delay(1000);  
    }  
    else  
    {  
        // If all ok
        USB.print(“Read value: “);
        // Print the read data from the slave
        USB.print(node.getResponseBuffer(0));
        delay(1000);  
    }
}

See an example of use here:

Read discrete inputs

Reading input values with Modbus is done in the same way as reading the status of coils. The only difference is that for inputs, Modbus function readDiscreteInput() is used (code 0x02). Like with coils, the address of the first input, and the number of inputs to read must be put in the data field of the query message. After receiving a query message with Modbus function readDiscreteInput(), the slave puts the requested input values in a message structure and sends this message back to the Modbus master. The length of the message depends on the number of input values returned.

Example of use:

{  
    // This variable will store the result of the communication  
    // result = 0: no errors  
    // result = 1: error occurred  
    int result = node.readDiscreteInputs(address, bitQty); 
     
    if (result != 0)  
    {
        // If no response from the slave, print an error message
        USB.println(“Communication error”);
        delay(1000);  
    }  
    else  
    {  
        // If all ok
        USB.print(“Read value: “);
        // Print the read data from the slave
        USB.print(node.getResponseBuffer(0));
        delay(1000);  
    }
}

Write single coil

This function writes a single coil to either on or off. The request message specifies the coil address to be written. The requested on/off state is specified by a constant in the request data field. The normal response is an echo of the request, returned after the coil state has been written.

Example of use:

{  
    // This variable will store the result of the communication  
    // result = 0: no errors  
    // result = 1: error occurred  
    int result = node.writeSingleCoil(address, bitData);  
    
    if (result != 0)  
    {
        // If no response from the slave, print an error message
        USB.println(“Communication error”);
        delay(100);  
    }  
    else  
    {  
        // If all ok
        USB.println(“Data writted successfully“);
        delay(100);  
    }
}

See an example of use here:

Write multiple coils

This Modbus function code is used to write each coil in a sequence of coils to either on or off in a remote slave. The request 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.

{  
    // Write data in the transmission buffer, for writing it in the slave  
    node.setTransmitBuffer(0, ON); 
    // ON defined previously  
    node.setTransmitBuffer(1, OFF);
    // OFF defined previously  
    node.setTransmitBuffer(2, ON);  
    
    // This variable will store the result of the communication  
    // result = 0: no errors  
    // result = 1: error occurred  
    int result = node.writeMultipleCoils(address, byteQty);  
    delay(100);
}

Read holding registers

This function is used to read the contents of a contiguous block of holding registers in a slave The request specifies the starting register address and the number of registers. In the 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.

Example of use:

{  
    // This variable will store the result of the communication  
    // result = 0: no errors  
    // result = 1: error occurred  
    //Read 4 bytes  
    int result = node.readHoldingRegisters(accX, bytesQty);
}

Read input registers

This function code is used to read contiguous input registers in a slave. The Request PDU specifies the starting register address and the number of registers. The registers are addressed starting at zero. 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.

Example of use:

{  
    // This variable will store the result of the communication  
    // result = 0: no errors  
    // result = 1: error occurred  
    int result = node.readInputRegisters(address, bytesQty);
}

See an example of use here:

Write single register

This function code is used to write a single holding register in a remote device. The request specifies the address of the register to be written. Registers are addressed starting at zero. Therefore, the register numbered 1 is addressed as 0. The normal response is an echo of the request, returned after the register contents have been written.

Example of use:

{  
    // This variable will store the result of the communication  
    // result = 0: no errors  
    // result = 1: error occurred  
    int result = node.writeSingleRegister(address, bitData);  
    
    if (result != 0)  
    {
        // If no response from the slave, print an error message
        USB.println(“Communication error”);
        delay(100);  
    }  
    else  
    {  
        // If all ok
        USB.println(“Data writted successfully“);
        delay(100);  
    }
}

See an example of use here:

Write multiple registers

This function is used to write a block of contiguous registers in a remote device. The requested values to write 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.

Example of use:

{  
    // Write data in the transmission buffer, for writing it in the slave  
    node.setTransmitBuffer(0, analogRead(1));  
    node.setTransmitBuffer(1, analogRead(2));  
    node.setTransmitBuffer(2, analogRead(3));  
    
    // This variable will store the result of the communication  
    // result = 0: no errors  
    // result = 1: error occurred  
    int result = node.writeMultipleRegisters(address, byteQty);  
    delay(100);
}

Mask write register

This function code is used to modify the contents of a specified holding register using a combination of an AND mask, an OR mask, and the register\'s current contents. The function can be used to set or clear individual bits in the register. The request specifies the holding register to be written, the data to be used as the AND mask, and the data to be used as the OR mask.

Read and write multiple registers

This function code performs a combination of one read operation and one write operation in a single Modbus transaction. The write operation is performed before the read. The request specifies the starting address and number of holding registers to be read as well as the starting address, number of holding registers, and the data to be written. The byte count specifies the number of bytes to follow in the write data field. The normal response contains the data from the group of registers that were read. The byte count field specifies the quantity of bytes to follow in the read data field.

Other library functions

Retrieve data

All data received from the slave is stored in an internal buffer in the master. This buffer has public declaration and can be read using the corresponding object, when you are using Modbus read functions.

Example of use:

{  
    // Store the read data from the slave  
    int data0 = node.getResponseBuffer(0));  
    int data1 = node.getResponseBuffer(1));
}

Clear response buffer

This function acts like a flush of the response buffer and delete all previous information. It is recommended to use this function before starting a new reading process.

Example of use:

{  
    // Clear the response buffer  
    node.clearResponseBuffer();
}

Last updated