How I Monitor Power

Note, there are several updates to this device described after the initial description.  Scroll down to see them.

I'm using current transformers (200A) that clip around the main power lines coming into the house.  These feed one of the analog inputs to an Arduino Duemilanove.  I also sample the wall power level to give me a voltage reference and use a basic wall wart for power.  Originally I had a Wishield for wifi since there is no network connection near the power panel, but Wifi proved to unreliable over time.  I changed my link to an XBee and eventually installed them all over the house.

The distance from my power monitor to the House Controller was through a number of walls and proved to be too much for the little XBee to do.  I installed an intermediate XBee roughly half way between the two devices and the store-forward capabilities of the XBees took care of the problem nicely.

Every couple of seconds the Arduino samples the power levels, calculates power and holds the values in variables. Every 10 seconds I transmit the data over the XBee network to the House Controller which in turn forwards it with other data from the house on a minute basis to several web based data services.  The reason I transmit it every 10 seconds is to update the Power Display I have on a wall that tells me the current power usage at a glance.

So, it's power panel to Arduino to XBee to House Controller to the web.  Confused yet?  

I'm only serving comma separated values so they're easy to parse.  In order they are, real power, apparent power, power factor, rms current, rms voltage and frequency.  This makes it really easy to grab the data and forward it using simple code.

Details on the Implementation

Somehow, I needed to measure the current flowing through the wires into the house.  There are a number of devices out there that can do this, but they're expensive, won't work on my house, inadequate or the company wouldn't respond to questions.  And yes, I did try to call them and even left messages.  But prowling the web looking at these devices I discovered a little component called the current transformer.

These things are a coil of wire that wraps around the wire and inductively measures the power flowing through a wire.  There are a ton of web descriptions of these devices so learning about them was relatively easy; finding one at a reasonable price was a different matter.  Finally, I found a nice device that would work at my house.  I have a 400 Amp service that splits into two 200 Amp distributions.  I'm currently only using half of it for 200 Amps but the wires leading to it are a little over a half inch in diameter.  I actually broke the first device I tried by forcing it over the wire.


Here are the two devices, one on each leg of the 240 split phase mains we have here in the US.  They were not hard to install; just clip them around the mains and run the wire out of the box.  There's very little risk of shock since the wires are insulated and you don't have to touch them to clip the CT (current transformer) around the wire.  They tended to slip down the wire so a couple of plastic ties hold them in place.

You can actually tie these in series, attach a multimeter and get a reasonable indication of the power usage by watching the voltage rise and fall as you turn on appliances.  The voltage output has to be compared against some standard before you actually know how much power you're using, but you can certainly tell they are working.

The CTs are available from ITeadStudio and usually have about a two week lead time.  Besides the 200 Amp version I used, there are other styles and ratings available.  Just be sure to get one big enough to go around the wire.

Most of my implementation was blatantly stolen from Trystan Lea.  Please visit his site at http://openenergymonitor.org/emon/ for an in-depth discussion of his ongoing implementation.  I took his Arduino code for power monitoring, modified it to work with two current transformers, and added network code to serve data based on a simple html request.  Trystan has single phase 240 power and didn’t need to consider using double CTs, but don’t worry, you simply tie the two of them in series if you have split phase 220.  My device hasn’t made it past the breadboard stage.  Why bother right now?  It works fine and I can get back to it anytime.


Original Device


The transformer on the left is a 10V center taped step down to provide a reference for the AC mains.  The wires coming in the center are the outputs from the CTs and are tied in series.  I use the center connection of the CTs to calibrate a single CT; one has to do this only once in the beginning.  Yes, I know that the transformer could be used to power the Arduino, that will come in time, but for now…it works, don’t fix it.  The wire leaving the Arduino and looping up to the right is the Wifi antenna; I got the Wishield with the separate antenna to extend the range and prevent worrying about where I put the device.

My future plans for this device are to add screw terminals for the incoming wires, get power from the step down transformer removing the wall wart and solder the various parts down on a proto board to pretty it up.  Heck, someday I might actually mount it on a pretty plastic base instead of the piece of plywood I found.  I’ll never cover it up though since it’s too much fun to show off the circuitry.

