Ghost 0.14A load?

Not sure whether I'm dealing with a hardware or software problem so here it goes in the general forum. I've got a monitor setup and it's working reasonably well however for some strange reason I am reading a ghost 0.14A even when the cable that the CT is clamped to is unplugged from the mains. The weird thing is that it is spot on when measuring a load that has been verified with a DMM. So if I futz around with any of the settings it might fix the .14A reading but throws off the good values when there's a load. I'm hoping this is just a duh moment on my part that someone could see from a mile away.

I ended up picking up a 333mV CT with 100A range in part because they could be had cheaply and in part because they seem to be everywhere once I started looking for them. Not an ideal range for what I want to measure but it works, sort of. While I have no datasheet for my CT, after cracking the case on the sensor I found a 40.2 ohm burden resistor inside so using the online calculator my best guess is that the CT has somewhere in the ballpark of 2200 turns. Im also using a 12 VAC adapter that outputs something like 14 V for a reference and my circuit is simply the bog standard one with a bunch of 10k resistors and a 100k resistor on the AC line, with no external burden resistor of course. I've also hooked up a graphic lcd to make a nice little package out of this monitor when Im done.

So here's the code Im working from. Mostly the standard emon code cleaned up some and brought in line with Arduino 1.0 along with the lcd display stuff, although Im still working on the sketch. Ive also worked up some code for a kwh total although it will reset when millis() resets but Im not sure I can be bothered about that. Like I said, this setup is bang on when measuring a known load but when everything is turned off it still displays a 0.14A load. Any thoughts?

Cheers-

Brian

#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

const int numberOfSamples = 3000;
const int voltageSensor = A0;
const int currentSensor = A1;

const float AC_WALL_VOLTAGE      = 124.0;
const float AC_ADAPTER_VOLTAGE   = 14.1;
const float AC_VOLTAGE_DIV_RATIO = 11.0;
const float CT_BURDEN_RESISTOR   = 40.2;
const float CT_TURNS             = 2274.0;

//Calibration coeficients
const float VCAL = 1.015;
const float ICAL = 1.05;
const float PHASECAL = 0.1;

// Initial gueses for ratios, modified by VCAL/ICAL tweaks
const float AC_ADAPTER_RATIO = (AC_WALL_VOLTAGE / AC_ADAPTER_VOLTAGE);
const float V_RATIO = AC_ADAPTER_RATIO * AC_VOLTAGE_DIV_RATIO * 5 / 1024 * VCAL;
const float I_RATIO = CT_TURNS / CT_BURDEN_RESISTOR * 5 / 1024 * ICAL;

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

//Filter variables
float lastFilteredV,lastFilteredI,filteredV,filteredI;

//Power calculation variables
float sumI,sumV,sumP;

//Stores the phase calibrated instantaneous voltage
float calibratedV;

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

unsigned long last_kWHtime, kWHtime;
float kWH = 0.0;

void setup() {
 lcd.begin(16,2);
}

void loop() { 
 calculatePower();

 last_kWHtime = kWHtime;
 kWHtime = millis();
 kWH += realPower * ((kWHtime-last_kWHtime)/3600000.0);

 lcd.clear();
 lcd.print(realPower, 0);
 lcd.print(" ");
 lcd.print(apparentPower, 0);
 lcd.print(" ");
 lcd.print(powerFactor, 2);
 lcd.setCursor(0,1);
 lcd.print(Vrms, 0);
 lcd.print(" ");
 lcd.print(Irms, 2);
 lcd.print(" ");
 lcd.print(kWH);
}

void calculatePower() {
 for (int n=0; n<numberOfSamples; n++) {
   //Used for offset removal
   lastSampleV = sampleV;
   lastSampleI = sampleI;

   //Read in voltage and current samples.   
   sampleV = analogRead(voltageSensor);
   sampleI = analogRead(currentSensor);

   //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
   sumV += calibratedV * calibratedV;

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

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

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

 //Calculation power values
 realPower = V_RATIO * I_RATIO * sumP / numberOfSamples;
 apparentPower = Vrms * Irms;
 powerFactor = realPower / apparentPower;

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

glyn.hudson's picture

Re: Ghost 0.14A load?

 Hi Bw Evans,

Sounds like good progress. I think your pretty much there. Due to noise in the circuit the reading when nothing is connected will never be quite zero. Trystan should be able to explan this in greater detail to you. 

If you really want increased accuracy at low power readings you should use a lower rated CT. 

Its interesting that you have used Arduino 1.0. We are yet to try it out ourselves. I would be intrested to hear what changes (if any) you had to make to the energy onitor sketch to make it compile?

All best, Glyn. 

bwevans's picture

Re: Ghost 0.14A load?

Actually, I didn't have to make any changes to get it to compile which was nice for a change. A few of the changes I did make was to move the double datatypes over to floats (floats and doubles are identical in Arduino and generally I find floats easier to explain), changed all constants and #defines to the const variable qualifier (again to make them more Arduino friendly and in my testing const is better than #define when using the Arduino library and has no impact on RAM), I took out the sqI, sqV, and instP variables consolidating those operations with the sum operations (to save a little memory and streamline the code), and I moved the bulk of the code into a function to make it a little easier to read the loop() function if/when I start to add sd logging and/or ethernet connectivity. I'm actually writing this up for a chapter in an upcoming Arduino book which is why I needed to bring it into line with some of the other code samples. Still working on it though so I'll let you all know how it works out.

So the sensitivity is much as I expected, I just wanted to make sure I wan't missing something totally obvious. A little reality check is always a good thing. Thanks for the quick reply - this community has been great with lots of information and work done to make these things so simple to work with. Thanks again!

Cheers-
Brian

glyn.hudson's picture

Re: Ghost 0.14A load?

 Hi Brian,

Thats good to hear. I like the chages you have suggested. In due cause I will update the source code on github. 

What is the book that your writing? This is great news, let us know if we can be of assistance. Could you sent us the section your write about energy monitoring before the book goes to press so we can have a read through?

Cheers, Glyn. 

bwevans's picture

Re: Ghost 0.14A load?

Glyn-

I just finished up Beginning Arduino Programming for Apress Media to be published in the next week or so and have been asked to contribute a chapter to Emery Premeaux's upcoming Arduino Projects to Save the World. I'm on a super tight deadline but would love some feedback. Why don't you send me an email at bevans24 [at] mscd [dot] edu and I can bounce you a manuscript for the chapter early next week. There's only so much that I would be able to change but I would welcome your thoughts and ciritcism.

Cheers-

Brian

calypso_rae's picture

Re: Ghost 0.14A load?

I think your 0.14A figure for current is just a consequence of random noise.  Because of the squaring, the calculation for Irms sees all sample values as positive. 

(Unless, or course, you are seeing 33W of background 'real power')

Robert Wall's picture

Re: Ghost 0.14A load?

You've dug up an old post there, Robin!

calypso_rae's picture

Re: Ghost 0.14A load?

Sure, but the underlying principles are unlikely to have changed much since then. 

I got there via a Building Blocks page ...

PaulOckenden's picture

Re: Ghost 0.14A load?

A ghost topic about ghost current from a ghost poster!

Spooky!

P.

Comment viewing options

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