Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
SRGDamia1 committed Aug 29, 2019
2 parents 5e59143 + 5c580a0 commit 4f059fe
Show file tree
Hide file tree
Showing 16 changed files with 14,111 additions and 18 deletions.
48 changes: 30 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
# SensorModbusMaster

This library is designed to use an Arduino as a modbus master to communicate with a sensor/slave via [modbus RTU](https://en.wikipedia.org/wiki/Modbus). It's specifically written with lots of "higher-level" functions to help out users who are largely unfamiliar with the modbus protocol and want an easy way to get information from a modbus device.
This library is designed to use an Arduino as a Modbus master to communicate with a sensor/slave via the [Modbus RTU](https://en.wikipedia.org/wiki/Modbus) communication protocol. It's specifically written with lots of "higher-level" functions to help out users who are largely unfamiliar with the Modbus protocol and want an easy way to get information from a Modbus device.

### Contents:
- [Using the library](#usingLibrary)
- [Notes on Modbus maps](#notesModbusMaps)
- [Notes on TTL and RS485/RS322 electrical communications standards](#notesRS485)
- [Hardware interface suggestions for EnviroDIY Mayfly and other Arduino boards](#hardwareMayfly)

_____

## Using the library
## <a name="usingLibrary"></a>Using the library

To communicate with a modbus sensor or other modbus slave, first create a stream instance (ie, Serial1, SoftwareSerial, AltSoftSerial) and then an instance of the modbusMaster.
To communicate with a Modbus sensor or other Modbus slave, first create a stream instance (ie, Serial1, SoftwareSerial, AltSoftSerial) and then an instance of the modbusMaster.

```cpp
// Create the stream instance
Expand Down Expand Up @@ -43,11 +50,11 @@ The following data types are supported:
- uint16 (16-bit unsigned integer)
- Value must be within a single 16-bit register
- bigEndian or littleEndian can be specified, bigEndian will be used by default
- By default, the modbus command for pre-setting a single register will be used (0x06). Set the forceMultiple boolean flag to 'true' to force the use of the modbus command for setting multiple resisters (0x10).
- By default, the Modbus command for pre-setting a single register will be used (0x06). Set the forceMultiple boolean flag to 'true' to force the use of the Modbus command for setting multiple resisters (0x10).
- int16 (16-bit signed integer)
- Value must be within a single 16-bit register
- bigEndian or littleEndian can be specified, bigEndian will be used by default
- By default, the modbus command for pre-setting a single register will be used (0x06). Set the forceMultiple boolean flag to 'true' to force the use of the modbus command for setting multiple resisters (0x10).
- By default, the Modbus command for pre-setting a single register will be used (0x06). Set the forceMultiple boolean flag to 'true' to force the use of the Modbus command for setting multiple resisters (0x10).
- float32 (32-bit float)
- Value must be in two adjacent 16-bit registers
- bigEndian or littleEndian can be specified, bigEndian will be used by default
Expand Down Expand Up @@ -77,28 +84,28 @@ The following data types are supported:
- See https://www.tai64.com/ for more details on this format type
- byte (8-bit unsigned integer or raw byte of data)
- Must specify either the first or second 8-bit component of a single 16-bit register)
- By default, the modbus command for pre-setting a single register will be used (0x06). Set the forceMultiple boolean flag to 'true' to force the use of the modbus command for setting multiple resisters (0x10).
- By default, the Modbus command for pre-setting a single register will be used (0x06). Set the forceMultiple boolean flag to 'true' to force the use of the Modbus command for setting multiple resisters (0x10).
- char (c++/ASCII style characters)
- Characters can be in one or more contiguous 16-bit registers
- Length of the character array must be specified
- By default, the modbus command for pre-setting a single register will be used (0x06) if the character array has two or fewer characters. Set the forceMultiple boolean flag to 'true' to force the use of the modbus command for setting multiple resisters (0x10).
- By default, the Modbus command for pre-setting a single register will be used (0x06) if the character array has two or fewer characters. Set the forceMultiple boolean flag to 'true' to force the use of the Modbus command for setting multiple resisters (0x10).
- String (Arduino Strings)
- Characters can be in one or more contiguous 16-bit registers
- By default, the modbus command for pre-setting a single register will be used (0x06) if the String has two or fewer characters. Set the forceMultiple boolean flag to 'true' to force the use of the modbus command for setting multiple resisters (0x10).
- By default, the Modbus command for pre-setting a single register will be used (0x06) if the String has two or fewer characters. Set the forceMultiple boolean flag to 'true' to force the use of the Modbus command for setting multiple resisters (0x10).
- pointer (pointers to other registers)
- Value must be within a single 16-bit register
- By default, the modbus command for pre-setting a single register will be used (0x06). Set the forceMultiple boolean flag to 'true' to force the use of the modbus command for setting multiple resisters (0x10).
- By default, the Modbus command for pre-setting a single register will be used (0x06). Set the forceMultiple boolean flag to 'true' to force the use of the Modbus command for setting multiple resisters (0x10).

There are also mid-level functions available to help to reduce serial traffic by calling many registers at once and low level functions to make raw modbus calls. See SensorModbusMaster.h for all the available functions and their required and optional inputs
There are also mid-level functions available to help to reduce serial traffic by calling many registers at once and low level functions to make raw Modbus calls. See SensorModbusMaster.h for all the available functions and their required and optional inputs
_____


## Notes on modbus maps
While modbus RTU specifications define the format of a data frame and a very simple data structure for a master and slave, there are no specification for what types of data a slave stores, where it is stored, or in what format it is stored. You **MUST** get this information from the manufacturer/programmer of your modbus device. Typically this information is shared in what is called a modbus map.
## <a name="notesModbusMaps"></a>Notes on Modbus maps
While Modbus RTU specifications define the format of a data frame and a very simple data structure for a master and slave, there are no specification for what types of data a slave stores, where it is stored, or in what format it is stored. You **MUST** get this information from the manufacturer/programmer of your Modbus device. Typically this information is shared in what is called a Modbus map.

You need the following data from your modbus map:
- the baud rate the device communicaes at (modbus allows any baud rate)
- the parity the device uses on the serial line (modbus technically allows 8O1, 8E1, and 8N2, though some devices may use 8N1)
You need the following data from your Modbus map:
- the baud rate the device communicates at (Modbus allows any baud rate)
- the parity the device uses on the serial line (Modbus technically allows 8O1, 8E1, and 8N2, though some devices may use 8N1)
- the type of register or coils the data you are interested is stored in (ie, holding register, input register, coil, or discrete input)
- Note - This library does not currently support getting or setting values in coils.
- the register or coil number the data is stored in
Expand All @@ -107,9 +114,14 @@ You need the following data from your modbus map:
- whether single-register data is stored "big-endian" or "little-endian" (That is, is it high _byte_ first or low _byte_ first. Modbus specifies that it should be high byte first (big-endian), but devices vary.)
- Note - This library only supports data that is "fully" big or little endian. That is, data must be both high byte and high word first or both low byte and low word first.

Without this information, you have little hope of being able to communicate properly with the device. You can use programs like [CAS modbus scanner](http://www.chipkin.com/cas-modbus-scanner/) to find a device if its address, baud rate, and parity are unknown, but it may take some time to make a connection. You can also use the "scanRegisters" utility in this library to get a view of all the registers, but if you don't have a pretty good idea of what you are looking for that will not be as helpful as you might hope.
Without this information, you have little hope of being able to communicate properly with the device. You can use programs like [CAS Modbus scanner](http://www.chipkin.com/cas-modbus-scanner/) to find a device if its address, baud rate, and parity are unknown, but it may take some time to make a connection. You can also use the "scanRegisters" utility in this library to get a view of all the registers, but if you don't have a pretty good idea of what you are looking for that will not be as helpful as you might hope.
_____


## TTL and RS485/RS322
While modbus RTU specifications define the format of a data frame transfered over a serial line, the type of serial signal is not defined. Many modbus sensors communicate over [RS-485](https://en.wikipedia.org/wiki/RS-485). To interface between RS485 and the TTL used by standard Arduino-type boards, you will need an RS485-to-TTL adapter. There are a number of RS485-to-TTL adapters available. When shopping for one, be mindful of the logic level of the TTL output by the adapter. The MAX485, one of the most popular adapters, has a 5V logic level in the TTL signal. This will _fry_ any board that can only use on 3.3V logic. You would need a voltage shifter in between the Mayfly and the MAX485 to make it work. Also note that most RS485-to-TTL adapters are implemented _without_ automatic flow control. That is, you must manually set voltages on driver enable and receiver enable pins to control the data flow direction. While this library includes functions for setting the enables, I've found commutation to be much more stable on adapters with built-in flow control. You will also need an interface board to communicate between an Arduino and any modbus sensor that communicates over [RS422](https://en.wikipedia.org/wiki/RS-422) or [RS232](https://en.wikipedia.org/wiki/RS-232). Again, mind your voltages and the method of direction control.
## <a name="notesRS485"></a>Notes on TTL and RS485/RS322 electrical communications standards
While Modbus RTU specifications define the format of a data frame transferred over a serial line, the type of serial signal is not defined. Many Modbus sensors communicate over [RS-485](https://en.wikipedia.org/wiki/RS-485). To interface between RS485 and the TTL used by standard Arduino-type boards, you will need an RS485-to-TTL adapter. There are a number of RS485-to-TTL adapters available. When shopping for one, be mindful of the logic level of the TTL output by the adapter. The MAX485, one of the most popular adapters, has a 5V logic level in the TTL signal. This will _fry_ any board that can only use on 3.3V logic. You would need a voltage shifter in between the Mayfly and the MAX485 to make it work. Also note that most RS485-to-TTL adapters are implemented _without_ automatic flow control. That is, you must manually set voltages on driver enable and receiver enable pins to control the data flow direction. While this library includes functions for setting the enables, I've found commutation to be much more stable on adapters with built-in flow control. You will also need a [hardware interface board](#hardwareMayfly) to communicate between an Arduino and any Modbus sensor that communicates over [RS422](https://en.wikipedia.org/wiki/RS-422) or [RS232](https://en.wikipedia.org/wiki/RS-232). Again, mind your voltages and the method of direction control.

## <a name="hardwareMayfly"></a>Hardware interface suggestions for EnviroDIY Mayfly
For use with the [EnviroDIY Mayfly datalogger](https://github.com/EnviroDIY/EnviroDIY_Mayfly_Logger) and other Arduino framework boards, you will likely need some additional [Hardware for using ModbusRTU with RS-485 on Arduino](https://github.com/EnviroDIY/SensorModbusMaster/tree/master/hardware).

We have developed a [Modbus-Mayfly-WingShield](https://github.com/EnviroDIY/SensorModbusMaster/tree/master/hardware/Modbus-Mayfly_WingShield) that combines AltSoftSerial TTL to RS-485 conversion with an optional power boost to 9V or 12V. This has worked quite well for us for a variety of deployment configurations and sensors.
Binary file added hardware/Modbus-Mayfly_WingShield/Board_Mrk1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 4f059fe

Please sign in to comment.