This library allows your Arduino to communicate via Modbus protocol. The Modbus is a master-slave protocol used in industrial automation and can be used in other areas, such as home automation.
The Modbus generally uses serial RS-232 or RS-485 as physical layer (then called Modbus Serial) and TCP/IP via Ethernet or WiFi (Modbus IP).
In the current version the library allows the Arduino operate as a slave, supporting Modbus Serial and Modbus over IP. For more information about Modbus see:
Author's note (motivation and thanks):
It all started when I found the Modbus RTU Arduino library of Juan Pablo Zometa. I had extend the library to support other Modbus functions.
After researching several other Modbus libraries I realized strengths and weaknesses in all of them. I also thought it would be cool have a base library for Modbus and derive it for each type of physical layer used.
I appreciate the work of all the authors of the other libraries, of which I used several ideas to compose the modbus-arduino. At the end of this document is a list of libraries and their authors.
Operates as a slave (master mode in development) Supports Modbus Serial (RS-232 or RS485) and Modbus IP (TCP) Reply exception messages for all supported functions Modbus functions supported: 0x01 - Read Coils 0x02 - Read Input Status (Read Discrete Inputs) 0x03 - Read Holding Registers 0x04 - Read Input Registers 0x05 - Write Single Coil 0x06 - Write Single Register 0x0F - Write Multiple Coils 0x10 - Write Multiple Registers Notes:
1) When using Modbus IP the transport protocol is TCP (port 502) and, by default, the connection is terminated to each transmitted message, that is, is not a keep-alive type connection. If you need a TCP keep-alive connection you have to remove comments of this line in ModbusIP.h header (or ModbusIP_* headers):
#define TCP_KEEP_ALIVE 2) The offsets for registers are 0-based. So be careful when setting your supervisory system or your testing software. For example, in ScadaBR (http://www.scadabr.com.br) offsets are 0-based, then, a register configured as 100 in the library is set to 100 in ScadaBR. On the other hand, in the CAS Modbus Scanner (http://www.chipkin.com/products/software/modbus-software/cas-modbus-scanner/) offsets are 1-based, so a register configured as 100 in library should be 101 in this software.
3) Early in the library Modbus.h file there is an option to limit the operation to the functions of Holding Registers, saving space in the program memory. Just comment out the following line:
#define USE_HOLDING_REGISTERS_ONLY Thus, only the following functions are supported:
0x03 - Read Holding Registers 0x06 - Write Single Register 0x10 - Write Multiple Registers 4) When using Modbus Serial is possible to choose between Hardware Serial(default) or Software Serial. In this case you must edit the ModbusSerial.h file and comment out the following line:
#define USE_SOFTWARE_SERIAL Now, You can build your main program putting all necessary includes:
#include <Modbus.h> #include <ModbusSerial.h> #include <SoftwareSerial.h> And in the setup() function:
SoftwareSerial myserial(2,3); mb.config(&myserial, 38400); mb.config(mb.config(&myserial, 38400, 4) for RS-485 How to There are five classes corresponding to five headers that may be used: ==== Modbus - Base Library ==== ModbusSerial - Modbus Serial Library (RS-232 and RS-485) ModbusIP - Modbus IP Library (standard Ethernet Shield) ModbusIP_ENC28J60 - Modbus IP Library (for ENC28J60 chip) ModbusIP_ESP8266AT - Modbus IP Library (for ESP8266 chip with AT firmware) If you want to use Modbus in ESP8266 without the Arduino, I have news: http://www.github.com/andresarmento/modbus-esp8266 By opting for Modbus Serial or Modbus IP you must include in your sketch the corresponding header and the base library header, eg: #include <Modbus.h> #include <ModbusSerial.h> === Modbus Jargon === In this library was decided to use the terms used in Modbus to the methods names, then is important clarify the names of register types: Register type Use as Access Library methods Coil Digital Output Read/Write addCoil(), Coil() Holding Register Analog Output Read/Write addHreg(), Hreg() Input Status Digital Input Read Only addIsts(), Ists() Input Register Analog Input Read Only addIreg(), Ireg() Notes: Input Status is sometimes called Discrete Input. Holding Register or just Register is also used to store values in the slave. Examples of use: A Coil can be used to drive a lamp or LED. A Holding Register to store a counter or drive a Servo Motor. A Input Status can be used with a reed switch in a door sensor and a Input Register with a temperature sensor. ====== Modbus IP(ENC28J60) ====== The Arduino standard Ethernet shield is based on chip WIZnet W5100, therefore the IDE comes with this library installed. If you have a shield based on ENC28J60 from Microchip you must install another Ethernet library. Among several available we chose EtherCard. Download the EtherCard in https://github.com/jcw/ethercard and install it in your IDE. Use the following includes in your sketches: #include <EtherCard.h> #include <ModbusIP_ENC28J60.h> #include <Modbus.h> Done! The use of Modbus functions is identical to the ModbusIP library described above. ===== Notes: ===== EtherCard is configured to use the pins 10, 11, 12 and 13. The voltage for shields based on ENC28J60 is generally 3.3V. Another alternative is to use the ENC28J60 UIPEthernet library, available from https://github.com/ntruchsess/arduino_uip. This library was made so that mimics the same standard Ethernet library functions, whose work is done by Wiznet W5100 chip. As the ENC28J60 not have all the features of the other chip, the library UIPEthernet uses a lot of memory, as it has to do in software what in the shield Wiznet is made in hardware. If for some reason you need to use this library, just change the file ModbusIP.h and your sketches, changing the lines: #include <Ethernet.h> by #include <UIPEthernet.h> Then, you can use the ModbusIP library (not the ModbusIP_ENC28J60). In fact it allows any library or skecth, made for Wiznet shield be used in shield ENC28J60. The big problem with this approach (and why we chose EtherCard) is that UIPEthernet library + ModbusIP uses about 60% arduino program memory, whereas with Ethercard + ModbusIP_ENC28J60 this value drops to 30%!