Trystan’s site (http://openenergymonitor.org/emon/) has tons of details on how the measurements are made and links to the source he used.  Each implementation will have some nuance that will need adaptation though so use his work as a starting example; consider my work as a recreation and proof of concept.  But basically rapid measurements of the instantaneous voltage and current are squared, summed and averaged to get the Vrms and Irms.  These are used along with the power factor to get a fairly accurate measure of real power usage.  I simply combined this with a very simple web server to pass the data along.


Update March19, 2011:  I had a failure of a WiShield in the power display that I will detail on that page later, but this pointed out that I need to have a wireless communication path that has massive availability.  I chose XBee as the tool to use.  Since this entire set of projects is for saving power, I started with the power monitor.  After doing a bunch of work to enable the device to send over XBee radio I realized I had forgotten how I had built the darn thing.  So I reverse engineered my own device to get the schematic and am posting it here to help other folks and provide a reference for myself next time.


Simple isn't it?  Nothing but a couple of voltage sources and dividers to scale the values for the Arduino to read.

The Arduino Sketch #1, Using Ethernet

//Basic energy monitoring sketch plus kwh and frequency calc - by Trystan Lea
//Licenced under GNU General Public Licence more details here
// openenergymonitor.org
/*
 * Credits:
 * Most of the power measurement and calculations were invented by Trystan Lea and documented at
 * http://openenergymonitor.org/.  I modified it for the split phase 240 in residential use in the U.S.
 * I'm using a ladyada boot rom (purchased directly from her site) to overcome weak network problems
 * and multiple vulnerable arduinos.  A lot of the remaining code was taken from example sketches
 * supplied by the Arduino site www.arduino.cc
 *
 * Open source rules!
 * Dave Thompson
 */


//Sketch measures voltage and current.
//and then calculates useful values like real power,
//apparent power, powerfactor, Vrms, Irms, frequency and kwh.

#include <WiServer.h>
#include <avr/wdt.h>

#define WIRELESS_MODE_INFRA 1
#define WIRELESS_MODE_ADHOC 2

// Wireless configuration parameters ----------------------------------------
unsigned char local_ip[] = {192,168,0,200}; // IP address of WiShield
unsigned char gateway_ip[] = {192,168,0,1}; // router or gateway IP address
unsigned char subnet_mask[] = {255,255,255,0}; // subnet mask for the local network
PROGMEM const prog_char ssid[] = {"whatever"}; // max 32 bytes

unsigned char security_type = 1; // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2

// WPA/WPA2 passphrase
const prog_char security_passphrase[] PROGMEM = {"whatever"}; // max 64 characters

// WEP 128-bit keys
// sample HEX keys
prog_uchar wep_keys[] PROGMEM = { 0x11, 0x11, 0x11, 0x11, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 0
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 1
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 2
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Key 3
};

// setup the wireless mode
// infrastructure - connect to AP
// adhoc - connect to another WiFi device
unsigned char wireless_mode = WIRELESS_MODE_INFRA;

unsigned char ssid_len;
unsigned char security_passphrase_len;
// End of wireless configuration parameters ----------------------------------------


//Setup variables
int numberOfSamples = 3000;

//Set Voltage and current input pins
int inPinV = 4;
int inPinI = 5;

//Calibration coeficients
double VCAL = 0.592;
double ICAL = 03.2;
double PHASECAL = 0.1;

//Sample variables
int lastSampleV,lastSampleI,sampleV,sampleI;

//Filter variables
double lastFilteredV, lastFilteredI, filteredV, filteredI = 0;
double filterTemp;

//Stores the phase calibrated instantaneous voltage.
double calibratedV;

//Power calculation variables
double sqI,sqV,instP,sumI,sumV,sumP;

//Useful value variables
double realPower,
       apparentPower,
       powerFactor,
       Vrms,
       Irms;

#define NETTIMECHECK 120
long netTimeout = 0;  // counter to check for net activity    
    
  //--ENERGY MEASURMENT VARIABLES------------------------------
    //Calculation of kwh

    //time taken since last measurment timems = tmillis - ltmillis;
    unsigned long ltmillis, tmillis, timems;
    //time when arduino is switched on... is it 0?
    unsigned long startmillis;
  
    //kwhTotal is cumulative kwh today, the other 3 are historical over the last 3 days for comparison.
    double kwhTotal =0.0;
  //-----------------------------------------------------------

  //--FREQUENCY MEASURMENT VARIABLES---------------------------
    //time in microseconds when the voltage waveform
    //last crossed zero.
    unsigned long vLastZeroMsec;
    //Micro seconds since last zero-crossing
    unsigned long vPeriod;
    //Sum of vPeriod's to obtain an average.
    unsigned long vPeriodSum;
    //Number of periods summed
    unsigned long vPeriodCount;
  
    //Frequency
    float freq;
  
    //Used to filter out fringe vPeriod readings.
    //Configured for 50Hz
    //- If your 60Hz set expPeriod = 16666
    unsigned long expPeriod = 16666;
    unsigned long filterWidth = 2000;
  //-----------------------------------------------------------

// This is my page serving function that generates web pages
boolean sendMyPage(char* URL) {
    /* The assumption is that if the code got here, the network is alive.  However
        if too much time passes without someone requesting data, the network may
        have died.  Therefore, measure the time and after it passes set a watchdog
        to expire.  In this routine the timer will be reset and the main loop will
        set the watchdog.
    */
    netTimeout = millis();        // made it, reset the timer
    wdt_reset();                  // turn off the watchdog
    wdt_disable();                // and disable it just in case
    Serial.println("net request");

    // Check if the requested URL matches "/"
    if (strcmp(URL, "/") == 0) {
        WiServer.print(realPower);
        WiServer.print(", ");
        WiServer.print(apparentPower);
        WiServer.print(", ");
        WiServer.print(powerFactor);
        WiServer.print(", ");
        WiServer.print(Irms);
        WiServer.print(", ");
        WiServer.print(Vrms);
        WiServer.print(", ");
        WiServer.print(freq);
        // URL was recognized
        return true;
    }
    // URL not found
    return false;
}

/* Measurement calculations */

int PwrCalcs()
{
  for (int n=0; n<numberOfSamples; n++) // gather samples
  {

     //Used for offset removal
     lastSampleV=sampleV;
     lastSampleI=sampleI;
     // wireless server has to have some time to work
     WiServer.server_task();
     //Read in voltage and current samples.
     sampleV = analogRead(inPinV);
     sampleI = analogRead(inPinI);

     //Used for offset removal
     lastFilteredV = filteredV;
     lastFilteredI = filteredI;

     //Digital high pass filters to remove 2.5V DC offset.
     filteredV = 0.996 * (lastFilteredV+sampleV-lastSampleV);
     filteredI = 0.996 * (lastFilteredI+sampleI-lastSampleI);

     //Phase calibration goes here.
     calibratedV = lastFilteredV + PHASECAL * (filteredV - lastFilteredV);

     //Root-mean-square method voltage
     //1) square voltage values
     sqV= calibratedV * calibratedV;
     //2) sum
     sumV += sqV;

     //Root-mean-square method current
     //1) square current values
     sqI = filteredI * filteredI;
     //2) sum
     sumI += sqI;

     //Instantaneous Power
     instP = abs(calibratedV * filteredI);
     //Sum
     sumP += instP;

     //--FREQUENCY MEASURMENT---------------------------        
     if (n==0) vLastZeroMsec = micros();

     //Check for zero crossing from less than zero to more than zero
     if (lastFilteredV < 0 && filteredV >= 0 && n>1)
     {
       //period of voltage waveform
       vPeriod = micros() - vLastZeroMsec;

       //Filteres out any erronous period measurments
       //Increases accuracy considerably
       if (vPeriod > (expPeriod-filterWidth) && vPeriod<(expPeriod+filterWidth))
       {
          vPeriodSum += vPeriod;
          vPeriodCount++;
       }
       vLastZeroMsec = micros();
     }
  } //end of sample gathering

  //Calculation of the root of the mean of the voltage and current squared (rms)
  //Calibration coeficients applied.
  Vrms = VCAL*sqrt(sumV / numberOfSamples);
  Irms = ICAL*sqrt(sumI / numberOfSamples);

  //Calculation power values
  realPower = VCAL*ICAL*sumP / numberOfSamples;
  apparentPower = Vrms * Irms;
  powerFactor = realPower / apparentPower;

  //FREQUENCY CALCULATION--------------------------
  freq = (1000000.0 * vPeriodCount) / vPeriodSum;
    
  vPeriodSum=0;
  vPeriodCount=0;
  //------------------------------------------------

  //--ENERGY MEASURMENT CALCULATION----------------  
      
  //Calculate amount of time since last realpower measurment.
  ltmillis = tmillis;
  tmillis = millis();
  timems = tmillis - ltmillis;
    
  //Calculate number of kwh consumed.
  //kwhTotal = kwhTotal + ((realPower/1000.0) * 1.0/3600.0 * (timems/1000.0));

  //Output to serial
  Serial.print("RP=");
  Serial.print(realPower);
  Serial.print(" AP=");
  Serial.print(apparentPower);
  Serial.print(" PF=");
  Serial.print(powerFactor);
  Serial.print(" V=");
  Serial.print(Vrms);
  Serial.print(" I=");
  Serial.print(Irms);
  Serial.print(" KW=");
  Serial.print(kwhTotal);
  Serial.print(" F=");
  Serial.println(freq);

    //Reset accumulators
  sumV = 0;
  sumI = 0;
  sumP = 0;
}

void setup()
{
  
  Serial.begin(57600);
  Serial.println("Initialize web server");

  wdt_enable(WDTO_8S);          // I'm giving the network 8 seconds to set itself up
  // Initialize WiServer and have it use the sendMyPage function to serve pages
  WiServer.init(sendMyPage);
  // Enable Serial output and ask WiServer to generate log messages (optional)
  wdt_reset();                  // made it, turn off the watchdog until things start working
  wdt_disable();
  Serial.println("Enable webserver");
  WiServer.setIndicatorPins(5, 6);              //This could make it fun to monitor.
                                                //However, the Wishield uses 2,8,9,10,11,12,13
                                              
                                              

  //debug mode for webserver
  //WiServer.enableVerboseMode(true);

  netTimeout = millis();               // timer to make sure the net is active

  //--ENERGY MEASURMENT SETUP--------------------------------
  //Calculation of kwh
  tmillis = millis();
  startmillis=tmillis;
  //---------------------------------------------------------
}

void loop()
{
    // get power calcs into variables
  PwrCalcs();
  // Run WiServer
  WiServer.server_task();
  delay(100);
  if ((millis() - netTimeout) >= (NETTIMECHECK * 1000))  //has too much time passed?
  {
    wdt_enable(WDTO_8S);    // eight seconds from now the device will reboot
    Serial.println("net timeout, rebooting");
    while(1) {}
  }
}


Update April 16,2012: After literally months of perfect operation, the device failed.  I really don't have a clue what happened, but it quit transmitting power information over my XBee network.  A simple reset got it running again which indicates the problem is, most likely, software, not hardware.  I didn't get enough to fully understand the failure so I really don't know what to fix.  But, since the device has been running really well for months, I just decided to put in an automatic reboot on a periodic basis to clean out any problems that may be building up in the code.

Initially, I wanted to get the correct time from the XBee network and set the Arduino clock for real, but when the Arduino is spending most of its time calculating, it doesn't leave much time for decoding a semi-constant stream of XBee traffic.  See, each power reading takes about a second and the incoming data can easily get lost during that second.  So, I just gave up on having the correct time on the little device.  I added the timeAlarm library for the Arduino playground to the device to handle timing the reset.  This allowed me to set up a timer that causes the device to send the power data every 5 seconds.  This stuff worked perfectly.  I don't know when the device will reset exactly, but it will at roughly 24 hour intervals starting from when it last rebooted.

When I came here to update this blog, I noticed that I never posted the code that uses my XBee network instead of the WiShield and ethernet.  I also noticed that the drawing of the home network and photo of the device are way out of date.  Guess I'll take care of updating those.  I want to keep the WiShield code online to help people that want a web based device, so I'll have both examples here to confuse the reader a little more.

Arduino Sketch #2, Using XBee network

/*
Version 6 of the monitor; I had the device hang up for around 12 hours not
reporting the proper power over the XBee network.  The house controller was seeing a
power usage of zero and assumed (correctly) that this was invalid and didn't
update pachube.  I didn't think to get enough data from the various devices around
the house before resetting the monitor, so I don't know exactly what happened.

However, the monitor doesn't reset itself to clean out any problems, and since the
reset fixed it; it must have been a software problem.  The easiest way to fix this
without information is to just have the board reset itself periodically.  So, I'm
just setting the time to something and having it reboot every 24 hours.  That will
restart all the stuff and allow it come up cleanly.  To do this I added the timeAlarm
library.  There are two timers, one to report the power and the other to cause the
reset.  I also moved the reporting function into it's own routine partly because that
made it easier to hook it to a timer and partly to clean up the display logic.  Since
I have lots of memory on this device, I used sprintf() to format the string for transmission
This can also provide an example for folks trying to do something similar.


Version 5 of the monitor.  The first version was ethernet enabled and
used wifi to communicate.  Later, I added an XBee and transmitted the data over
it also.  Now, I removed the WiShield that allowed connection over the ethernet.
I was getting more and more hangups and resets over time.  I suspect there is a
problem in the code with large packets that occasionally travel around and the
device isn't supported anymore, why spend time fixing the code?
So the device transmits only over the XBee now.  Which makes it a remote power
monitor that forwards data to another device that can listen to it.

Actually, this isn't a bad idea at all.  I can pick up the data from any other
device around the house and do whatever I want with it.
/*
 * Credits:
 * Most of the power measurement and calculations were invented by Trystan Lea and documented at
 * http://openenergymonitor.org/.  I modified it for the split phase 240 in residential use in the U.S.
 * I'm using a ladyada boot rom (purchased directly from her site) to overcome unexpected problems
 * and multiple vulnerable arduinos.  A lot of the remaining code was taken from example sketches
 * supplied by the Arduino site www.arduino.cc
 * Basic energy monitoring sketch plus kwh and frequency calc - by Trystan Lea
 * Licenced under GNU General Public Licence more details here
 * openenergymonitor.org
 *
 * Open source rules!
 * Pin usage:
 *   3,4 for newsoftserial XBee comm
 *   Analog 0 current sensor
 *   Analog 1 voltage sensor
 */

//Sketch measures voltage and current.
//and then calculates useful values like real power,
//apparent power, powerfactor, Vrms, Irms, frequency and kwh.

#include <avr/wdt.h>
#include <MemoryFree.h>
#include <avr/pgmspace.h>
#include <SoftwareSerial.h>
#include <Time.h>
#include <TimeAlarms.h>


SoftwareSerial xbeeSerial = SoftwareSerial(3,4);
char Dbuf[100];   // general purpose buffer
//Setup variables
int numberOfSamples = 3000;

//Set Voltage and current input pins
int inPinV = 4;
int inPinI = 5;

//Calibration coeficients
double VCAL = 0.592;
double ICAL = 03.2;
double PHASECAL = 0.1;

//Sample variables
int lastSampleV,lastSampleI,sampleV,sampleI;

//Filter variables
double lastFilteredV, lastFilteredI, filteredV, filteredI = 0;
double filterTemp;

//Stores the phase calibrated instantaneous voltage.
double calibratedV;

//Power calculation variables
double sqI,sqV,instP,sumI,sumV,sumP;

//Useful value variables
double realPower,
       apparentPower,
       powerFactor,
       Vrms,
       Irms;

  //--ENERGY MEASURMENT VARIABLES------------------------------
    //Calculation of kwh

    //time taken since last measurment timems = tmillis - ltmillis;
    unsigned long ltmillis, tmillis, timems;
    //time when arduino is switched on... is it 0?
    unsigned long startmillis;
 
  //--FREQUENCY MEASURMENT VARIABLES---------------------------
    //time in microseconds when the voltage waveform
    //last crossed zero.
    unsigned long vLastZeroMsec;
    //Micro seconds since last zero-crossing
    unsigned long vPeriod;
    //Sum of vPeriod's to obtain an average.
    unsigned long vPeriodSum;
    //Number of periods summed
    unsigned long vPeriodCount;
 
    //Frequency
    float freq;
 
    //Used to filter out fringe vPeriod readings.
    //Configured for 50Hz
    //- If your 60Hz set expPeriod = 16666
    unsigned long expPeriod = 16666;
    unsigned long filterWidth = 2000;
  //-----------------------------------------------------------

/* Measurement calculations */

void PwrCalcs()
{
  for (int n=0; n<numberOfSamples; n++) // gather samples
  {
     //Used for offset removal
     lastSampleV=sampleV;
     lastSampleI=sampleI;
     //Read in voltage and current samples.
     sampleV = analogRead(inPinV);
     sampleI = analogRead(inPinI);

     //Used for offset removal
     lastFilteredV = filteredV;
     lastFilteredI = filteredI;

     //Digital high pass filters to remove 2.5V DC offset.
     filteredV = 0.996 * (lastFilteredV+sampleV-lastSampleV);
     filteredI = 0.996 * (lastFilteredI+sampleI-lastSampleI);

     //Phase calibration goes here.
     calibratedV = lastFilteredV + PHASECAL * (filteredV - lastFilteredV);

     //Root-mean-square method voltage
     //1) square voltage values
     sqV= calibratedV * calibratedV;
     //2) sum
     sumV += sqV;
 
     //Root-mean-square method current
     //1) square current values
     sqI = filteredI * filteredI;
     //2) sum
     sumI += sqI;

     //Instantaneous Power
     instP = abs(calibratedV * filteredI);
     //Sum
     sumP += instP;
 
     //--FREQUENCY MEASURMENT---------------------------        
     if (n==0) vLastZeroMsec = micros();
 
     //Check for zero crossing from less than zero to more than zero
     if (lastFilteredV < 0 && filteredV >= 0 && n>1)
     {
       //period of voltage waveform
       vPeriod = micros() - vLastZeroMsec;

       //Filteres out any erronous period measurments
       //Increases accuracy considerably
       if (vPeriod > (expPeriod-filterWidth) && vPeriod<(expPeriod+filterWidth))
       {
          vPeriodSum += vPeriod;
          vPeriodCount++;
       }
       vLastZeroMsec = micros();
     }
  } //end of sample gathering

  //Calculation of the root of the mean of the voltage and current squared (rms)
  //Calibration coeficients applied.
  Vrms = VCAL*sqrt(sumV / numberOfSamples);
  Irms = ICAL*sqrt(sumI / numberOfSamples);

  //Calculation power values
  realPower = VCAL*ICAL*sumP / numberOfSamples;
  apparentPower = Vrms * Irms;
  powerFactor = realPower / apparentPower;

  //FREQUENCY CALCULATION--------------------------
  freq = (1000000.0 * vPeriodCount) / vPeriodSum;
   
  vPeriodSum=0;
  vPeriodCount=0;
  //------------------------------------------------

  //--ENERGY MEASURMENT CALCULATION----------------  
     
  //Calculate amount of time since last realpower measurment.
  ltmillis = tmillis;
  tmillis = millis();
  timems = tmillis - ltmillis;
   
  //Reset accumulators
  sumV = 0;
  sumI = 0;
  sumP = 0;
}

// this function outputs the current free memory to the serial port
// really nice to use in debugging and making sure the board doesn't
// fail running out of memory
void showMem(){
  strcpy_P(Dbuf,PSTR("Mem = "));
  Serial.print(Dbuf);
  Serial.println(freeMemory());
}

// this set of functions are for a software reset of the board
// the reset function allows a call to location zero which will emulate a reset
// the resetMe funtion allows a normal call from the timer routines
void(* resetFunc) (void) = 0; //declare reset function @ address 0

void resetMe(){  // for periodic resets to be sure nothing clogs it up
  Serial.println("Periodic Reset - Normal Operation");
  resetFunc();
}

// this little function will return the first two digits after the decimal
// point of a float as an int to help with sprintf() (won't work for negative values)
int frac(float num){
  return( (num - (int)num) * 100);
}

// report the power usage over XBee network and out the Serial Port
void reportPower(){
  memset(Dbuf,0,sizeof(Dbuf));
  Serial.print("Broadcast--");
  // first construct the payload line
  sprintf(Dbuf,"Power,%d.%02d,%d.%02d,%d.%02d,%d.%02d,%d.%02d,%d.%02d\r",
       (int)realPower, frac(realPower),
       (int)apparentPower, frac(apparentPower),
       (int)powerFactor, frac(powerFactor),
       (int)Vrms, frac(Vrms),
       (int)Irms, frac(Irms),
       (int)freq, frac(freq));
  // Display it on the serial monitor for debugging
  Serial.print(Dbuf);
  Serial.print("\n");
  xbeeSerial.print(Dbuf);  // out to XBee
}

void setup()
{
  Serial.begin(9600);
  xbeeSerial.begin(9600);
 
  //--ENERGY MEASURMENT SETUP--------------------------------
  tmillis = millis();
  startmillis=tmillis;
  //---------------------------------------------------------
  Serial.println("I'm alive ");
  Serial.println("Setting timer for reporting");
  /* I really don't care what time it is on this device
     it just measure time and reports.  But, I want the timer capability
     to allow a reset every 24 hours and to handle the reporting function
     so I just set the time to something reasonable and get on with the
     rest of the work.
  */
  setTime(0,0,0,1,1,12);
  Alarm.timerRepeat(5, reportPower);   // report the power usage every 5 seconds
  Alarm.alarmRepeat(23,59,0,resetMe);  // periodic reset to keep things cleaned up
                                       // I use a lot of libraries and sometimes they have bugs
                                       // as well as hang ups from various hardware devices
  showMem();                           // to make sure I don't make it too big to fit in ram reliably
  Serial.println("Init done");
  xbeeSerial.println("Is the XBee there?");
  wdt_enable(WDTO_8S);          // No more than 8 seconds of inactivity
}

/*
  The loop() just calculates power over and over again.  There is a timer
  set in setup() that causes the device to report every few seconds.
  The loop() also resets the watchdog timer so it doesn't time out.
*/
void loop()
{
  // get power calcs into variables
  PwrCalcs();
  wdt_reset();                   // watchdog timer set back to zero
  Alarm.delay(0);                // This causes the alarm timer to update
}


Notice that the comments at the top are almost as long as the code?  Yes, I have trouble keeping track of the various problems, changes, and solutions to my devices over months of time.  It's funny how often I come here to see what I did about a particular problem.  Nice way to keep a diary of this kind of thing.  Notice also that the loop() routine only calculates the power, updates the watchdog, and updates the alarm timer.  If it hangs in a loop somewhere the watchdog will reset it and start over.  Every 5 seconds the alarm code causes it to send the data; that's about as simple an implementation as I can come up with. The timers are set up in the setup() routine and the reporting is done using the callback routine reportPower().  The XBee for this device is set up in transparent mode; this is a specific mode for the XBees and you'll understand this when you start working with the little devices, but it means that I don't have to have special encoding or decoding software to use it.

Device as of April 16, 2012


Three people now have asked me how to put the CTs in series.  It's actually pretty simple to do: first put them on  the incoming power wire, see the picture of my power panel with the CTs installed.  Then hook one color wire from one CT to the other color wire from the other CT.  The remaining two wires are your input.  Measure the input and then hook two wire of the same color together and measure again.  You want the highest reading.  Notice above that I have a black and white wire running to the center of the three screw input block; that's where I short them together.  I just wrapped them together and screwed them down.  The other two wires on the other terminals are my input.

Now, I'll let the device run until the next problem crops up.

Update, February 14, 2013: I decided to move the software forward from Arduino IDE 21 to the latest, 1.0.3.  I expected this to be a pain, so I decided to make it worse and convert the XBee code to use the library created by Andrew Rapp.  I noticed a while back that the library had been updated to work with Software Serial and supported the multiple serial ports on the Mega2560 board.  This means I can still use the software serial pins and have the normal serial pins for debugging and other things.

Well, it turned out to be pretty painless.  Yes, there were a few items that I had to work out, but it took less than a morning to make all the changes and return the device to service.  The code was greatly simplified by using the library, although I now have the XBee running in API mode 2 to fit with the library.  This is OK though since I discovered that I can monitor it with a little XBee sniffer I put together, or tell the XBee to transmit in broadcast for a while if I think there are problems.  Here's the updated code:

The Arduino Sketch

/*
Version 9, The changes to this device to stop using XBee broadcast fixed all the
problems with it failing over time.  A month ago I discovered the XBee library
had been updated to support the SoftwareSerial library and this means I can now
use the library to simplify the code I have to write, and rejoin the mainstream
of XBee work.  This version has the library associated and it made the XBee send
much, much simpler.  I don't check the transmit response frame to see what happened
with the transmission.  I will if there seems to be a problem at any point.  However,
that always brings up the problem of what to do with an error report.  I have
nowhere to send it.

Version 8, Well, as I add devices to the network, I have to stop using broadcast.
Each device is echoing the broadcast and totally clogging up the network with
retransmissions.  So, this version is the same as 7 except it sends the packets to
the house controller.  The house controller is responsible for updating status now,
so that isn't too bad.

Version 7 of the monitor; still trying to get around the problem of short lines.
I got a clue when it stopped a couple of days ago.  Monitoring the XBee traffic, it
was stopping in exactly the same place each time.  Then after a second or two it would
continue.  The lines were always complete, but characters inside were separated by a
couple of seconds.  This meant that the clock or something else was able to get in
the middle of the transmission.  This was happening on every single line, so the
controller couldn't decode the transmission.  I switched the XBee to API mode and put
code in to support it so that each packet was complete.  Now to wait a week or so to
see if this gets rid of the problem.  Months of working just fine and then this shows
up.  Funny how something like this hides forever.

Version 6 of the monitor; I had the device hang up for around 12 hours not
reporting the proper power over the XBee network.  The house controller was seeing a
power usage of zero and assumed (correctly) that this was invalid and didn't
update pachube.  I didn't think to get enough data from the various devices around
the house before resetting the monitor, so I don't know exactly what happened.

However, the monitor doesn't reset itself to clean out any problems, and since the
reset fixed it; it must have been a software problem.  The easiest way to fix this
without information is to just have the board reset itself periodically.  So, I'm
just setting the time to something and having it reboot every 24 hours.  That will
restart all the stuff and allow it come up cleanly.  To do this I added the timeAlarm
library.  There are two timers, one to report the power and the other to cause the
reset.  I also moved the reporting function into it's own routine partly because that
made it easier to hook it to a timer and partly to clean up the display logic.  Since
I have lots of memory on this device, I used sprintf() to format the string for transmission
This can also provide an example for folks trying to do something similar.


Version 5 of the monitor.  The first version was ethernet enabled and
used wifi to communicate.  Later, I added an XBee and transmitted the data over
it also.  Now, I removed the WiShield that allowed connection over the ethernet.
I was getting more and more hangups and resets over time.  I suspect there is a
problem in the code with large packets that occasionally travel around and the
device isn't supported anymore, why spend time fixing the code?
So the device transmits only over the XBee now.  Which makes it a remote power
monitor that forwards data to another device that can listen to it.

Actually, this isn't a bad idea at all.  I can pick up the data from any other
device around the house and do whatever I want with it.
/*
 * Credits:
 * Most of the power measurement and calculations were invented by Trystan Lea and documented at
 * http://openenergymonitor.org/.  I modified it for the split phase 240 in residential use in the U.S.
 * I'm using a ladyada boot rom (purchased directly from her site) to overcome unexpected problems
 * and multiple vulnerable arduinos.  A lot of the remaining code was taken from example sketches
 * supplied by the Arduino site www.arduino.cc
 * Basic energy monitoring sketch plus kwh and frequency calc - by Trystan Lea
 * Licenced under GNU General Public Licence more details here
 * openenergymonitor.org
 *
 * Open source rules!
 * Pin usage:
 *   3,4 for newsoftserial XBee comm
 *   Analog 0 current sensor
 *   Analog 1 voltage sensor
 */

//Sketch measures voltage and current.
//and then calculates useful values like real power,
//apparent power, powerfactor, Vrms, Irms, frequency and kwh.

#include <avr/wdt.h>
#include <MemoryFree.h>
#include <avr/pgmspace.h>
#include <SoftwareSerial.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <XBee.h>

char verNum[] = "Version 9";

SoftwareSerial xbeeSerial = SoftwareSerial(3,4);
XBee xbee = XBee();

char Dbuf[100];   // general purpose buffer
//Setup variables
int numberOfSamples = 3000;

//Set Voltage and current input pins
int inPinV = 4;
int inPinI = 5;

//Calibration coeficients
double VCAL = 0.592;
double ICAL = 03.2;
double PHASECAL = 0.1;

//Sample variables
int lastSampleV,lastSampleI,sampleV,sampleI;

//Filter variables
double lastFilteredV, lastFilteredI, filteredV, filteredI = 0;
double filterTemp;

//Stores the phase calibrated instantaneous voltage.
double calibratedV;

//Power calculation variables
double sqI,sqV,instP,sumI,sumV,sumP;

//Useful value variables
double realPower,
       apparentPower,
       powerFactor,
       Vrms,
       Irms;

  //--ENERGY MEASURMENT VARIABLES------------------------------
    //Calculation of kwh

    //time taken since last measurment timems = tmillis - ltmillis;
    unsigned long ltmillis, tmillis, timems;
    //time when arduino is switched on... is it 0?
    unsigned long startmillis;
   
  //--FREQUENCY MEASURMENT VARIABLES---------------------------
    //time in microseconds when the voltage waveform
    //last crossed zero.
    unsigned long vLastZeroMsec;
    //Micro seconds since last zero-crossing
    unsigned long vPeriod;
    //Sum of vPeriod's to obtain an average.
    unsigned long vPeriodSum;
    //Number of periods summed
    unsigned long vPeriodCount;
   
    //Frequency
    float freq;
   
    //Used to filter out fringe vPeriod readings.
    //Configured for 50Hz
    //- If your 60Hz set expPeriod = 16666
    unsigned long expPeriod = 16666;
    unsigned long filterWidth = 2000;
  //-----------------------------------------------------------

/* Measurement calculations */

void PwrCalcs()
{
  for (int n=0; n<numberOfSamples; n++) // gather samples
  {
     //Used for offset removal
     lastSampleV=sampleV;
     lastSampleI=sampleI;
     //Read in voltage and current samples.  
     sampleV = analogRead(inPinV);
     sampleI = analogRead(inPinI);

     //Used for offset removal
     lastFilteredV = filteredV;
     lastFilteredI = filteredI;
 
     //Digital high pass filters to remove 2.5V DC offset.
     filteredV = 0.996 * (lastFilteredV+sampleV-lastSampleV);
     filteredI = 0.996 * (lastFilteredI+sampleI-lastSampleI);

     //Phase calibration goes here.
     calibratedV = lastFilteredV + PHASECAL * (filteredV - lastFilteredV);
 
     //Root-mean-square method voltage
     //1) square voltage values
     sqV= calibratedV * calibratedV;
     //2) sum
     sumV += sqV;
 
     //Root-mean-square method current
     //1) square current values
     sqI = filteredI * filteredI;
     //2) sum
     sumI += sqI;

     //Instantaneous Power
     instP = abs(calibratedV * filteredI);
     //Sum
     sumP += instP;
 
     //--FREQUENCY MEASURMENT---------------------------          
     if (n==0) vLastZeroMsec = micros();
 
     //Check for zero crossing from less than zero to more than zero
     if (lastFilteredV < 0 && filteredV >= 0 && n>1)
     {
       //period of voltage waveform
       vPeriod = micros() - vLastZeroMsec;

       //Filteres out any erronous period measurments
       //Increases accuracy considerably
       if (vPeriod > (expPeriod-filterWidth) && vPeriod<(expPeriod+filterWidth))
       {
          vPeriodSum += vPeriod;
          vPeriodCount++;
       }
       vLastZeroMsec = micros();
     }
  } //end of sample gathering

  //Calculation of the root of the mean of the voltage and current squared (rms)
  //Calibration coeficients applied.
  Vrms = VCAL*sqrt(sumV / numberOfSamples);
  Irms = ICAL*sqrt(sumI / numberOfSamples);

  //Calculation power values
  realPower = VCAL*ICAL*sumP / numberOfSamples;
  apparentPower = Vrms * Irms;
  powerFactor = realPower / apparentPower;

  //FREQUENCY CALCULATION--------------------------
  freq = (1000000.0 * vPeriodCount) / vPeriodSum;
     
  vPeriodSum=0;
  vPeriodCount=0;
  //------------------------------------------------

  //--ENERGY MEASURMENT CALCULATION----------------    
       
  //Calculate amount of time since last realpower measurment.
  ltmillis = tmillis;
  tmillis = millis();
  timems = tmillis - ltmillis;
     
  //Reset accumulators
  sumV = 0;
  sumI = 0;
  sumP = 0;
}

// this function outputs the current free memory to the serial port
// really nice to use in debugging and making sure the board doesn't
// fail running out of memory
void showMem(){
  strcpy_P(Dbuf,PSTR("Mem = "));
  Serial.print(Dbuf);
  Serial.println(freeMemory());
}

// this set of functions are for a software reset of the board
// the reset function allows a call to location zero which will emulate a reset
// the resetMe funtion allows a normal call from the timer routines
void(* resetFunc) (void) = 0; //declare reset function @ address 0

void resetMe(){  // for periodic resets to be sure nothing clogs it up
  Serial.println("Periodic Reset - Normal Operation");
  resetFunc();
}

// this little function will return the first two digits after the decimal
// point of a float as an int to help with sprintf() (won't work for negative values)
int frac(float num){
  return( (num - (int)num) * 100);
}

// report the power usage over XBee network and out the Serial Port
void reportPower(){
  memset(Dbuf,0,sizeof(Dbuf));
  Serial.print("Broadcast--");
  // first construct the payload line
  sprintf(Dbuf,"Power,%d.%02d,%d.%02d,%d.%02d,%d.%02d,%d.%02d,%d.%02d\r",
       (int)realPower, frac(realPower),
       (int)apparentPower, frac(apparentPower),
       (int)powerFactor, frac(powerFactor),
       (int)Vrms, frac(Vrms),
       (int)Irms, frac(Irms),
       (int)freq, frac(freq));
  // Display it on the serial monitor for debugging
  Serial.print(Dbuf);
  Serial.print("\n");
  sendStatusXbee(Dbuf);
}

void setup()
{
  Serial.begin(9600);
  Serial.println(verNum);
  xbeeSerial.begin(9600);
  // This sets the XBee library to use the software serial port
  xbee.setSerial(xbeeSerial);

  //--ENERGY MEASURMENT SETUP--------------------------------
  tmillis = millis();
  startmillis=tmillis;
  //---------------------------------------------------------
  Serial.println("I'm alive ");
  Serial.println("Setting timer for reporting");
  /* I really don't care what time it is on this device
     it just measure time and reports.  But, I want the timer capability
     to allow a reset every 24 hours and to handle the reporting function
     so I just set the time to something reasonable and get on with the
     rest of the work.
  */
  setTime(0,0,0,1,1,12);
  Alarm.timerRepeat(5, reportPower);   // report the power usage every 5 seconds
  Alarm.alarmRepeat(23,59,0,resetMe);  // periodic reset to keep things cleaned up
                                       // I use a lot of libraries and sometimes they have bugs
                                       // as well as hang ups from various hardware devices
  showMem();                           // to make sure I don't make it too big to fit in ram reliably
  pinMode(6,OUTPUT);
  digitalWrite(6,LOW);
  Serial.println("Init done");
  wdt_enable(WDTO_8S);          // No more than 8 seconds of inactivity
 
}

/*
  The loop() just calculates power over and over again.  There is a timer
  set in setup() that causes the device to report every few seconds.
  The loop() also resets the watchdog timer so it doesn't time out.
*/
void loop()
{
  // get power calcs into variables
  PwrCalcs();
  wdt_reset();                   // watchdog timer set back to zero
  Alarm.delay(0);                // This causes the alarm timer to update
}


Of course, I have the XBee handling in a separate source file (these are known as 'tabs' in the Arduino IDE) so this is the code that resulted from moving to the XBee library:

The XBee 'tab'

XBeeAddress64 HouseController = XBeeAddress64(0x0013A200, 0x4055B0A6);
XBeeAddress64 Broadcast       = XBeeAddress64(0x00000000, 0x0000ffff);

void sendStatusXbee(char *msg){
  byte checksum = 0;
  char xbeeOut[100];
  int i, length;

  digitalWrite(6,HIGH);               // indicator light on
  Alarm.timerOnce(1, indicatorOff);   // Turn the indicator led off in a second
  ZBTxRequest zbtx = ZBTxRequest(HouseController, (uint8_t *)msg, strlen(msg));
  xbee.send(zbtx);
}

void indicatorOff(){
  digitalWrite(6,LOW);
}


Notice that I have both the addresses for the House Controller and Broadcast in the file.  All I have to do to revert to broadcast for debugging is to use the broadcast address.  Nice little capability; I may automate that in the future.

168 comments:

  1. Cool how you glued together various components to build a smart solution that really seems to pay off

    I saw your post on jeelabs and thought I'd just check your project out.

    ReplyDelete
  2. Thanks for visiting. This is, and has been, an interesting project that actually pays off.

    ReplyDelete
    Replies
    1. Hello Dave
      I need a code in C to implement RMS value of the line AC voltage

      Delete
    2. It's right up the page in the code box

      Delete
  3. Hello Dave, Nice work! do you mind if I link through to your write-up I'm sure it would be of great use to people. I have put a link at the bottom of the page here:
    http://openenergymonitor.org/emon/node/58

    Thanks, Trystan

    ReplyDelete
  4. Of course I don't mind. Especially since I stole so many ideas from you and your site.

    ReplyDelete
  5. As I understand it, you have put the two CT's on the 220V mains input wires in series so you are only using a single ADC channel on the Arduino. Is this accurate?

    Otherwise, nice work. I am building a similar system based on Trystan's info as well. Thanks for sharing.

    -Jon

    ReplyDelete
  6. Yes, the two CTs are in series on one input to the Arduino. I calibrated them one at a time using a current meter around the wire then hooked them up. If you get too low a level when you hook them in series reverse the phase on one of them. I did the final test with a 2KW load (large light) plugged into one side then the other.

    ReplyDelete
  7. Nice work and great website.

    Thanks for sharing.

    Dawn.

    ReplyDelete
  8. Hi, I noticed that you and Trystan Lea seem to disagree in the RMS calculation section 1).

    You square the CalibratedV (what Lea calls shiftedV), but Lea squares filteredV...

    It seems to me that you are probably correct, can you confirm that? Thanks!

    ReplyDelete
  9. Y'know, I'm not sure there's a significant difference. I chose to square the calibrated value because it matched the metering equipment I was using that way. I'm not sure why Trystan did it his way. However, I was able to read a commercial meter and compare it to mine and that gave me a bunch more confidence in the voltage reading.

    Basically, I wanted my values to be as close to a calibrated commercial source as I could get to keep the debugging and tweaking down.

    ReplyDelete
  10. I'm from Brazil and we have 2 x 110v phases and 1 neutral.

    How did you measure voltage on 2 phases? You wire your transformer only on one phase or each leg of transformer input on each phase and you don't use the neutral? Is it better to use two transformers to get two different reading from each phase?

    ReplyDelete
  11. Take a look at the pictures above, I used two CTs, one on the hot leg of each phase. You can then wire them in series to get the total power used or read each one in the code and add them together. To calibrate them, only hook one up and put a controlled load on that leg of the power.

    ReplyDelete
  12. Dave,

    I am trying to get my graphs to work in Pachube. Right now, I only have one graph and cannot figure out how to get multiple datastreams. How did you get yours to works.

    Thanks,

    Paul.

    ReplyDelete
  13. Notice in the sketch I sent a comma separated string of values, something like:

    100,200,300,400,500

    Pachube itself separated these out into separate data streams. At first I had forgotten a couple of things and sent about 10 items separated by strings and it took some time to figure out why I had too many datastreams showing up. I simply deleted the extras on pachube and corrected my code.

    So, each value in the csv (comma separated values) string is assigned to a data stream.

    I was too lazy to learn JSON or EML or the other methods when something this simple was available.

    ReplyDelete
  14. Dave,

    Thanks for your reply.

    I finally figured it out. If the content_length is larger than the length of the data being received it won't work.

    I just put in a number for my content_length. Do you have a formula to find the data length or did you just do it by putting in a numerical value too.

    Thanks,

    Paul.

    ReplyDelete
  15. I have two different devices that update to pachube right now. I'll be using only one in a couple of weeks. I'm moving my update operation to a more dedicated device. However, with the WiShield, it takes care of the length for me and I don't have to do anything. With an 'official' arduino ethernet board, I get the data string all formated then then do a strlen(dataString), send the standard header, with the length in it and lastly, the data string.

    Here's the code fragment that I use:

    strcpy_P(Dbuf2, PSTR("%d,%d,0.%d,%d.%02d,%d.%02d,%d.%02d"));
    sprintf(dataBuf,Dbuf2,
    (int)round(realPower),
    (int)round(apparentPower),
    (int)(powerFactor*100),
    (int)rmsCurrent,
    (int)(((rmsCurrent+0.005) - (int)rmsCurrent) * 100),
    (int)rmsVoltage,
    (int)(((rmsVoltage+0.005) - (int)rmsVoltage) * 100),
    (int)(frequency),
    (int)(((frequency+0.005) - (int)frequency) * 100));
    strcpy_P(Dbuf,PSTR("Pachube Connecting..."));
    Serial.print(Dbuf);
    if(pachube.connect()){
    strcpy_P(Dbuf,PSTR("OK"));
    lastConnectionTime = millis();
    Serial.println(Dbuf);
    tNow = now();
    strcpy_P(Dbuf,PSTR("PUT /api/feedNumber.csv HTTP/1.1\n"));
    pachube.print(Dbuf);
    strcpy_P(Dbuf,PSTR("Host: www.pachube.com\n"));
    pachube.print(Dbuf);
    strcpy_P(Dbuf,PSTR("X-PachubeApiKey:bunch of numbers\n"));
    pachube.print(Dbuf);
    strcpy_P(Dbuf,PSTR("Content-Length: "));
    pachube.print(Dbuf);
    pachube.println(strlen(dataBuf), DEC); // this has to be a println
    strcpy_P(Dbuf,PSTR("Content-Type: text/csv\n"));
    pachube.print(Dbuf);
    strcpy_P(Dbuf,PSTR("Connection: close\n"));
    pachube.println(Dbuf);
    pachube.println(dataBuf);
    pachube.stop();
    }

    Notice that I had some trouble with the darn floating point numbers getting them into a sprintf that doesn't support floats. But that was easier than writing special code for it.

    Hope this helps

    ReplyDelete
  16. Dave,

    Cool. Thanks for the code. I had problem with floats too. So I just stuck with client.print instead of sprintf but it is kind of a hack job and I would like to pretty it up.

    cheers,

    Paul.

    ReplyDelete
  17. The information you have on this page is great, and it's prompted me to start getting into Arduino projects. I've been able to pretty much piece together the general way I could go about duplicating your work, but I cannot seem to source the ac/ac step-down transformer.

    Any suggestions would be greatly appreciated.

    ReplyDelete
  18. Something like this will work fine. http://search.digikey.com/scripts/DkSearch/dksus.dll?Cat=590573&k=T1004-ND It's a wall wart for supplying power for a clock or something. I picked mine up at Fry's Electronics when I was there drooling over other stuff. Just look for something that will take line voltage to 6-12VAC. The only hard requirement is that it be AC to AC, which leave out cell phone chargers and such. You can tailor the voltage divider to provide reference voltage to the Arduino which only needs a volt or two.

    ReplyDelete
  19. Hi Dave!

    Great work! Can u explain where this come from (mathematically)?

    "kwhTotal = kwhTotal + ((realPower/1000.0) * 1.0/3600.0 * (timems/1000.0));"

    Thanks!

    Gabriel

    ReplyDelete
  20. add real power / 1000 (power in watts) / number of seconds in an hour * how long it has really been in seconds

    Notice that I don't actually use this number. There is a small amount of drift from what I read and what they read. It's a tiny amount, but it adds up over time to totally confuse me. I could have tailored this more and added corrections, but what I was really interested in was what I'm using right now. Controlling it on an ongoing basis is better than looking at it at the end of the month.

    ReplyDelete
  21. Hey, this is a really cool setup, I'm building a project where the arduino acts as a webserver and hosts a simple html page to control relays. I cannot perform exactly what I like though because of the below errors. Seems the sample libraries we used are the same so I thought maybe you ran into this problem too. The sample code Webserver works and I can host a html page in one big string, but I want to print different things to the server to change/update the website on current values. This may be a bit different but you seem knowledgeable so I thought I would ask. Also, having trouble with the get request to receive data when a button on the webpage is clicked. Thank you very much.

    C:\Users\COLINV~1\AppData\Local\Temp\build8672606563252562455.tmp/sketch_may11a.cpp:283: undefined reference to `WiServer'
    C:\Users\COLINV~1\AppData\Local\Temp\build8672606563252562455.tmp/sketch_may11a.cpp:173: undefined reference to `Server::server_task()'

    ReplyDelete
  22. This looks like the compiler can't find the library. The source needs to be in the library directory of the Arduing IDE and you have to restart the IDE before it will know it is there. Also, it can happen if you forget the #include for the WiShield software up at the top of the module.

    ReplyDelete
  23. Dear, The port analog arduino number of A4 and A5 I turn on the circuit above? I can connect the output of 5 V arduino too?

    ReplyDelete
  24. Yes, I used the Arduino 5V and ground.

    ReplyDelete
  25. Why are you using 320Ohm burden resistor with this CT?

    I made some calculations and on 3.3v I would use 36Ohm resistors or 56Ohm on 5v.

    ReplyDelete
  26. If I remember right, it was what I had on hand at the time. It's easy to correct for values (within reason) in the code. That's the beauty of using a computer.

    ReplyDelete
  27. I truly like to reading your post. Thank you so much for taking the time to share such a nice information. I'll definitely add this great post in my article section.
    Freight Forwarding Software

    ReplyDelete
  28. I was looking for a way to send you a private email, but it doesn't look like there's a way. I hate to offer any feedback that isn't completely constructive, so I hope this helps you at some point in the project:

    This is a great project and I love what you're doing. Just one issue that might really confuse you or someone else at some point trying to duplicate this(unless I'm really missing something).

    The way you have this configured is not really measuring what you think it's measuring. I'm sure you've calibrated out some error but various reactive appliances will not read correctly (unless, like I said, I'm really missing something). The two 110 lines coming in to your home are two separate feeds. They are 180 degrees out of phase and power various device in your home either completely separately, or in the case of a 220 dryer, as a combined (but out of phase) load. From your photo, you've got the CT's placed out of phase from each other, which will (sort of) provide an additive effect. However, since reactive loads will shift the phase of each one a different amount, what you end up with is two semi-out of phase signals combined. To add insult to injury, you are only using one of the two lines for your voltage reading. As such, any reactive voltage components on the second line are completely ignored. As such, a reactive component on the unmeasured line will read as if it is purely resistive.

    You might think the error is small, but I would estimate that if you calibrate to a load on one line, a load of the same power consumption but a different reactive component on the other line could easily read up to 20-40% off.

    Please let me know if I'm missing something. Again, thanks for all the great work!

    ReplyDelete
  29. You're right. The situation is that I have to make some trade offs or spend a heck of a lot of money setting up highly accurate devices. The goal here is not to get the numbers exact, but close enough.

    The trade off is not between the numbers I get and a very accurate reading, it's between a coarse reading of instantaneous power or nothing at all. See, the only method that's available without instrumentation, is to read the meter and write it down, come back later and read the meter and write it down...etc. Each of these is after the fact and I already owe the money for the period that the measurement took. If the power company provided meters that had a pulse output, the readings would be as accurate as the power meter provides, but that's not the case in my area.

    Regarding power factor. I did a long test of power factor and it never varied more than around 3%, which corresponded to the numbers the power company said their reading were. So, things like dryer motors, A/C motors and such don't really cause much problem. I measured the voltage on the two legs of the split phase 220 and graphed them over a week and they never varied more than a volt from each other. Actually, this made sense because all my heavy loads are 220 and suck from both sides.

    Things changed a bit when I got a permanent magnet motor for the swimming pool. It's highly reactive and causes a drop in the power factor that definitely will cause a misreading. I'll work on that problem someday, but for now, the period is so small I'm just ignoring it.

    Notice that I don't try to accumulate the power usage over time (at least not anymore) I use the device to tell me trends, tracing high usage periods and monitoring the usage of appliances. When I first put it in, I did accumulate values and they corresponded within 2% to the power company values. Then I went through a period of flaky power and recurring outages. That convinced me that I didn't want to try and argue total usage with the power company.

    I'd just lose.

    ReplyDelete
  30. There are several factors that help me in this. My major loads are all 220. I only have one seriously reactive load. I balanced my 110V legs by moving appliances (actually repositioning the breakers) such that the two legs are close to each other. And probably a couple of things I've forgotten. Over the past year and some months my peak demand bills from the power company have matched pretty darn closely the numbers I get going back through the readings.

    Regarding calibration: It was tough at first. I started out using a resistive load (toaster) and comparing it to a Kill-a-watt; when I was comfortable this was working correctly using light bulbs heaters and such, I tried reactive loads and was really surprised that they matched up equally well. Then I used a 220V resistive load (my water heater) and added the phases as you noticed. That compared favorably with a true rms meter I borrowed from an electrician down the street and around the corner. Then I compared this to a 220V motor (A/C compressor and water pump motor) and was again surprised that it matched. So, I hooked it up and took on the power company. I described this interaction somewhere on this site. It resulted in them replacing the meter and suddenly, my readings and the meter's readings matched each other. After that I, unsuccessfully, tried accumulating values.....

    So, while it isn't as accurate as the power company's equipment,it does give me a good indication of my instantaneous power usage. I can turn on a motor and see the increase immediately. I can tell at a glance when the outside security lights have been left on or the dishwasher drying element was not turned off. I have watched the electric oven cycle the element to keep the temperature even and the same with the electric dryer element. I can even see when the vacuum cleaner motor is turned on; amazing how much power a 10 amp vacuum cleaner uses.

    In our efforts to lessen our electricity usage, we are severly hampered by not having anything that will tell us what our usage is 'right now'. This little device with all its shortcomings, does this admirably well in my case.

    And, it was about a quarter of the cost of the cheapest similar device.

    My thoughts for the future of this device follow your suggestions, measuring the voltage for both legs and separating the CTs such that I can actually measure the usage on each leg. The problem with this is the additional isolation transformer and increased load on the tiny processor. This would be added and then my reading would be closer to absolutely correct. If I'm someday lucky enough to get a meter with a pulse output, I may read it and get away from the CTs altogether, but I'm not holding my breath. I do not plan on accumulating values, that will just lead to frustration when my numbers and the power company's don't match. I'm satisfied knowing that I'm using somwhere around 6.8KW when the South A/C kicks on at the same time as the pool motor.

    Thanks for bringing this up. I may add a link to your comment and my response to the page so people can get a clearer understanding of the purpose.

    And, sorry I rambled on so long.....

    ReplyDelete
  31. I second Dave here. I have to deal with 2 X 120 volts and placed a CT on each leg of the 220 volts coming in. I use the reference voltage from only one leg, since I, too, measured really small (negligible?) differences between the two legs over a period of time. Most heavy loads use 220 volts anyway.
    Contrary to Dave, I don't sum the two reading from the CTs at input, but calculate two separate values and sum the resulting current/watt readings. This tales care of any phase discrepancies between various CTs.

    I actually use 5 CTs in my setup, which keeps the Arduino really busy. The Arduino runs at full speed, without delays in the code and outputs one set of values every 3 seconds or so.

    ReplyDelete
  32. OK, you two guys have convinced me...see, I can learn from others as well. I'm going to change the code and hook the other CT to one of the other arduino pins. I have plenty of room for additional resistors and it's not like I have to worry about running out of Arduino pins! It'll be interesting to see how much difference this makes.

    Unfortunately, it'll mean that I have to recalculate the phase angle difference caused by the CT itself, but if I remember correctly, it's not all that hard to do.

    Robert, you convinced me to try this; my hesitation was that I wasn't sure the arduino could keep up with the floating point math.

    I suspect it will wait until after Christmas though. Well, and New Year too. And, the hangover after New Year.

    ReplyDelete
  33. Hello!

    Thank you for sharing your awesome creation! I am trying to build a contraption to monitor my well pump. I'm having a tough time understanding how you have your CT's wired. I would pay pal you 10 dollars if you would throw together a little sketch (even in mspaint) of how you have those wired in series and where they connect to your arduino. If you get a chance would you shoot it to me in an e-mail? Cyrus@jandjpumps.com
    I would really appreciate your help!

    ReplyDelete
  34. Cyrus, I dropped you a note on how I figured out the wiring. If it doesn't help, write me back and I'll explain it better (well, maybe better). Regarding how it's wired into the Arduino, I just hooked it to an analog input and started reading the voltage. The schematic above shows how I used a voltage divider to get the proper range and which pins I used to do it.

    ReplyDelete
  35. Hi Dave I am trying also to build a energy monitor and I have some questions about you design. How did you wire the current transducers in series and what kind of circuitry you build for voltage/current measurement? I mean what kind of sensor electronic did you use to connect the current transducers into the arduino.
    my email is xeneixen@hotmail.com
    Thank you

    ReplyDelete
  36. Hi Dave, as you I followed Trystan assembly and made some modifications. I am trying to save the data into a csv file using a memory card connected to the arduino. However I am having a problem in creating the dataString, because it seems like it doesn't support float numbers. I have checked the code that you used to pass the values to pachube but I didn't get how to do it in my case.
    I want to do something like this: // String dataString = String(emon.realPower) + "," + String(emon.apparentPower) + "," + String(emon.powerFactor) + "," + String(emon.Vrms) + "," + String(emon.Irms); //

    because after I want to save this string in the memory card using something like this :
    logFile.println(dataString);
    logFile.close();
    Serial.println(dataString);

    but I receive an error when creating the dataString, because of the float numbers and I need them to be float because of the accuracy.
    Can you give me some help. my email is pedrosantosg89@gmail.com
    Thank you very much

    ReplyDelete
  37. hi DAve thx for sharing . i'm building a power analyzer. i have some questions
    mamadoulamine.deme@uqtr.ca

    ReplyDelete
  38. In case anyone's wondering, the folks above that asked for individual help were contacted directly using email. I'm not sure they got it all working, but I tried to help them directly. Floating point numbers, using the arduino ethernet library are a bit of a pain, but they can be done. Using the arduino String library will cause pretty serious problems over time due to memory fragmentation and the arduino will usually reboot itself. So, use some of the memory tricks that I've detailed on other parts of this site to help with these problems.

    ReplyDelete
  39. Hello At the entrance you A4 binds directly to the network voltage from 127v. It is not necessary to rectify with diodes? I'm doing a college project and I found a very interesting method of measuring voltage. So I connect the A4 directly into Arduino? How do I convert the reading port A4 (digital) to display the value in voltage? Thank you. Marcelo - marcelocuin@gmail.com

    ReplyDelete
  40. No, the input to both pins on the Arduino is AC. One is for measuring voltage and the other is for measuring current. A4 specifically is for measuring the incoming AC voltage from the mains. I first reduce it to a little over 9VAC with a transformer, then further lower it using a voltage divider so that I can stay inside the tolerance of the Arduino analog input pin. A5 is taken from the current transformers installed inside the mains box. They also go through a voltage divider to keep the voltage inside the Arduino range.

    You are measuring the AC power, do not rectify it to DC, use the actual (reduced voltage) in your calculations. To get the voltage from your readings, hook a meter to the mains and adjust the compensation value in your calculations to match it. Since you don't have any capacitors or other active components, it will track just fine for different voltages.

    ReplyDelete
  41. Very nice write up. I was actually just on opensourcenergymonitor trying to figure out the best way to monitor my whole home usage. What I don't understand is why is the step-down transformer necessary? If I know my total voltage coming into the house is 240V, then why couldn't I just use that in my calculations?

    ReplyDelete
  42. You will need a zone controller if you want to turn a single zone HVAC system into a multiple zone system. The zone controller will connect to the HVAC system and control it. The HVAC system sees the zone controller as just one thermostat so it just does what it is told. The Zone controller's job is to take the request from all the connected thermostats and serialize and package the requests to the HVAC system.

    ReplyDelete
  43. No, I don't. Sophisticated zone control is a nice thing to have if you're in a building with multiple floors, lots of rooms with varying heat sources and such. They could even be useful in open warehouse environments. However, they are overkill for a person's home. Unless you live in the White House or have a Spielberg type budget, simply controlling the thermostats you have is good enough.

    I have two heat pumps with two thermostats I made. These in turn connect via ethernet to a central controller that can set the temps and air circulation based on my desires. The thermostats and controller are shown on this site.

    I'm not saying your device isn't useful, just not for a person's home. Actually, your device is a prime example of what I'm working to avoid. A costly solution that might, maybe, save me money amortized over many years.

    I want solutions that I can control, I can fix, I can customize, and never ever need to call a repairman out for hundreds of dollars to adjust.

    ReplyDelete
  44. hi dave. i need your help. hmmm. i would like to ask the same question if how you connect current transformer and your voltage transformer?.from a service entrance we have 3 wires. Maybe 220 volts of the two wires and the other is the neutral. csn i ask for sketch. .thank you very much Dave. .Thanks for the help. .

    ReplyDelete
  45. Daj, I'm having a little trouble understanding what you're missing. If you are in the US, you will have three wires coming in from the power company and one wire leading to a ground somewhere nearby. The three wires are two hot and one neutral, you want to use the two hot wires and ignore the neutral for the current measurement. The way it works is there is 110 volts from each of the hot wires to the neutral and 220 volts between the two hot wires. This isn't really important for measuring current though, you want to put a CT around both wires. There are drawings all over the web that show this. My picture above of my power distribution box shows where I put the two CTs around the wires; those are the two hot wires. There's not much else to it. Just shut off the power and put them around the wires. Be sure to turn off the power, it's real easy to make a mistake in there and you don't want the power on if you drop a screwdriver or something.

    My voltage transformer is just a simple 110V to 9V transformer that you can find from electronic suppliers on the web. An even easier technique is to find a 9VAC wall wart and use it. 9V wall warts are pretty rare, but I've seen them on eBay for 5 dollars a few times.

    ReplyDelete
  46. Thanks for the reply dave..is it safe if i will not turn off the power line? cause i'm planing to put the current transformer above the breaker if it is ok.

    dave . What is the purpose of youre capacitor in your diagram above?
    Since i used Two CT for the hot wires. .do i need to use two transformer?
    Thank you very much Dave.

    ReplyDelete
  47. i mean two voltage transformer.

    ReplyDelete
  48. Regarding safety. I can't actually see your power setup, so I can't say for sure, but if the wires are insulated and you don't go in there with metal tools, loose clothing that can catch on stuff, and long wires that can short something out, you should be OK. Don't do it in the rain.

    Regarding two voltage transformers. No, you shouldn't need two of them. Just read the voltage on one of them and consider the other leg to be the same. I mentioned above how I measured both legs of the incoming power for a week before I decided only one transformer was good enough. Over the entire week, the voltage never varied by more than a volt between the lines. This makes sense because the power company has a huge reserve and your home shouldn't make one leg change enough to matter.

    This may not be true if the power lines to your house are too small for the load your house puts on them. That used to happen to people and they would see the voltage drop as they turned things on because the resistance of the wires was too high. I haven't seen that problem in many years, so unless you notice something very strange, don't be concerned about that.

    Regarding the capacitors. Those are to remove high frequency noise from the circuit. The power lines run a long way and electrical noise gets into them and can mess up the readings. These capacitors remove the noise so you don't have to deal with it.

    ReplyDelete
  49. So its safe.!! thanks for the idea dave. it helps me a lot doing my project. but i'm planning to use it in LAN/WLAN . . and dave what is better to use? using ethernet shield or the XBEE Wishield in arduino??what is better??
    Thanks a lot for your reply dave.

    ReplyDelete
  50. I tried both wired and wireless ethernet. The wireless constantly had troubles of various kinds and would sometimes take several minutes to recover from it. The wired worked much better, but my house gets disconnected from the internet a lot and it would require the device to reconnect. Not as bad a problem as it sounds like, but really annoying. These are the reasons I set up a XBee network in the house, it was just too annoying being at the mercy of the phone company for the various devices.

    For a long time I had a house clock that grabbed time off the internet and supplied it to the house. This was so darn prone to errors that I got a GPS receiver and hooked the clock to that. It's been about two years now with very, very few problems.

    You may have much better luck, so give it a shot. It's not to hard to convert to some other communications method if you need to later, and is actually fun to experiment with. I'd avoid wireless though, it takes a lot more code and eats up a lot of memory on these little boards. Of course, if you're a long ways from a wired connection, you may want to try the wireless and see if it works better for you.

    ReplyDelete
  51. hello dave, im planning to make a power consumption monitoring system for a certain building. This incoming power line to the building is three phase each line is 110Vac and the lines are in phase resulting 220Vac supplied to the appliances. I'm using 3 power analyzer http://www.e-gizmo.com/KIT/PAnalyzer.htm
    and im planning to hack the power analyzer to insert the Current transformer in the Shunt resistor. And dave i would like to ask how to interface arduino duemilanove with these 3 power analyzer using Newsoftserial. i cant read the output from the power analyzer when i used other digital pins the serial window output is displaying alien characters. but if i used pin 0(rx) its read the output of the power analyzer. .Dave i need your help. Do you have any idea how to fix this problem? or do u have codes that can solve this problem?? thanks a lot dave. .Hoping for your kind consideration.Thanks.

    ReplyDelete
  52. First, thank you very much for pointing out this device (the analyzer) I really like it. I suspect you want to use the CT to increase the rating since it will only go up to 2.2 kW, or you want to make it non-invasive (don't have to cut wires). Take special care during the hack, the CT will put out more voltage than the drop across the coiled wire resistor and that could give you no end of grief.

    To make a reasonable suggestion I need to know a couple of things. What kind of LCD display are you using serial with only one data wire, or parallel with a bunch of data wires? Where is the LCD connected, to the analyzer or to the arduino? Which version of the Arduino IDE are you using? If it is greater than 1.0, the software serial library is included with the download, if before that you have to hunt down the library and load it yourself.

    But, to get you started troubleshooting, try working with the software serial example. This uses the two ports and you can modify it to test things for comm. You could have a baud rate problem (try 9600 on all ports) or a latency problem; that's where your code is too busy to allow the software serial port to work properly.

    Also, I've used software serial to control two serial ports in addition to the hardware serial port, but never more than that. It sounds like you want to have three serial ports and an LCD display running at the same time. This may be too much for the little arduino and moving to an atmega2560 may be necessary. But, play with the one software port and the hardware port first to see what the results are.

    ReplyDelete
  53. Dave thank you for your help. i dont use LCD i planning to connect the power analyzer to the arduino and the arduino is connect to an ethernet Shield ENC28j60 via SPI and the through LAN i will display the data in visual basic 6. .i try the example from software serial using arduino 1.0 and the arduino 0022 but the same results.the serial window display unkwown characters. do you know how to solve this problem dave using the arduino duemilanove. .Thank you for the help dave.

    the hardware serial can read the output from the arduino but the softserial cannot..:(

    ReplyDelete
  54. That sounds like a baud rate problem. In your setup() routine you need to initialize both the hardware serial and the software serial. Something like this:

    #include

    SoftwareSerial mySerial(2, 3);

    void setup()
    {
    // set the hardware serial speed
    Serial.begin(9600);
    // and the SoftwareSerial port
    mySerial.begin(9600);
    }

    void loop() // run over and over
    {
    if (mySerial.available())
    Serial.print((char)mySerial.read());
    if (Serial.available())
    mySerial.print((char)Serial.read());
    }

    I chose 9600 because that is the speed your monitor device runs at (at least that's what I got from the documentation). Hook your monitor to 2,3 and catch characters the output them to something you can see, like the arduino IDE serial monitor.

    ReplyDelete
  55. thanks for the code dave.your right dave. Thanks a lot dave. your a saver.hehe. i used 4800 in mySerial.begin(4800), thats why i cant see the output characters. Thanks dave.
    Dave, do u have idea how can i communicate my arduino using ethernet shield ENC28j60 to VISUAL BASIC 6 in my PC using LAN?. .i dont have any sample code in using arduino to vb using LAN. Thanks a lot dave. Dave here is my yahoomail panot_gomez17@yahoo.com

    ReplyDelete
  56. hello dave i forgot to mension why i post my email. .i post it because i need your expertise.is it okay to you if i'll ask you questions about the communication from ethernet shield enc28j60 to a visual basic.i got problem interfacing the code in ethernet shield enc28j60. maybe you could help me what will i used?.i planning to use ethercard library but i dont know what are the codes to communicate n vb.

    ReplyDelete
  57. You just went beyond my experience range. I've never used the 28j60, I always use the Wiznet chip. There's a reason for this. The 28j60 is a lower level chip and requires a lot more code on the arduino. That means you have less room for your own code and often run out trying to do things. There are very inexpensive versions of the Wiznet board around. To get samples of the ethernet code for the Wiznet chip go to the arduino forum (arduino.cc and click forum up at the top) there are many examples there that are really good.

    Glad I was able to help. Maybe this conversation will help others as well.

    ReplyDelete
  58. thank you dave.
    im planning to use w5100 chip but now i have enc28j60. i starting making program for w5100 but i dont know what will i used to communicate to visual basic with winsock,tcp or udp?others said tcp but i dont have any reference for tcp code in w5100 to visual basic. thank you very much for your kind consideration dave. your the best.

    ReplyDelete
  59. Dear all, i use Non Invasive current sensor SCT-013-30 and use ATMega 8535 for the micro controller, could you give some schematic how to make it can be red by ADC micro controller? many thanks

    ReplyDelete
  60. Arifin, I show the schematic that I used up the page a ways. If you google for your sensor, there are a lot of circuit examples for it on the web. The one you chose is one of the most often used devices.

    ReplyDelete
  61. Hello Dave, I have my sct-013-000. I got problem in calibrating my ct.
    1.What will be the CT calibration if i used 33ohms with 5% tolerance. ?
    2. Also in my voltage transformer (220Vrms -> 12Vrms) i used 10kohms resistor and 680hms resistor for my stepdown voltage divider. I got problem in calibrating it.Our power line has single phase 220Vrms. Do you have any idea will be the calibration of the two transformer?.
    Please i need your expertise. Thank you dave.
    Hoping for your kind consideration.

    ReplyDelete
  62. I had a lot of trouble getting my setup calibrated. I don't care how much you calculate the various values, it will be wrong when you finish. I finally just gave up trying to calibrate it by calculations and settled for getting the voltage and current in the general area of correct and then calibrating it the rest of the way in the code. As far as tolerance on the components goes, it doesn't really matter if you adjust for it in the code.

    The key to this is to get something like the kill-a-watt that we have here in the US. It tells you the current and voltage, so you can adjust the calibration values in the code to match. I don't know what's available where you are and how much the devices cost, but you should be able to find something. Maybe borrow one from someone, or buy it, then take it back a week later for a refund?

    You simply use the calculation instructions that Trystan Lea has on his site to get the voltage roughly in the range the arduino can handle, then tweak it by changing the calibration value in the code. Look at the page:

    http://openenergymonitor.org/emon/buildingblocks/ct-sensors-interface

    This will show you how to get the ct going, then look at:

    http://openenergymonitor.org/emon/buildingblocks/measuring-voltage-with-an-acac-power-adapter

    For the voltage transformer. Once you get these voltages, compare it to the meter you've somehow acquired and adjust the calibration values in the code to match it.

    Trying to get it right by calculation and purchasing the exact right components is almost impossible unless you have extremely good equipment to measure and confirm the components. The commercial devices have a potentiometer in the ct circuit and another one in the voltage circuit. They adjust these to calibrate it to a know source; that's something us experimenters don't have access to.

    Another trick is to calibrate it to something that pulls over a Kw of power. Things like toasters electrical heaters, big light bulbs will work. You have to let them run a little while to settle down since the current draw changes as they heat up, but it makes calibration a lot easier.

    Hope this helps.

    ReplyDelete
  63. Thank you very much for your help dave. I calibrated the voltage but if there's no power on transformer the program can still read an analoginput eventhough there's no transformer connected. .

    ReplyDelete
  64. If there's nothing connected to the arduino analog input pin, it floats at a high impedance. That means it will pick up stray voltages and give you a reading. If you want to observe it, hook something up to it. I use a voltage divider of two 10K resistors from ground to +5V and hook the pin to the middle of the two. That way I will have close to 2.5V to play with. Remove the resistors before hooking it up to the voltage reference you're going to use for power.

    ReplyDelete
  65. Thank you very much Dave. Is it ok if i will put a pull down resistor to analog input. ? Thank you.

    ReplyDelete
  66. Yes, that will give you a low value.

    ReplyDelete
  67. so that i cant read any value when transformer is off?

    ReplyDelete
  68. I'm having a bit of a problem understanding what is giving you trouble. If you unplug the transformer from the wall, the AC will disappear and you will be reading the voltage at the center of the divider from 5V to ground. If you unplug the arduino input pin, you will be reading a random voltage that the pin happens to be setting at. Let's use Krystan's drawing as the example:

    http://openenergymonitor.org/emon/sites/default/files/Arduino%20AC%20voltage%20input_1.png

    In his drawing, removing the ac adapter from the mains will still leave the voltage divider from the +5 to ground through R3 and R4. This voltage will be seen by the arduino pin. I suspect this is what is giving you trouble. You're seeing a constant 2.5 volts (or so) on the pin when the transformer is unplugged.

    I can't currently think of any way to stop that. You can, however, tell that this is what happened in the code and do something. The code is capable of measuring the frequency of the incoming AC mains. Simply look for the frequency to drop to zero and you'll know that the mains voltage has disappeared.

    ReplyDelete
  69. Ahh, so its normal that my arduino can read random values if i did not put my ct to the Power line and voltage transformer to power plug ?

    ReplyDelete
  70. Hello Dave. I got trouble in sending Power Parameters in my LAN using ethernet shield. client.write() needs a character value to able to send data to my visual basic.
    I just want to ask if do you have an idea how to convert Double to charater.

    Thank you very much Dave. I really appreciated you help.Thanks.

    ReplyDelete
  71. Yes, I noticed that too. I chose to use sprintf() because it has the ability to format lots of stuff. Make sure you have stdio.h included in your sketch and do something like this:

    sprintf(yourBuffer,"%d.%02d",yourFloatVariable);
    client.write(yourBuffer);

    You can put more than one variable in and construct an entire string to send. Look at the documentation for printf() online to get an idea what to do.

    ReplyDelete
  72. Thank you for the response Dave. .Is this applicable for integer? sprintf(yourBuffer,"%d.%02d",yourFloatVariable);

    ReplyDelete
  73. Crap. Daj, glad you noticed that I made a mistake. I messed up the code fragment when I typed it in. What I should have put down was:

    sprintf(yourBuffer,"%d.%02d",(int)yourFloatVariable,(int, (((yourFloatVariable+0.005) - (int)yourFloatVariable) * 100);

    client.write(yourBuffer);

    The idea is to take the float value, cut it into integer values for the whole and fractional parts, then print it out as two values on each side of a decimal separator. Adding the .005 is rounding for the hundreths positions. So, if your value is 1.23, the (int)yourFloat variable will give you back 1. Then the (((yourFloatVariable+0.005) - (int)yourFloatVariable) * 100) will give you back the 23. The you print it as two things before and after a '.' to give you '1.23'

    Sorry about the mistake. Be sure to look at documentation for printf(), there are a lot of tricks in there to help you.

    ReplyDelete
  74. Thanks a lot dave. That will help me very much. :)
    Did you try 0.2%lf ?? or %lf for double float and %f for single float?

    ReplyDelete
  75. I did, but I can't remember for certain what happened. I think it failed because the code for that part of sprintf() wasn't ported. It's easy to try, just set up a tiny little test program and use literal values to test it. It may be that when I tried it it didn't work and they have fixed it since.

    ReplyDelete
  76. Ahh ok. .Thank you for the help Dave.

    ReplyDelete
  77. Hello Dave .How can i set the current and power factor to 4 decimal places. .

    strcpy_P(Dbuf2, PSTR("Inrange,%d.%02d,%d.%02d,%d.%02d,0.%d,%d.%02d,%d.%02d,"));
    sprintf(Tpadata,Dbuf2,(int)round(realPower),(int)(((realPower+0.005) - (int)realPower) * 100),(int)round(apparentPower),(int)(((apparentPower+0.005) - (int)apparentPower) * 100),(int)round(reactivePower),(int)(((reactivePower+0.005) - (int)reactivePower) * 100),(int)(powerFactor*100),(int)round(Vrms),(int)(((Vrms+0.005) - (int)Vrms) * 100),(int)round(Irms),(int)(((Irms+0.005) - (int)Irms) * 100));

    ReplyDelete
  78. Use something like "%d.%04d" as the format string and then the integer part is:

    (int)(round(realPower))

    And the fractional part is something like:

    (int)((realPower + .00005) - (int)realPower) * 10000)

    But, you're getting into the realm of not having any real meaning to the last digits. 1/10000th is way beyond the accuracy of the devices you're using. It may be better to just set the last couple of digits to zero.

    ReplyDelete
  79. Thank you for the code dave i will try this one. .Thanks for the help. I really appreciate it.

    ReplyDelete
  80. Dave . i cant find people that can help my problem,only you. I wanna hear your advice if you dont mind. Here is my situation.

    First I made a power monitoring for my study using visual basic. My arduino send data to visual basic through ethernet in my LAN with this string format. .example:

    "InRange,-0250.6,0010.0,-0150.2,+0.6228,220.39,0.5,|InRange,-0250.6,0010.0,-0150.2,+0.6228,220.39,0.5,|InRange,-0250.6,0010.0,-0150.2,+0.6228,220.39,0.5,|09:12:42:23:12:11|10000"

    and save that data to ms access. The problem of this, is that when i close my visual basic program ,the data from arduino have no destination or in short i can get data when i open my visual basic program.

    Now, my adviser told me to use sql.
    So therefore dataflow will go like this arduino-->LAN--->database(sql)-->visual basic. .With this i wanna send data to my database and view it in visual basic like what your project is doing.
    Dave what database did you use?. .please help. ::(

    ReplyDelete
  81. I send my data over the internet to Cosm, thingspeak, and opencms. They are all web services that store the data online. My actual architecture is that I have several sensors around the house that send data to a central concentrator that bundles them all together and uses ethernet to send the data to these servers. Most of my sensors are based on the Arduino, but there are a couple that are XBee radios with the sensor attached to them. The concentrator is an Arduino Mega2560, that forwards the data and also provides a web interface that I can use to control various devices like my home heating and water heater.

    I had exactly the same problem you're having when I first started this. I was logging the data to a laptop, but when the laptop was off, nothing worked. This was unacceptable so I added an arduino with an ethernet shield to forward the data to Cosm for storage. This led to more sensors, more Arduinos, etc.

    There really is no good solution to logging data on a laptop, since it will get taken on trips, turned off, or just used to play games. Many people use an SD card to log the data, then carry it over to the laptop, retrieve the data, and do their analysis. That may be your best solution if you can get a shield for the arduino that supports an SD card.

    If you can get access to a computer that is never taken off line, you can probably work out a way to use it to store the data, but those are hard to find. If you can spend some money, there are many little computers that have ethernet and some storage that you can hook into the system. Maybe borrow someone's old laptop and leave it on 24x7 to collect the data.

    ReplyDelete
  82. Dave .in your case.can you send data without internet? or not?

    ReplyDelete
  83. I send it over the internet to web based commercial servers. Take a look at Cosm.com to see what kind of thing I do.

    ReplyDelete
  84. Hello Dave,
    I'm having some problems calibrating the Arduino board to show me the real time current and voltage values. I used one 50:1 A CT with a burden resistance of 33ohm and the electric sketch from Trystan Lea's website, and one 230 to 9 V AC-AC power adaptor again with the electric sketch from Trystan Lea's website. Then I used your arduino sketch and interface it with an LCD to show the current and voltage. After that I used some variable resistances with a ampermeter so I can see if it shows the real current value, modified the resistances to show 1A on the ampermeter, then calibrated the value of "double ICAL = 2.85;" so the LCD from the arduino would show 1A and after that I lowered the resistance to give me 2 A on the ampermeter but the LCD would show a current of aprox 2,2 A that is a really big error, 0.2 A... I couldn't lowered the resistance to give more then 2,5A and dident try to connect a bigger consumer to see if the error grows too, but I'm sure that it will. Did you had the same problem ?

    Thanks,
    Marius

    ReplyDelete
  85. No, I did not. I did it differently though, I used a higher value for the calibration. I borrowed a great big light from a neighbor and pulled about 2kW and set it up at that level. Later, I was able to use a real resistive load that an electrician had that allowed me to set it up for 5kW. In the US, using split 220, I had to do this for both legs to be sure it was actually working correctly. I am not totally sure it's real accurate when the levels get up around 15kW or so, but for my purposes, extreme accuracy isn't as important as knowing that I'm using that much and when.

    Oh, when I tested the calibration at lower currents using light bulbs and such in comparison with a kill-a-watt, it was right on. The symptoms you're describing sort of suggest that the CT is saturating. Try a different burden value to see if things change for the better or worse.

    ReplyDelete
  86. Hello. This is such a great web site and very inspiring! Thank you! I just ordered a SCT-019 so I can build the same type of monitor as you.

    I have just one question, however, on the code. All the code makes sense except for this section which I don't understand how it works. Could you or someone else explain how this code removes the 2.5 v offset? Thanks.

    //Digital high pass filters to remove 2.5V DC offset.
    filteredV = 0.996 * (lastFilteredV+sampleV-lastSampleV);

    Joe

    ReplyDelete
  87. That code statement drove me nuts also. Basically it's a digital high pass filter that responds to the input in just a few cycles of the power. Unfortunately, that was two years ago and I don't remember any more. However, here's a thread (http://openenergymonitor.org/emon/node/932) that discusses it and there is a pretty good article on Wikipedia under "Digital high pass filter".

    The reason it removes the DC offset is because DC is the ultimate low frequency. Can't get much lower than zero.

    It's cool to watch it react. When you start experimenting, put together a bit of code to illustrate what it does and play with it a bit. It will remove the DC component of your measurements really well. That means you save on working up hardware and calculating capacitor values.

    ReplyDelete
  88. Thanks for your quick reply. I'll look into that.

    Another thing I was wondering about...I too live in the US and have a 200 amp 220 v feed. I ordered just one 2000 amp current sensor as I don't know if I could fit 2 inside my service panel; there is very limited room. But I believe one sensor is enough to measure my 220 volt usage (water heater, baseboard heat, dryer) and I can measure the current draw on one side of the 220v, right? I would need 2 only to measure both sides of the 220. And I would wire both in series. One thing I notice is the current sensors are labeled as to what side points to the source but I have never seen anyone mention this. Seems to be rather important if one is wiring 2 up in series.

    Joe

    ReplyDelete
    Replies
    1. Oops, I meant I ordered one 200 amp...

      Delete
  89. Back when I ordered my current sensor it didn't have any indication which end pointed where. The wires were different colors though which turned out to be the same thing. I just oriented them both the same way and it worked.

    Yes, you can measure only one side of the 220, that will tell you the current in that leg of the power. There are things that chew the power up that are not 220 though. Vacuums pull a lot of power, compressors, motors, deep fryers, that kind of thing. If you only want to control the major appliance though, be sure they are all on the leg you're going to measure.

    When you get the first CT in, you can look to see if there's room for another in the box somewhere. Just turn the power off to be sure you won't get shocked and check around inside.

    ReplyDelete
  90. Hello again. I just received the CT019 sensor and I am calculating the burden resistor. The CT019 is rated at 33 ma at 200 amps. Thats 6060 turns. For the 5 v Arduino, AREF2 = 2.5. Peak input current is 282 amps, peak output current is .0466 amps. I calculate a resistor of 54 ohms. But your circuit show 320 and I am not sure why. We are both using the same sensor to measure 200 amps RMS with a 5 volt Arduino, right?

    ReplyDelete
  91. OK, I just used what I had available at the time and calibrated the code to make up for any difference. See, getting the burden resistor exactly right is a good thing if you are going to be hooking them to different devices or selling them based on a known calibration. However, if it's going in your own garage and you have access to a calibration source like a good electrician's meter that can give accurate readings, you can adjust things to work.

    The important item is to keep the CT out of saturation so you don't clip off the tops of the 60 Hz waveform.

    ReplyDelete
  92. UPDATE - Got the CT and Arduino wired up and working well. Right now I am testing it on an extension cord and light bar and it measures 350 watts pretty close. But my end goal of course is to do what you are doing, datalogging to the net the house mains so I can monitor my house power usage from anywhere. I haven't checked to see yet but I assume you have posted here the code you are using to send your data to that web site. Thanks again for the inspiration!

    ReplyDelete
    Replies
    1. I do have the code I'm using posted, but the web site that I send it to has changed. It used to be Pachube.com, then it was Cosm.com and now it's Xively.com. They haven't changed the API, but things are different. When you get to that point, you may have some discovering to do.

      Congratulations. It's fun being able to see the power change as you turn things on and off around the house.

      Delete
    2. I got xively working. It was quite easy using the online tutorial. But the output doesn't look good, just some line graphs. I take it you export the data from xively and send it to some other web site to do the nice gauges and graphics.

      Delete
    3. Yes, I use the SteelSeries gauges and the google graph api for things that I want to get into in depth, or just glance at to get information. For mobile (phone or tablet) I use the Xively graphs. The reason is that the Xively graphs are .png files and can be displayed by all browsers. They don't look as good, but they work on a Kindle or a phone.

      It's as easy to get the information back from Xively as it is to get it there in the first place, so you won't have much trouble with it.

      Delete
  93. You don't happen to have a full set of schematics and instructions as a bundle do you?

    ReplyDelete
  94. Actually no, this page is the record I keep on this project. The schematic is up there somewhere, as is the code that I use. The pictures are here also, so is there something else you need?

    ReplyDelete
  95. Dave, just a quick update...I got everything done and I am on line! As I stated before, I have only one CT sensor on one leg of my 220v service. I need to buy another one.

    Today to test it out, I turned everything on in the house, everything but the electrical heat that is. The electrical stove, oven, water heater, lights, fans, AC's. etc. The dashboard showed I was using 12,500 watts and 101 amps! Since I have a 200 amp entrance and I am monitoring only one leg, the amps sound right.

    I found one of the biggest draws is my 30 year old 12,900 BTU AC. It draws 15 amps. My other AC, 8000 BTU, draws 7 amps. So now I am looking into replacing them.

    JC

    ReplyDelete
    Replies
    1. Good job Joe. I also found the AC units were eating most of my power, but they're relatively new, so I can't justify replacing them yet. I also found that my swimming pool pump was eating me out of house and home. Got a new one of those and noticed a huge difference.

      Also, I got your mail, but when I tried to answer it, it bounced back at me. Tried a second time and I don't know if it got through. However, I put the stuff up on the blog. I show how I do the gauges and also how I get the charts. Now, you should be able to take the code and put in your numbers and do the same thing.

      Delete
    2. No, sorry, I did not get the email. I am not sure what email Google gave you. I see you posted blogs on the subject. I am sure this will help alot of other people too. I need to study them in detail.

      One thing I may add to my display; not sure if you have thought of this or not. But I want to add cost to my display. I want to see how much all this electricity is costing me. Since I know my electric rate it should be easy for the Arduino to calculate and display along with usage. Then I can turn on my AC and actually see what it is costing me!

      Delete
    3. I had cost on mine for a little while. The problem was that every time it rebooted, it got set back to zero. I could have saved the data in rom, but it was a real pain to do correctly. I just learned what the levels of usage meant and lived with it.

      Now, when the little light turns red on my power monitor, I run all over the house turning things off.

      Delete
    4. I got both CTs on line now and it seems to be working good. But I do have a problem. At random times (I think ) I lose the feed to Emoncms and I have to reboot the Arduino. I am not sure if I am getting a power surge knocking out the program or maybe a program issue. Since the Arduino is in my garage away from my laptop I can't troubleshoot the issue. I tried storing the running KW usage to an SD card but it doesnt work yet. Do you have problems where the Arduino just stops running or sending data?

      Delete
    5. Actually, my internet connection is so lousy that I have this happen all the time. What I do is sample the network every so often to be sure it works and reset the arduino to cause it to reconnect. Here recently the connection to Xively has hung up with some error or other and I'm starting to think about checking it every 5-10 minutes to see if that path is alive. Just a couple of days ago I had it fail to transmit data for several hours because I didn't notice it wasn't transmitting correctly.

      I don't have a good solution, but I certainly have the same problem.

      Delete
    6. For my house, the internet is OK. I think the Uno is messing up because I am at the limits of SRAM and program space. I bought a Mega 2560 which I am going to swap in and see if it fixes the problem. I also am trying to get the SD card working so it will remember the running KWH. But of course that wont restart the system if it crashes. A watchdog timer or something like that would be needed I guess.

      Delete
    7. If you move to a mega 2560, take a look at the posts here I have about the bootloader. I had to whine for over a year to get a fix in place to make the bootloader on that board work. There was also a bug with loading software that had three exclamation points in it.

      As I am told, the very latest board have the fix in place, but if you get older stock, you could have problems with a bootloader that doesn't support watchdog timers.

      Delete
  96. How have you calculated burden resistor for CT and calibration constant for voltage and current. I am using 220V/9V VT and 100/5A C.T having 5VA Burden.

    ReplyDelete
  97. There's a really great write up on this at:
    http://openenergymonitor.org/emon/buildingblocks/ct-sensors-interface

    and there's even a calculator designed to help you at:

    http://cyrod.com/z3/ct-helper.php

    It's interesting that, when I first started this project, there was very little on the web to show me what to do. Now, it's all over the place. Prowl around on the web a bit and you'll probably find many more examples.

    ReplyDelete
  98. can you help me , please , i have a problem with the calculation of apparent power and the average power using arduino, when i sample and use the sampled vlaue to calculate apparrent , average power , i get wrong answer but when i do them separately it works.

    ReplyDelete
  99. I can try. Do you have a code fragment you can share?

    ReplyDelete
  100. Hello again. I'd thought I give you an update regarding my Arduino hanging and needing a reset every day or two...

    I was having problems with the SD card on the Ethernet shield. It would not save data to the card reliably. So I completely commented out the section of code that reads/writes to the SD card for each measurement and since then I have not had any hangs or crashes. I have gone for 11 days so far w/o a hang. So somehow the SD card code was causing problems. I plan to give up on using the card and just write to the EEPROM like every hour instead. FYI.

    ReplyDelete
    Replies
    1. That's the first time I've heard about the SD card hanging up the Arduino. Sort of makes sense though, the writes are synchronous, and if something happens, you're just stuck.

      I'm really familiar with the Arduino getting stuck though. Over the years I've had the Ethernet board hang, I2C hang, library bugs hang, etc. That's why every darn Arduino I have has a watchdog timer enabled to reset and start over. I still love the little Arduino board and will continue to use it for various devices.

      Delete
  101. Please can you post just a brief description how you selected calibration constants 0.592 and 3.2 for voltage and current only, I cannot get it right from EmonTx forum. Please I only need a brief desciption.

    I have used CT of 20/1A, burden resistor 1.7Ohm. What will be my calibration constants? The rest of the circuit is same as in EmonTx mentioned below.

    http://openenergymonitor.org/emon/sites/default/files/Arduino%20AC%20current%20input%20A.png

    ReplyDelete
  102. I've described how I did this a couple of times above and my memory of doing it is scatter a bit since it has been a long time.

    But, I used trystan's calculation to get it roughly in range, but I didn't have the right resistor available. Since I was anxious to see it work, I grabbed something close a used it instead. I have a kill-a-watt (google it) and I hooked up an extension cord with the kill-a-watt in series so I could read what it said and then compared what my device calculated. Then it was just find a reasonable load like a light bulb, toaster, the neighbors big yard light, things like that. I changed the calibration constants until they matched the kill-a-watt and hooked the device up to the power panel.

    At that point, the kill-a-watt was useless since I was measuring very large currents and there wasn't any way to plug it in. So, I borrowed an electrician's meter that clamps around the wire and clamped it close to the CT in the power panel. That gave me the current and another meter to measure the voltage and did the calculations by hand to make sure the calibration worked at higher levels. It worked just fine which meant that I wasn't saturating the CT and I was ready to go.

    But, a 20:1 ratio is the lowest I've seen. Are you sure about that? 200:1 or even 2000:1 sounds more likely.

    ReplyDelete
  103. Hallo,

    I have 3 Arduino Uno and i will send data via XBee Pro s2b to PC (Multipoint to point). Im so confused how to configure this xbee so i can show 3 data from arduino in PC.
    I've been searched, i found i have to configure xbee coordinator in API mode. I dont understand at all. And to show graph in PC use processing.
    I wanna ask you about coding in processing. im newbie and confused about that.
    please help me about coding in processing to make realtime graph.
    Or you have a recommendation for me?

    thank you

    ReplyDelete
  104. I recommend you do what I did. Get Robert Faludi's book on XBee networking, "Building Wireless Sensor Networks". Then, start at the very beginning and step through it. These little XBees are too big a bite of knowledge to take on all at once. You need to do the very basics of getting two of them to talk first, then add in another, and another, etc.

    The biggest single reason people have so much trouble with them is because they try to do it all at once. When I bring up an XBee, even after doing it dozens of times, I start with something simple and work it up a bit at a time.

    The cool thing about Faludi's book in your particular case is that he uses processing to develop a network in the later chapters. I dealt with processing a bit, but I didn't want to tie up a larger computer doing stuff around the house, so I went with arduinos, and most recently a raspberry pi.

    The confusion goes away if you take it a little bit at a time. Get the book and dig in.

    ReplyDelete
    Replies
    1. ya, i have read the book and i've try all of step from the book.
      i have sent data from arduino to PC via xbee and X-CTU display the data but if i try 3 data from 3 arduino simultaneously, X-CTU just display 1 data. then I follow the book, i configure the coordinator (XBee in PC) into API Mode. I display 3 data successfully but data looks weird because the API Mode.
      I wanna display the data in a graph realtime or just display data.
      Im still confused to find the problem. maybe arduino code?
      Can you help me, please?

      Thank you.

      Delete
    2. What may be happening is that the data is getting interleaved because all three of them are hitting at the same time. In transparent mode (that's the mode that doesn't use the api packets) you'll get part of a transmission from one XBee in the middle of the transmission from a second XBee. The only real good way of transmitting from several XBees to a single location is by using API mode.

      So, on XCTU you're seeing garbage until you go to API mode, then you can't read it until you pull it out of the packets. Try putting all of the XBees in API mode and use the library example on the arduino that I have on this site. Go up the page and look for Using XBee library, I have several examples of how to code for this on the arduino.

      Then, on the PC, you'll start getting packets from the arduinos that are (usually) complete and make some sense. Now, if you want to decode these on the PC, there are processing libraries that you can use and examples of how to use them. There are also some brand new JavaScript libraries out there and I think I saw some libraries for PHP.

      Using one of these languages, and stealing information from the examples you should be able to decode the packets and get your data back out. I have examples for this using python on this site as well, but python isn't the same as processing, similar, but not the same.

      Take a look at my examples and see if they help.

      Delete
    3. i've Try putting all of the XBees in API mode (Coordinato and Router).
      in your examples use arduino mega,mine UNO and i've try #include , it doesn't work.
      my arduino's code :

      #include

      // Create an XBee object at the top of your sketch
      XBee xbee = XBee();

      // create an array for holding the data you want to send. You can change the contents of your array later on in the loop.
      uint8_t payload[] = { 'X', 'B', 'e', 'e' };

      // Specify the address of the remote XBee (this is the SH + SL)
      XBeeAddress64 addr64 = XBeeAddress64(0x0013a200, 0x409f40de);
      // Create a TX Request
      ZBTxRequest zbTx = ZBTxRequest(addr64, payload, sizeof(payload));
      // Create a Status Response object
      ZBTxStatusResponse txStatus = ZBTxStatusResponse();

      // Tell XBee to start Serial
      void setup() {
      xbee.begin(9600);
      }

      void loop() {
      // Send your request
      xbee.send(zbTx);

      // We'll wait up to five seconds for the status response. If the receiving XBee is powered on, the response will
      // arrive very quickly, but if the remote XBee is not powered on or associated it could take a few seconds for a response.
      if (xbee.readPacket(5000)) {
      // Got a response!

      // Should be a ZB TX Status
      if (xbee.getResponse().getApiId() == ZB_TX_STATUS_RESPONSE) {
      // It is, now get the status response
      xbee.getResponse().getZBTxStatusResponse(txStatus);

      // Check if it was delivered
      if (txStatus.getDeliveryStatus() == SUCCESS) {
      // Packet was successfully delivered
      } else {
      // The remote XBee did not receive our packet. is it powered on?
      }
      }
      }
      delay(1000);
      }

      display in X-CTU in hex : 7E 00 10 90 00 7D 33 A2 00 40 9F 41 67 90 E5 01 58 42 65 65 59

      is there anything wrong???
      and how to decode in Processing? i've searched but nothing.

      Delete
    4. how to sent number of data. i mean int not char like above??
      for example :
      int c = 5;
      void setup() {
      Serial.begin(9600);
      }
      void loop() {
      Serial.println(c);
      c = c + 1;
      if ( c>30 )
      c = 5;
      delay( 1000 );
      }

      I dont get it.

      Delete
  105. hex : 7E 00 10 90 00 7D 33 A2 00 40 9F 41 67 90 E5 01 58 42 65 65 59
    This has the word XBee in it and is a receive packet. Some of the strange stuff is because it is API mode 2, but it looks fine. I don't know how to decode it in processing because I haven't used processing in 4-5 years now and much of the stuff has changed.

    Regarding sending an integer, this is seldom done between machines because different machines and languages represent integers differently. People almost always convert numbers to text, send the text, and then convert back to numbers. This serves two purposes first it takes care of the differences between the devices and second it makes the numbers readable in a log of the data transmitted.

    ReplyDelete
  106. what do you mean this is seldom done?? if so how to send a sensor data (float) for example 0.003 0.004 0.006 ?? I mean the algorithm in arduino program? I didn't get it about to convert numbers to text, send the text, and then convert back to numbers. Can you give me a example??
    I've try Xbee in router i configure AT Mode and upload the code :
    c = c + 5;
    if ( c>30 )
    c = 5;
    delay( 1000 );

    display in terminal X-CTU contain the data (5 10 15 20 25 30 ...and so on) but not periodic, i mean --> 5 noData noData 10 noData noData ..and so on. it has 2 interval.
    what do you think about it?? can i try to decode this?

    Thank you in advance.

    ReplyDelete
    Replies
    1. I assume you have a print statement in there somewhere. So, if you do, then that print statement is changing the variable c from whatever it is to ascii before it sends it to the terminal. The number 5 is not the character '5' and there are things that have to be done to convert it. That's the kind of thing I'm talking about. Go look at the tutorials for c++ and see how they change things from binary data to ascii data for display.

      Delete
    2. Im sorry, I didnt get you. Can you explain more simple?
      you mean, for example value c = 5 (integer) that's decimal value then convert into ASCII --> ENQ (enquiry) then send it to the terminal?
      first, value 5 (decimal) convert to binner --> 101. am i right??
      how about i configure AT mode? can i use it??

      Delete
  107. OK, computers work in binary so a 5 is binary 101 as you know. But you can't read that so the number has to be converted to an ascii character for you to read. What is often done is they take the ascii number '0' which is hexadecimal 0x30 or 110000 binary and add it to the 5 to get 0x35 which is the ascii number '5'. You can look up an ascii chart to see how the numbers work. So things like adding the ascii number 5 and the ascii number 5 dont give you 10, it gives you 'j'. There's a big difference from what print puts out and what is actually used. That's why they send text instead of a real integer.

    As for AT mode, yes it will work, but you'll have to do a lot of the work yourself because all the libraries use API mode (some use API 1 and others use API 2).

    Take a look at converting numbers to text and back again to get a better understanding. There are routines to do this in every language; in c its itoa() for integer to ascii and atoi() for ascii to integer. The source for both of these is online so you can see it.

    ReplyDelete
    Replies
    1. Hey dave, what if i use Ethernet Shield to upload data sensor? I have 1 Ethernet Shield.
      my project just like yours about monitoring energy. I have read energy successfully then i wanna upload data. would you give me the formula? i mean how to upload 3 data from 3 arduino use xbee (Router) ?? are 3 data send to the coordinator then coordinator upload the data via Ethernet??
      Thank you in advance.

      Delete
    2. If you mean write the code for you, then no. Doing it yourself is all about doing it yourself. I've got enough information and code samples on this site for people to pick and choose what they want to build almost anything related to XBee communications. If you want a ready made system, those are available on the web with various capabilities.

      Delete
  108. ya on this site is enough. many examples
    i mean how to configure the Xbee? keep using API mode for the coordinator and Router? or there are additional settings? And library?
    I just wanna make sure my steps are correct.
    So 3 data from Arduino+Xbee(Router) send to Arduino+Ethernet Shield+Xbee(Coordinator) then upload?
    Thank you for all your explanation.

    ReplyDelete
  109. I recommend the library that I talk about on my XBee posts and api mode 2. If you have an arduino and power on each of the XBees, let them run all the time which is the default configuration. It works nicely if you name each XBee. Use XCTU and set the NI parameter to something like "Appliance", something meaningful to you. This is for the remote configuration that you can do on the configuration page. You can read a remote XBee's configuration and actually change it without going there and unplugging it. I use this all the time to mess with the XBees. Use a broadcast address at first on all of them so you can see the traffic with an XBee plugged into your computer. Once you get them working, change the addressing scheme to only send where they need to. Broadcast can mess things up when you have several devices.

    ReplyDelete
  110. Hello Dave,

    First of all congratulations by your wonderful work.

    I would like to know if is possible with your code, to see the current flow way.
    ex. If I turn the CT in one direction, the current value with be positive and if I turn it in opposite direction it will be negative.

    If know do you have any idea how can I do that?

    Thanks for the help.
    Regards,
    Hugo Gomes

    ReplyDelete
  111. Actually, yes you can, but I haven't experimented with it. The difference is in the phase relationship of the current to the voltage, because AC power goes both ways all the time; that's why the call it 'alternating'. So, to find out how to measure this, look around for power flow in the mains, not current.flow.

    ReplyDelete
    Replies
    1. Hello Dave,

      I understand the relationship. I've tried to figure out where you "compare" the current and the voltage to get the power flow, but I didn't found it.

      For my system is important to see what is the current flow, because I can consume from the grid or inject in the grid.
      What is happening know is that the monitor assumes every thing was consumption, but when I'm sending to the grid I'm not consuming anything.
      Do you see my problem?

      Regards,
      Hugo

      Delete
    2. Hugo, go look at the emoncms web site. They have a forum and several people have worked on this problem a lot. They have several solutions posted in the forums.

      Delete
  112. Hi dave,
    i understand, i've sent integer :
    int pin5 = 35;
    payload[0] = pin5 >> 8 & 0xff;
    payload[1] = pin5 & 0xff;
    35 = 0x23 = #
    the receive packet contain #.
    does it work correctly?

    i wanna ask u, how to send a float?
    union {
    float f;
    byte b[4];
    } stuff;
    // Sending a float
    stuff.f = 3.14159;
    payload[0] = stuff.b[0]; // Converting using the data type defined in "union"
    payload[1] = stuff.b[1];
    payload[2] = stuff.b[2];
    payload[3] = stuff.b[3];
    i didnt get it. can you explain?

    i've try broadcast, and it's work. Hello word bla bla (with garbage stuff). and i 've try 2 arduino(router) sent to coordinator (broadcast)
    in X-CTU : Hello word......Hello word.....I saw what you did last night.......I saw what you did last night (with garbage stuff) does it work correctly?

    f i got it right, i wanna ask u how to receive the packet in arduino (Coordinator) then upload via Ethernet shield?
    Can you give the picture?

    Thank you in advance.

    ReplyDelete
    Replies
    1. The float thing is a way of getting each of the bytes of a float and sending them as a series since you can't send floats, only bytes over an XBee. There are many other ways, but the one I like is to convert the float into a character array and send that I have a specific example of that on this page up in the description. I use a sprintf and format string to create it and the send it as text. This is working day in and day out and has the advantage of being readable if I need to debug it. The data I send from my power monitor is regular old text.

      For example,
      sprintf(Dbuf,"Power,%d.%02d\r", (int)realPower, frac(realPower));

      Where Power is a float will display something like 1202,75 when you print it from Dbuf. You can then send that string directly over the XBee and receive it at the end.

      The intermingling of the broadcasts you saw is what I was describing earlier. To avoid this, you have to go to API mode and use that to send the data. I have examples of exactly how to decode this on my XBee page. The code there will compile and do exactly what you want to do, you just have to adapt it to what you're doing.

      I have examples of uploading that data on an ethernet shield in several places on here. The old house controller page has examples of how to send the data over the internet to cloud services and such as well as an example of a web page to display it.

      Delete
  113. hey dave,
    im confused. i try to send integer = 83. then in X-CTU display S = 0x53. which makes me confused is why in X-CTU :
    7E 00 12 92 00 13 A2 00 40 9F 41 67 1C 33 41 01 00 00 01 02 0D 90 ( Zigbee IO Data Sample RX Indicator)
    7E 00 0E 90 00 13 A2 00 40 9F 41 67 1C 33 41 00 53 50 ( Zigbee Receive Packet)

    Why there is a Zigbee IO Data Sample RX Indicator? This appears irregular because in X-CTU display :
    Zigbee IO Data Sample RX Indicator - Zigbee Receive Packet - Zigbee IO Data Sample RX Indicator - Zigbee IO Data Sample RX Indicator - Zigbee Receive Packet - .........
    is it normal ??

    i didnt get about sprintf for sending a float data. how this displayed in xctu?? can you explain more detail or specific?

    Thank you in advance

    ReplyDelete
    Replies
    1. As I keep telling you, the way things are handled in the computer and what you see are different. You set an integer to 83. That's in decimal, it sent it as two bytes 00 and 53, these are in hexadecimal when you see them in xctu because xctu prints the bytes in hexadecimal. 83 decimal is 53 in hexadecimal. The data sample rx is probably because you have data sampling turned on in one of the XBees you have configured. Check the configuration in xctu for the devices that is sending.

      Regarding understanding sprintf, put the code in an arduino and start experimenting. It'll come to you if you actually try it.

      Delete
  114. Hey dave,

    I've try to change value PHASECALL for calibration. it start from 0.9 increase. but i didnt see real power and power factor value change. whereas the difference real power of my system between multimeter about 11 W.
    how to calibrate the system??

    Thanks in advance

    ReplyDelete
  115. What I did was move it in a big step to see what happened. I think I started with .1 to see which way it went and then moved it a bunch the other way. After learning what I needed to do, I nudged it in small increments until I hit it dead on. That's when I tested it with various load levels to see if it tracked in a linear fashion.

    So move it a lot and see which direction you need to go, then narrow it down further. If I remember correctly, it only took about 20 minutes to get it set.

    ReplyDelete
  116. ya i get 0.72 ... quite troublesome

    Dave, how about Total Harmonic Distortion? In the function EnergyMonitor there is no filter. I'm also still confused this section.
    Can you explain it to me in simple terms?
    thanks in advance.

    ReplyDelete
  117. Harmonic distortion is caused by multiples of the original signal on the wave form. There is also noise from motors, RF caught by the wiring, and distortion caused by switching power supplies that get in there. This stuff all has one thing in common, it's of short duration and can be removed with a low pass filter. There is a low pass filter built into the code that removes most of that over a few cycles of power. The filter is tough to understand, but there are several articles on the web about it you can read. Wikipedia has a page that covers it.

    ReplyDelete
  118. so the code above is just for normal home load just like resistive, inductive and capacitive without harmonic distortion source. if there is no harmonic distortion source, it no need LPF, isnt it

    ReplyDelete
  119. Actually, I messed up the explanation a bit (actually a lot), and you got it right. Let me try this again.

    I was right about harmonic distortion, that's caused by things that add a multiple of the power frequency back into the wave form. Normal house current doesn't have much of that because the impedance of the circuit supplying your house is very low. There's a lot of noise on the wire though due to it's length and location outside on a power pole. The CT and its circuitry removes most of that. The filter I talked about is a HIGH pass filter, not a low pass and its purpose is to remove the DC component of the measurement to make it much easier to calibrate since we don't have to worry about the offset voltage.

    There are distortions in the current and voltage wave forms due to some of the devices in the house, but they are also part of the measurement since we're taking many measurements per cycle and combining them. Also, if you look at the power on an oscilloscope, the waveform is quite stable with some little disturbances from time to time when a motor kicks on or something. These are a tiny percentage of the total and can be ignored unless you're doing high accuracy measurements.

    When people work with AC signals they often worry about the perfect waveform. This is an important factor in music and such, but with 170 volt sine waves at 10 amps, it becomes such a small factor that it isn't much concern.

    ReplyDelete
  120. oh i see. but in my country AC signal 220 V and Imax = 6 amps. i wanna ask what if what if the current is small, for example 0.1 - 1 amps?

    ReplyDelete
  121. Actually, I don't know. Borrow an oscilloscope from someone and take a look at the input to the arduino. The noise and waveform should tell you what you're dealing with.

    ReplyDelete
  122. Ok dave. I'll do it.
    I wanna ask how about the code for calculating rms and power :

    // Root-mean-square voltage
    sumV += calibratedV * calibratedV;

    // Root-mean-square current
    sumI += filteredI * filteredI;

    // Instantaneous Power
    sumP += abs(calibratedV * filteredI);

    I dont use :
    //Root-mean-square method voltage
    //1) square voltage values
    sqV= calibratedV * calibratedV;
    //2) sum
    sumV += sqV;

    //Root-mean-square method current
    //1) square current values
    sqI = filteredI * filteredI;
    //2) sum
    sumI += sqI;

    //Instantaneous Power
    instP = abs(calibratedV * filteredI);
    //Sum
    sumP += instP;

    what is the difference??

    ReplyDelete
    Replies
    1. There isn't any difference. For some people it's easier to understand one method over the other.

      Delete
  123. Hey Dave,
    why use the function abs / absolute? does it help when partially reactive load? I'm still confused to understand it because there is a negative part
    is there phase-shift limit?

    ReplyDelete
  124. Basically it's because you can't take the average of an alternating current because the sum of all points is zero. However, for a full explanation, take a look at: http://www.allaboutcircuits.com/vol_2/chpt_1/1.html That site goes into it a lot farther that I can here.

    ReplyDelete
  125. dave, the number of samples = 3000? what it means?
    is it mean my code samples at about 3000 per second?

    ReplyDelete
  126. No, it means it take 3000 samples before it does a calculation.

    ReplyDelete
  127. Dave,
    can you explain about : 1) uint8_t payload[] = { 0, 0 };
    2) what a difference of API mode 1 and 2.
    3) a brief description of communication API mode in XBee. I mean how it
    I've make it succesfully but I dont know about the third point works?
    Thanks in advance

    ReplyDelete
  128. uint8_t payload[] = { 0, 0 }; is a two byte array of integers
    The two API modes are exactly the same except mode 2 requires certain characters be changed before transmission. The official explanation is a good one and is detailed in the XBee users guide that you can get on the Digi site.

    ReplyDelete
  129. Hey dave,

    I wanna ask about XBee's address
    Why “High” part of the address in every XBee has same value? 0013A200.

    Can you explain to me?
    Thank you in advance.

    ReplyDelete
    Replies
    1. That's the manufacturers number. If you get a Zigbee device from some other manufacturer, it will have a different number there.

      Delete
  130. Very interesting thread. I too am working on a house energy monitor, but the plan for wattage calculation isn't going to be done on the Arduino. Instead, I have installed two Scientific Columbus watt transducers - one for each leg entering the house (using CTs - Potential Transformers are integral to the transducers). They provide an analog output (current output) which can be scaled with the appropriate resistor. This way, the instantaneous power calculations are all done in the analog domain - no processor power necessary. See EBay for the watt transducers. The Arduino will act as the integrator to calculate watt-hours and store the intervals. Right now, this setup is sensitive enough to sense the kicking in and out of my soldering iron.

    ReplyDelete
  131. If I turn off everything else, my setup will measure a soldering iron turning on and off. That pretty much disappears when I turn on other stuff. Even ceiling fans will vary their power usage due to load when I open a door and the breeze blows through. Also, 40 watts or so from a soldering iron cycling pretty much disappears when the dryer kicks on and pulls 9kW. When the AC compressor kicks, a soldering iron is pretty darn insignificant. My savings on power has almost totally come from controlling the high usage devices. I gave up a long time ago worrying about parasitic devices like televisions (instant on and remote controlled) and battery chargers for cell phones that are left plugged in.

    If I watched and controlled them carefully, I would probably save a couple of hundred Watt hours; that just isn't worth worrying about.

    I am fascinated by the idea of a watt transducer. I spent a couple of hours reading about them before I looked at the prices. Price aside though, they are nice devices. I'd love to see circuit diagrams and pictures of your setup.

    Most of the folk I hear from complain about the $15 or so that they have to pay for current transformers and look for the cheapest arduino clone they can find, so your solution would really cause them to comment.

    But, now that I've been introduced to this technique, I have to wonder why the power companies use digital meters. They measure the power much the same way I do; they just put a heck of a lot of work into calibration and temperature compensation.

    ReplyDelete
  132. Hey Dave

    Great project you are doing. I am going to try to install one myself. but I do have a question about the way you measure your line voltage. First you transform it to 9V and then you use a voltage divider but I don't completely understand why you hook up the 5V of the arduino, 2 10K resistors and the condensator.... Could you give a bit more explanation about the Schematic you drawed ...

    Thanks and keep up the good work!

    Simon

    ReplyDelete
    Replies
    1. Way up there in the comments I provide some links that talk about exactly what you're wondering about. Actually, if you prowl through the comments, you'll find answer to a LOT of the things that people wonder about from time to time. To get you started, look here:

      http://openenergymonitor.org/emon/buildingblocks/measuring-voltage-with-an-acac-power-adapter

      Delete
  133. Hi Dave, I really enjoy your blog. I even have an alarm in Chrome which notifies me if you open a new entry.
    I have a question, so far I have been working with XBee in AT mode, I need to switch to API to allow more nodes and prevent mix information being gathered by the Raspberry Pi centrar receiver.
    Could you explain, or even easier and better, snapshot the XCT configuration of your coordinator, routers, and end devices of the network. Maybe in a new blog post explain which parameters are crucial to setup to allow the type of communitaction you are working with. Maybe in both cases, with broadcast on and off. Although if broadcast means that intermediate nodes pick up messages and resend them, I am not sure how you managed to overcome the long distances between node and central control , that you mention in this blog entry.

    Thanks for your time writing this blog and I encourage you to continue, its really interesting.

    ReplyDelete
    Replies
    1. Serge, I've been trying to avoid creating tutorials on how to set up and XBee to do various things because there are literally thousands of them out there on the web. However, based on the questions I've gotten, folk aren't able to understand them. I also don't like the idea of posting the setup of my XBees because then people don't think about what they're doing and just copy what I did, then complain about it not working in their particular setup.

      Sounds arrogant and childish doesn't it ? I don't mean to be that way, but there's no substitute for actually reading the XBee documentation and understanding what is going on. However, there is some reason to be confused about API mode. I have a post that is supposed to help people understand this, but maybe that isn't enough. (continued)

      Delete
    2. API mode only applies to what comes out or goes into the serial port of the XBee, not what goes over the air between XBees. It's simply a protocol for serial communication with the XBee. And, only the one XBee that you're dealing with. Changing one XBee doesn't affect the others or prevent communication between them because the XBees have their own protocol for comm, that we can't see and don't want to know about.

      So, the setting in XCPU is under 'Serial Interfacing' and is called 'API Enable' which you set to 0 for AT mode, 1 for API mode 1, and obviously, 2 for API mode 2. The difference between the two API modes is discussed on the XBee page, look at the top of the page for the tabs and go read it.

      Next, because the code is too big to fit all the options on an XBee, you have to load the correct software on the XBee. I use modem XB24-ZB and Zigbee coordinator API from the function set.

      Ah, crap, this is getting ridiculous and too long. I'll put together a blog post about it and post it. I really hate having to do this because it'll generate thousands of questions, and people won't go read the XBee documentation. But, it's pretty obvious that someone has to do it ...

      Delete
  134. Hi, have you heard about smappee ? It is device which monitors your power line and has ability to discover appliances plugged in. I have a lot of fun with it trying to integrate it with my home automation environment which is based on openremote middleware. Already discovered few power thieves of which I was not aware off. Now, I'm automatically switch them off with smart plugs and saving my energy bill.

    ReplyDelete
    Replies
    1. I've read about Smappee, but I couldn't find out anything about the protocol they use to communicate with the switches. Their stuff is based on sending data to a central location and compiling it there.

      I don't like having my data depend on a cloud based server. I keep thinking about the Alertme cloud server that used to be in the UK. After they got a number of customers on the server, they sold it. Suddenly the folk that were involved were out of luck and had to go looking for a new service. That kind of crap makes me avoid cloud services as something I depend on.

      Delete
  135. They are using 433MHz radio for their plugs ( http://support.smappee.com/hc/en-us/articles/201602599-How-to-pair-the-plugs-to-my-Smappee- ). It is local radio (unlike WeMo) so no need the cloud for switching it. However, their distance is only 30 m, which would not work with you I suspect.
    They have API so it is possible to integrate it with different technology. Right now, API is indeed cloud based but the Smappee controller is attached to my home LAN. I've already asked them if they have local API for the real time processing, but unfortunately not. Right now for it I would need use the local web interface and some hacking. But, my impression is that they are eager to improve it. When I suggested that I need switch API command - it wasn't there when I've took my first look on API - it took them less than 24h to add it. So my idea is, that some real power user like you could give them lot of ideas to improve their product. Their CEO accepted my Linkdin invitation, something which I would never expect from Belkin's CEO ;) IMHO, your input about why cloud is bad would be valuable for them. The Smappee device isn't expensive and has a lot of potential. Mind, it is not perfect yet.

    ReplyDelete