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; }
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.
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
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.
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
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')
Re: Ghost 0.14A load?
You've dug up an old post there, Robin!
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 ...
Re: Ghost 0.14A load?
A ghost topic about ghost current from a ghost poster!
Spooky!
P.