Modbus
Well I got around to dabbling with how to best communicate with a host to implement a data historian. I started writing a extremely dumbed down protocol inspired by Modbus After a day I realized that why settle for less and figured that pure Modbus would be better. I could then use Modbus master software to query my Arduinos. I found a Modbus C code for the arduino to provide RTU slave functionality over serial line. I loaded the sketch and downloaded a Modbus tool to read some values from the arduino to see if it all worked. There is only support for Modbus function 3 and function 16 in the arduino implementation and I added code to handle function 6. If you know enough C it is rather straightforward.
Java Host
Now that connectivity using Modbus was feasible, I wanted to ensure that I could implement a data historian with open source tools and decided that Java was the way to go. After all Apache Tomcat, mySQL, and the eclipse dev environment are free and just require wetware to use. I also wanted to have my own arduinoController to collect the energy information that abstracted the details of Modbus. After combing the net, I quickly realized that there was no reference implementation from Sun or whatever they are called now for Win32 serial data com. I will use Linux later host it all later, but wanted a platform independent solution. I found RXTX as a potentially viable implementation and free! Now all I need is a Java implementation of a Modbus not surpisingly, that exists too at jamod.
What I hate is screen painting and UI work can be a pain. I wanted a simple java application to test read/write of registers and display them in float, long, int, unsigned int, binary, and hex formats. It would be a way for me to understand the details further and I would not have to deal feel guilty using commercial software as a trial offer. I digressed in my focus and looked for a tool that would allow me to create UI with minimal effort. I found JformDesigner to be flawless and will probably purchase it. It installed in Eclipse without a glitch and a Luddite like me was productive in a matter of hours. Anyway after a couple of days, I had the RXTX source compiled and my arduinoController source integrated to provide a simple test tool for me to experiment with. The screen shot is shown below. The challenging part was how to display longs and floats as Modbus does not support floats and longs per say and is something one does at the application layer (for you OSI compliant people)
Representing Float
For those that are interested, to get implement a float from a Modbus register representation, one just has to do this
Arduino Side
It takes two registers ( 16 bytes in total to represent the float). One may ask how does one mash a float into ints on the arduino side? I used the union
union
{
int regsf[2];
float value;
} mashedFloat;
I used it as holding area to mash my floats into to registers.
e.g. mashedFloat.value = powerfactor
regs[0] = mashedFloat.regsf[0];
regs[1] = mashedFloat.regsf[1];
Java Side
The data flows over standard Modbus to the host and on the Java side do something like this to unmash into a float.
float x = Float.intBitsToFloat( (mRegisters[i+1].toShort() & 0xffff) << 16 | (mRegisters[ i].toShort() & 0xffff) );
Modbus Registers
I captured how I will represent my power metrics from the main panel and send over Modbus. Rather than waste 2 registers for floats to represent something like 118.1 volts I will cast it into a single register as a 1181 and convert back on the host. The reason for this, on the Arduino Duemilanove, there is only 2k of RAM and I created my power calcs using classes and that is not cheap on memory. I plan on taking the Modbus code I found on the web and make it class as well. I will have other arduino’s in the house collecting spot power measurements and must ensure that I can upgrade code (read fix bugs) in a consistent manner.
Tag | Line Voltage | Units | Type | R/W | Offset |
EI-011 | Black Line Voltage | Vrms | short | R | 0 |
EIC-011 | Black Line Voltage Crest Factor | short | R | 1 | |
CI-011 | Black Line Current | Irms | short | R | 2 |
CIC-011 | Black Line Current Crest Factor | short | R | 3 | |
CI-021 | Red Line Current | Irms | short | R | 4 |
CIC-021 | Red Line Current Crest Factor | short | R | 5 | |
KD-011 | Black Delta T between Samples | ms | short | R | 6 |
KD-031 | Red Delta T between Samples | ms | short | R | 7 |
TI-001 | Local Temperature | C | short | R | 8 |
JI-011 | Black Line Real Power | Watt | float | R | 9 |
JI-021 | Red Line Real Power | Watt | float | R | 11 |
JIA-011 | Black Line Aparrent Power | VA | float | R | 13 |
JIA-021 | Red Line Aparrent Power | VA | float | R | 15 |
JIR-011 | Black Line Reactive Power | var | float | R | 17 |
JIR-021 | Red Line Reactive Power | var | float | R | 19 |
JIP-011 | Black Line Reactive Power Factor | float | R | 21 | |
JIP-021 | Red Line Power Power Factor | float | R | 23 | |
GC-001 | Display Mode | short | W | 30 | |
GC-002 | Number of samples per calculation | short | W | 31 | |
KC-001 | Time sync (unix time) | s | long | W | 32 |
CO2 and kW*hr
On the arduino side, the CO2 produced and the kWatt*hr are accumulated over a 24 hour period and displayed on the LCD. I plan computing those on the host side rather than send over Modbus . I have all the raw data to do that and do statistical operations as well as part of the data historian. e.g. average CO2 per day, Standard Deviation, etc.