A few questions

I posted this in the software area but didnt get a response so trying here plus another question:

==================================

Hi Guys,

I am going to try and use my existing Arduino based inverter monitor to also monitor my household consumption. I am planning on basing it heavily on the great work on here. I am currently looking at modifying the "Basic energy monitoring sketch" I have a few questions in relation to that specific script:

I can poll my inverter for the current mains voltage so I don't need the AC-AC adapter solution. Given that I get an accurate mains voltage should I just comment out filteredV and shiftedV and use sampleV all the way down.

I assume that the code in this thread: http://openenergymonitor.org/emon/node/198 is what I would use to calculate the total consumption for the day. I then just need to write a small bit of code to calculate a RMS for real power because the data is uploaded every 5 mins.

EDIT: Also I am using 3 phase power so what is the best way to combine this. (1) Do three analogue reads and add them together for a total sampleI (or does the IRATIO vary too much between CTs?); or (2) Do consecutive calls to the function for each phase and add the real powers at the end; or (3) Something else??

================================

Plus my latest question after having built it is I am finding that my calibration curve isn't linear. I need a ICAL of about 1 for loads around 500W, at 2000W it is 1.25 and at 200w it is 0.66. So any ideas about this. Could it be my power meter? Could it be my circuit (I used 5% resistors)? Has anyone seen this before? I thought I could just get around it by using a simple IF-THEN and using a different ICAL depending on the raw power measurement?

Thanks for any help!

Krumlov's picture

Re: A few questions

Still would appreciate any additonal info but I think I have solved the calibration problem. I had noticed that I was getting 30-40W indicated when I had nothing connected but there were posts elsewhere on this site that said that was normal so I didn;t think anything of it. However it occurred to me that that is a significant proportion of any loads that are a few hundred watts. So I measured the values being returned with nothing connected (which was around 510) and then started subtracting that from the read values so that when nothing was connected I was getting only a couple of watts being shown.

This basically fixed it. My ICAL values are now around 2.6 and am seeing an accuracy of +/-3% of the plug in meter. So pretty happy I might have solved it. Why I am having this problem and no-one else I don't know.

Still would like some opinions on the best way to handle 3 phase power. I have seen the two phase example and note that it uses separate calls for each phase. I think it would be faster to read each pin and add them all together if this would work. Thoughts?

Krumlov's picture

Re: A few questions

Bit disappointed I wasn't able to get any feedback on my questions but for those in the future here is my test sketch that I came up with to get it to work for me. Thanks to those who came up with the initial sketches and circuits but I don't know how others have it working so well without removing the "noise" from the data. Unless mine is more noisy than others. I do have the three current sensing electronics and the voltage sensing all on a tiny breadboard. In any case once I started to remove the false readings I found that acted as a calibration for the low end of the current range and then the ICAL variable did the adjustment for the high end. I have 3 phase power so you will see how I solved that, I only reasonably had the ability to measure voltage on one phase so there will be some inaccuracies there but you will also see the effect that had on the PHASECAL values. Lastly I commented out a bunch of variables as I was trying to get this to work on a UNO which is also doing some other stuff so memory is at a premium. Again this is only a test sketch that I was using as a proof of concept but hopefully someone will find it useful.

 

/**************************************************************\
 * | ORIGINALLY:
 * //Basic energy monitoring sketch
 * //Authors: Trystan Lea, Eric Sandeen
 *
 * //Licenced under GNU General Public Licence more details here
 * // openenergymonitor.org
 \**************************************************************/

/*********************************************************************\
 * |Modified for future use as an energy monitor      |
 * |which uploads to pvoutput.org                                        |
 * |This version is test/calibration sketch                              |
 * |                                                                     |
 \*********************************************************************/
//Sketch measures voltage and current.
//and then calculates useful values like real power,

#define  PHASE_A  0
#define  PHASE_B  1
#define  PHASE_C  2
//Setup variables
int numberOfSamples = 3000;

//Set Voltage and current input pins
int inPinV = 2;
int inPinI[3] = {5, 4, 3};
//Sanity check calibration method thanks to Eric Sandeen http://sandeen.net/wordpress
//See discussion here: http://openenergymonitor.org/emon/node/59
//Enter the values of your setup below

// Voltage is reduced both by wall xfmr & voltage divider
// #define AC_WALL_VOLTAGE        245
// #define AC_ADAPTER_VOLTAGE     14.1
// Ratio of the voltage divider in the circuit
// #define AC_VOLTAGE_DIV_RATIO   13
// CT: Voltage depends on current, burden resistor, and turns
//#define CT_BURDEN_RESISTOR    56
//#define CT_TURNS              1350
//Calibration coeficients
//These need to be set in order to obtain accurate results
//Set the above values first and then calibrate futher using normal calibration method described on how to build it page.
double VCAL = 1.1567;
double ICAL[3] = {2.28, 2.3, 2.17};
double PHASECAL[3] = {-4.5, 5.78, 6.49};

