Modbus is a serial communications protocol originally published by Schneider Electric in 1979 for use with their programmable logic controllers (PLCs). Modbus is located in the level 2 of the OSI model, and uses a master/slave (or client-server) architecture. Simple and robust, it has since become a de facto standard communication protocol, and it is now a commonly available means of connecting industrial electronic devices. Modbus communication protocol presents the follow features:
Modbus allows communication between many devices connected to the same network, for example a system that measures temperature and humidity and communicates the results to a computer. Many of the data types are named from its use in driving relays: a single-bit physical output is called a coil, and a single-bit physical input is called a discrete input or a contact.
This list includes some of the most common uses of the standard:
Modbus | ||||||||
Data area | Up to 255 bytes per job | |||||||
Interface | Layer 7 of the ISO-OSI reference model | |||||||
Number of possible connections | Up to 32 in multi point systems | |||||||
Frame format | RTU | |||||||
Operating mode | Master/Slave |
Modbus for Arduino/RaspberryPi/Galileo uses RTU mode of transmission. This mode is used in serial communication and makes use of a compact, binary representation of the data for protocol communication. The RTU format follows the commands/data with a cyclic redundancy check checksum as an error check mechanism to ensure the reliability of data. Modbus RTU is the most common implementation available for Modbus. A Modbus RTU message must be transmitted continuously without inter-character hesitations. Modbus messages are framed by idle periods.
The Modbus RTU transmission mode usually includes a parity bit to detect transmission errors. You can choose to transmit data with or without parity checking, but always make sure that all equipment connected to Modbus has the same configuration mode, otherwise communication will not be possible.
An RTU frame includes the following information:
The Modbus protocol can be implemented over RS-485 and RS-232 phisical layers. Cooking-Hacks provides the necesary hardware and software for working with both protocols. The name and use of the functions are the same for RS-232 and RS-485, and the only changes are the library to include and the instantiation of the object. The diferences between the two standards are explained in the corresponding tutorials.
The RS-485 module must be used in combination with the Multiprotocol Radio Shield. The Multiprotocol Radio Shield has two sockets. The RS-485 module must be connected as shown in the next figures.
The RS-232 module is compatible with the Multiprotocol Radios Shield and the XBee shield.
Please, see the Multiprotocol Radio Shield Tutorial for more information.
Warnings::
The Modbus protocol counts with a C++ library that lets you manage the Modbus functions in a simple way. This library offers an simple-to-use open source system.
In order to ensure the same code is compatible in both platforms (Arduino and Raspberry Pi) we use the ArduPi libraries which allows developers to use the same code. Detailed info can be found here:
The Modbus protocol includes a high level library functions for a easy manage. Before start using this functions you should download the files from the next link. This zip includes all the files needed in several folders. These folders include the necessary file for using Modbus protocol in master and slave mode.
Download the Modbus / RS-485 library for Arduino
Download the Modbus / RS-232 library for Arduino
Libraries are often distributed as a ZIP file or folder. The name of the folder is the name of the library. Inside the folder will be the .cpp files, .h files and often a keywords.txt file, examples folder, and other files required by the library.
To install the library, first quit the Arduino application. Then uncompress the ZIP file containing the library. For installing libraries , uncompress zip file. Drag the folders into this folder (your libraries folder). Under Windows, it will likely be called "My Documents\Arduino\libraries". For Mac users, it will likely be called "Documents/Arduino/libraries". On Linux, it will be the "libraries" folder in your sketchbook.
The library won't work if you put the .cpp and .h files directly into the libraries folder or if they're nested in an extra folder. Restart the Arduino application. Make sure the new library appears in the Sketch->Import Library menu item of the software.
The Modbus libraries for Raspberry Pi requires the ArduPi library and both libraries should be in the same path.
Download the Modbus / RS-485 library for Raspberry Pi
Download the Modbus / RS-232 library for Raspberry Pi
Creating a program that uses the library is as simple as putting your code in this template where it says "your Arduino code here"
//Include Modbus library (it includes arduPi) /********************************************************* * IF YOUR ARDUINO CODE HAS OTHER FUNCTIONS APART FROM * * setup() AND loop() YOU MUST DECLARE THEM HERE * * *******************************************************/ /************************** * YOUR ARDUINO CODE HERE * * ************************/ int main (){ setup(); while(1){ loop(); } return (0); }
Compilation of the program (using Modbus library) can be done in two ways:
g++ -c arduPi.cpp -o arduPi.o g++ -c RS485.cpp -o RS485.o g++ -c Modbusmaster485.cpp Modbusmaster485.o g++ -lpthread -lrt user-Modbus-app.cpp arduPi.o RS485.o Modbusmaster485.o -o user-Modbus-app
g++ -lpthread -lrt user-Modbus-app.cpp arduPi.cpp RS485.cpp ModbusMaster485.cpp -o user-Modbus-app
Executing your program is as simple as doing:
sudo ./user-Modbus-app
The Modbus module includes a high level library functions for a easy manage. Before start using this functions you should download the files from the next link. This zip includes all the files needed in several folders. These folders include the necessary file for using Modbus protocol.
Download the Modbus / RS-485 library for Intel Galileo
Download the Modbus / RS-232 library for Intel Galileo
Libraries are often distributed as a ZIP file or folder. The name of the folder is the name of the library. Inside the folder will be the .cpp files, .h files and often a keywords.txt file, examples folder, and other files required by the library.
To install the library, first quit the Arduino application. Then uncompress the ZIP file containing the library. For installing libraries , uncompress zip file. Under Windows, it will likely be called "My Documents\Arduino\libraries". For Mac users, it will likely be called "Documents/Arduino/libraries". On Linux, it will be the "libraries" folder in your sketchbook.
The library won't work if you put the .cpp and .h files directly into the libraries folder or if they're nested in an extra folder. Restart the Arduino application. Make sure the new library appears in the Sketch->Import Library menu item of the software.
Initialization functions
ModbusMaster485(); // Creates class object using default Modbus slave ID 1 ModbusMaster485(uint8_t); // Creates class object using specified Modbus slave ID begin(); // Sets up the serial port using default 19200 baud rate begin(unsigned long ); // Sets up the serial port using specified baud rate
Send and receive functions
uint8_t readCoils(uint16_t, uint16_t); // Modbus function 0x01 Read Coils uint8_t readDiscreteInputs(uint16_t, uint16_t); // Modbus function 0x02 Read Discrete Inputs uint8_t readHoldingRegisters(uint16_t, uint16_t); // Modbus function 0x03 Read Holding Registers uint8_t readInputRegisters(uint16_t, uint8_t); // Modbus function 0x04 Read Input Registers uint8_t writeSingleCoil(uint16_t, uint8_t); // Modbus function 0x05 Write Single Coil uint8_t writeSingleRegister(uint16_t, uint16_t); // Modbus function 0x06 Write Single Register uint8_t writeMultipleCoils(uint16_t, uint16_t); // Modbus function 0x0F Write Multiple Coils uint8_t writeMultipleRegisters(uint16_t, uint16_t);// Modbus function 0x10 Write Multiple Registers
Utile functions
void setSlaveAddress(uint8_t); // Changes the slave address uint8_t available(void); // Returns the availbale data read uint16_t getResponseBuffer(uint8_t); // Retrieve data from response buffer void clearResponseBuffer(); // Clear Modbus response buffer uint8_t setTransmitBuffer(uint8_t, uint16_t); // Place data in transmit buffer void clearTransmitBuffer(); // Place data in transmit buffer
NOTE:
Modbus allows communication between many devices connected to the same network, for example a system that measures temperature and humidity and communicates the results to a computer. Many of the data types are named from its use in driving relays: a single-bit physical output is called a coil, and a single-bit physical input is called a discrete input or a contact.
In this example we are going to show how to use th RS-485 module to connect Arduino and Raspbery Pi platforms to Modbus devices measurement devices.
First of all, you must be sure that your device is compatible with Arduino and Raspberry. In the device manual will be described the communication parameters (device address, baud rate...). You also must check that the device uses RTU format. There are many variants of Modbus protocols, but the Arduino library implements the RTU format. Modbus RTU is the most common implementation available for Modbus.
Parameter | Setting |
Baud | 19200 |
Parity | N |
Data bits | 8 |
Stop bit | 1 |
Flow control | None |
The next step is to know what Modbus commands uses the device. The supported commands should be listed in a table. In the next Figure you can see an example of the Modbus commands extracted from a data sheet. The Modbus library for Waspmote is compatible with the majority of the Modbus commands.
Command Name | Command Number |
Read Holding Register | 03 |
Write (Preset) Single Register | 06 |
Return Slave ID | 17 |
Connect the signals A/B of the RS-485 module with the corresponding signal of the Modbus device. The name of these signal can change depending on the manufacturer. Usual names of these signal are A/B S+/S-, +/-, etc.
In our example, we are going to read the temperature value from our device. We can see in the register map, that the temperature value is stored in the register 101 and is accessible with the function readHoldingRegisters, and is stored in 16 bits format (2 bytes). So the necessary function to get the value of the temperature is shown in the next code example.
Address | Bytes | Range | Defaults (°C /°F) | Register and Description |
0 to 3 | 4 | - | - | Serial Number -4 byte value. Read-only |
4 to 5 | 2 | - | - | Serial Version -2 byte value. Read-only |
6 | 1 | 255 | 254 | ADDRESS. Modbus device address |
100 | 2 | 0-1000 | - | ROOM TEMPERATURE reading in DegF |
101 | 2 | 0-600 | - | ROOM TEMPERATURE reading in DegC |
304 | 2 | 0-1000 | - | Relative Humidity reading. Writing a humidity value to the register will do calibration. |
Arduino / Intel Galileo
/* * ModBus Module * * Copyright (C) Libelium Comunicaciones Distribuidas S.L. * http://www.libelium.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * a * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Version: 1.0 * Design: David Gascón * Implementation: Ahmad Saad */ // Include these libraries for using the RS-485 and Modbus functions #include <RS485.h> #include <ModbusMaster485.h> #include <SPI.h> // Instantiate ModbusMaster object as slave ID 1 ModbusMaster485 node(254); // Define one addres for reading #define address 101 // Define the number of bytes to read #define bytesQty 2 void setup() { // Power on the USB for viewing data in the serial monitor Serial.begin(115200); delay(100); // Initialize Modbus communication baud rate node.begin(19200); // Print hello message Serial.println("Modbus communication over RS-485"); delay(100); } void loop() { // This variable will store the result of the communication // result = 0 : no errors // result = 1 : error occurred int result = node.readHoldingRegisters(address, bytesQty); if (result != 0) { // If no response from the slave, print an error message Serial.println("Communication error"); delay(1000); } else { // If all OK Serial.print("Read value : "); // Print the read data from the slave Serial.print(node.getResponseBuffer(0)); delay(1000); } Serial.print("\n"); delay(2000); // Clear the response buffer node.clearResponseBuffer(); }
Raspberry Pi
You have to compile the Modbusmaster485 library:
g++ -c Modbusmaster485.cpp -o Modbusmaster485.o g++ -lpthread -lrt Modbus_example.cpp arduPi.o RS485.o currentLoop.o -o Modbus_example
/* * ModBus Module * * Copyright (C) Libelium Comunicaciones Distribuidas S.L. * http://www.libelium.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * a * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Version: 1.0 * Design: David Gascón * Implementation: Ahmad Saad */ // Include these libraries for using the RS-485 and Modbus functions #include "ModbusMaster485.h" #include "arduPi.h" // Instantiate ModbusMaster object as slave ID 1 ModbusMaster485 node(254); // Define one addres for reading #define address 101 // Define the number of bytes to read #define bytesQty 2 void setup() { pinMode(5, OUTPUT); digitalWrite(5, LOW); // Power on the USB for viewing data in the serial monitor Serial.begin(115200); delay(100); // Initialize Modbus communication baud rate node.begin(19200); // Print hello message printf("Modbus communication over RS-485\n"); delay(100); } void loop() { // This variable will store the result of the communication // result = 0 : no errors // result = 1 : error occurred int result = node.readHoldingRegisters(address, bytesQty); if (result != 0) { // If no response from the slave, print an error message printf("Communication error\n"); delay(1000); } else { // If all OK printf("Read value : \n"); // Print the read data from the slave Serial.print(node.getResponseBuffer(0)); delay(1000); } printf("\n"); delay(2000); // Clear the response buffer node.clearResponseBuffer(); } int main (){ setup(); while(1){ loop(); } return (0); }
You should receive the data in your serial monitor.
The Multiprotocol Radio Shield can be used to connect two communication protocols at the same time and make interconnections between different systems and devices. In the next example we are going to interconnect a Modbus device over RS-485 module with wireless protocol using and XBee module.
NOTE:
Connect the RS-485 module and XBee modules in the corresponding sockets as shown in the next image.
If you are using 802.15.4, use external pine with pin4 disconnected.
You should receive all data in your gateway device.
Arduino
/* * ModBus Module * * Copyright (C) Libelium Comunicaciones Distribuidas S.L. * http://www.libelium.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * a * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * * Version: 1.0 * Design: David Gascón * Implementation: Ahmad Saad */ // Include these libraries for using the RS-485 and Modbus functions #include <RS485.h> #include <ModbusMaster485.h> #include <SPI.h> // Instantiate ModbusMaster object as slave ID 1 ModbusMaster485 node(254); // Define one addres for reading #define address 101 // Define the number of bytes to read #define bytesQty 2 void setup() { // XBee in SOCKET0 pinMode(5, OUTPUT); digitalWrite(5, LOW); // Power on the USB for viewing data in the serial monitor Serial.begin(115200); delay(100); // Initialize Modbus communication baud rate node.begin(19200); // Print hello message Serial.println("Modbus communication over RS-485"); delay(100); } void loop() { // This variable will store the result of the communication // result = 0 : no errors // result = 1 : error occurred int result = node.readHoldingRegisters(address, bytesQty); if (result != 0) { // If no response from the slave, print an error message Serial.println("Communication error"); delay(1000); } else { // If all OK Serial.print("Read value : "); // Print the read data from the slave Serial.print(node.getResponseBuffer(0)); delay(1000); } Serial.print("\n"); delay(2000); // Clear the response buffer node.clearResponseBuffer(); }
If you are interested in Internet of Things (IoT) or M2M projects check our open source sensor platform Waspmote which counts with more than 100 sensors available to use 'off the shelf', a complete API with hundreds of ready to use codes and a low consumption mode of just 0.7µA to ensure years of battery life.
Know more at:
Get the Starter Kits at: