>> INDUSTRIAL INTEGRATION (MODBUS) USING AN ARDUINO
Who says that the use of Arduino devices are for hobby projects only - it has
grown up!
I have recently been involved in a few industrial applications where the
project involved integrating the Arduino platform with industrial hardware -
which of course involves some proprietary protocols. One of these protocols
is a serial communications protocol called
Modbus
- originally published by Modicon (now Schneider Electric). So how does one
interface with such devices?
While the details of the project must remain confidential - I can at least
give some insight on how I got my fingers dirty and started figuring out how
the Arduino platform can be used; the EM24 DIN (Energy Management/Analyzer)
is a great little unit you can pick up quite easily.
The first step was to find an RS-485 (physical layer for Modbus) adapter
for the Arduino and hook it all up. My quick search led me to the
cooking hacks
website - where they have an excellent step-by-step example for a number
of different micro-controllers. The tutorial is a must read - however it
is more important how to figure out which parameters to query to achieve
what you need.
What hardware you need:
To get started; first you need to get access to the Modbus register
specification that is associated with the device you wish to interface with.
For the EM24 - a few copies exist, but I found one on the
SHM Communications
website - as you can see there are a tonne of different pieces of information
one can interface with using the Modbus protocol.
To get started with your sketch; you need to have the Arduino assume
the role of a Modbus Master - basically, this means the EM24 will be a
slave device and the Arduino will initiate requests for information.
// define the slave ID we will want to connect to
#define SLAVE_ID 4
#define SLAVE_BAUD 9600
// instantiate ModbusMaster object with a specific slave ID
ModbusMaster485 node(SLAVE_ID);
void setup()
{
// initialize Modbus communication baud rate
node.begin(SLAVE_BAUD);
}
The Modbus protocol requires the definition of a unique ID that represents
the device the command will be issued to; in the above snipped this is
called the SLAVE_ID - in my example, it uses ID number 4.
This can be a number between 1 and 247 - the ID of
0 is reserved for broadcasting to multiple devices, but in most
cases you can find or set the unique ID on the hardware itself.
There are typically two signals for connecting to the Modbus device;
an inverted signal and a non inverted signal; or, the device can use a
DB9 connector in which case pins 3 and 7 are typically used. It is vital
to use the right polarity or no communication will be established.
There should also be a clearly documented baud rate in which the device
communicates; this is typically either 9600 or 19200
with 8-N-1 (8 bit, no carry, 1 stop bit). The libraries provided by
cooking hacks can support other configurations - but out of the box they
assume 8-N-1.
So; how would we read the total kWh that the device reports?
// define the addresses for reading (modbus)
#define EM24_KWH_MAX 0x3E // KWh * 10
// define the number of bytes to read for each address
#define EM24_KWH_MAX_B 4
void loop()
{
// read the KWh of the EM24
result = node.readHoldingRegisters(EM24_KWH_MAX, EM24_KWH_MAX_B);
if (result == 0)
{
int32_t data;
data = 0;
data |= ( int32_t)node.getResponseBuffer(1) << 16;
data |= (uint32_t)node.getResponseBuffer(0);
// Debug_Trace("%lu.%u KWh\r\n", (data / 10), (data % 10));
}
// wait a second before the next
delay(1000);
}
Believe it or not; it is that simple.
The secret here is knowing how to obtain the constants that are used to make
a request for information - in this case EM24_KWH_MAX and
EM24_KWH_MAX_B - which are parameters to the function
node.readHoldingRegisters. On making such a request; a response
buffer can contain a number of uint16_t values which can be
put together or processed to receive information from a single register
or a number of registers in sequence (if they follow each other).
The EM24 DIN register table outlines the kWh value is stored in register
0x3E and is of the type INT32. In order to correctly
extract the value as a series of 16 bit integers; you need to be careful
with the sign of the bytes you extract - I have tried to keep that simple
in the example above.
The document also mentions the value is kWh*10 - so, if the number
returned is 12345 - it represents the value of 1234.5
(one decimal point). While the Debug_Trace function is commented
out above; it gives you an idea how to show the value on the console. If
the request doesn't give a zero based result - check the signal connections
to make sure the polarity is correct.
Once you get your first Modbus device connected - it wont be long before
you start looking for other devices around your home or office you can
interface with. I noticed the other day my solar inverter has a Modbus
interface - it would be just as simple to connect to as the EM24 DIN.
Just make sure you do not go around electrocuting yourself! Happy tinkering!