double I_ZERO[3] = {512.2, 509.5, 511.6};
// Initial gueses for ratios, modified by VCAL/ICAL tweaks
//#define AC_ADAPTER_RATIO       (AC_WALL_VOLTAGE / AC_ADAPTER_VOLTAGE) // Variable Saving
double V_RATIO = (245/14.1) * 13 * 5 / 1024 * VCAL; // Variable Saving this was = AC_ADAPTER_RATIO * AC_VOLTAGE_DIV_RATIO * 5 / 1024 * VCAL;
double I_RATIO = (long double)1350 / 56 * 5 / 1024;  // Variable Saving this was = (long double)CT_TURNS / CT_BURDEN_RESISTOR * 5 / 1024 * ICAL;

//Sample variables
float lastSampleV,lastSampleI[3],sampleV,sampleI[3];
//Filter variables
double lastFilteredV, lastFilteredI[3], filteredV, filteredI[3];

//Stores the phase calibrated instantaneous voltage.
double shiftedV[3];
//Power calculation variables
double sumP;

//Useful value variables
double realPower[3];
//Variables used by Gav to determine total power consumption     
double Total_Daily_Consumption = 0L,   // This is the total power for the day and is a sum of the xxxx multipled by the time since last update
Sum_Power_Used = 0L;            // This is the average instantaneous power used to be uploaded at every 5 mins.

unsigned long lwhtime, whtime = 0L;
int number_PowerCalcs = 0;
char status_url[200];

void setup()
{
  Serial.begin(9600);
  sampleV = analogRead(inPinV);                        //Do a read now to stop spurious first calculations
  sampleI[PHASE_A] = analogRead(inPinI[PHASE_A])-I_ZERO[PHASE_A];
  sampleI[PHASE_B] = analogRead(inPinI[PHASE_B])-I_ZERO[PHASE_B];
  sampleI[PHASE_C] = analogRead(inPinI[PHASE_C])-I_ZERO[PHASE_C];
}

void loop()
{
  float tempPower = 0;
  for (int phase=0; phase<=2; phase++){
    Calc_Power_Used(phase);

    lwhtime = whtime;
    whtime = millis();
    Total_Daily_Consumption += realPower[phase] * ((whtime-lwhtime)/(3600000.0));
    tempPower += realPower[phase];
    switch(phase){
      case(0):
      Serial.println("PHASE A");
      break;
      case(1):
      Serial.println("PHASE B");
      break;
      case(2):
      Serial.println("PHASE C");
      break;
    }
    //Output to serial
    Serial.print(" RP ");
    Serial.print(realPower[phase]);
    Serial.print(" Increment ");
    Serial.print(realPower[phase] * ((whtime-lwhtime)/(3600000.0)));
    Serial.print(" Total ");
    Serial.print(Total_Daily_Consumption);
    Serial.print(" Sum Power ");
    Serial.print(Sum_Power_Used);
    Serial.print(" Calcs ");
    Serial.print(number_PowerCalcs);
    Serial.print(" TIME ");
    Serial.println(whtime-lwhtime);

  }
  Sum_Power_Used += (tempPower * tempPower);
  number_PowerCalcs++;

  sprintf(status_url, "v3=%ld&v4=%d HTTP/1.0\0", long(floor(Total_Daily_Consumption)), (int)round(sqrt(Sum_Power_Used / number_PowerCalcs)));
  Serial.println(status_url);
}


/*******************************************************************\
 * |                                                                   |
 * | Calc_Power_Used determines the power being used at that moment    |
 * | in time. The main loop then looks at the time differential        |
 * | and adds the real power used to the total used.                   |
 * |                                                                   |
 * | This will loop for 3000 samples or 3 seconds whatever comes first |
 * |                                                                   |
 \*******************************************************************/
void Calc_Power_Used(int phase)
{
  unsigned long start = millis();
  int n = 0;
  while ((n < numberOfSamples) && (millis() - start) < 3000)
  {
    n++;
    //Used for offset removal
    lastSampleV=sampleV;
    lastSampleI[phase]=sampleI[phase];

    //Read in voltage and current samples.  
    sampleV = analogRead(inPinV);               
    sampleI[phase] = analogRead(inPinI[phase])-I_ZERO[phase];
    if (sampleI[phase] < 0) sampleI[phase] =0;
    //Used for offset removal
    lastFilteredV = filteredV;
    lastFilteredI[phase] = filteredI[phase];

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

    //Phase calibration goes here.
    shiftedV[phase] = lastFilteredV + PHASECAL[phase] * (filteredV - lastFilteredV);
    //shiftedV = sampleV;
    //Instantaneous Power
    sumP = sumP + shiftedV[phase] * filteredI[phase];

  }
  //Calculation of the root of the mean of the voltage and current squared (rms)
  //Calibration coeficients applied.

  //Calculation power values
  realPower[phase] = V_RATIO*I_RATIO*ICAL[phase]*sumP / numberOfSamples;
  //Reset accumulators
  sumP = 0; 

}

 

 

Mr. Sharkey's picture

Re: A few questions

No expert here, but I found that if the burden resistors on the current transformers are not selected carefully, the resulting voltage sample is not linear over the entire measurement range. My test showed that after a break-over level, the voltage increase was no longer linearly proportional to the current increase when the resistor value was too high.

Krumlov's picture

Re: A few questions

Thanks for the reply. Your link didn't work for me but I used the standard Efergy CTs and a resistor of 56 Ohms which was recommended somewhere on the site. So not sure if that was my problem?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.