Calculating RMS Voltage

06 Jan 2012

I'm trying to calculate RMS voltage from analog pin 19 so that I can convert that for working out the current reading from a CT sensor.

I've taken some working Arduino code and attempted to convert/replicate for MBED but my results are way off! Could one of you really experienced chaps take a look and see if you can steer me in the right direction?

My CT sensor outputs 1v AC that's linear to the current so I am offsetting with a volatage divider.

Thanks!

#include "mbed.h"           // standard
#include "TextLCD.h"        // for the LCD


AnalogIn CurAnalog(p19); // Read this for current 




TextLCD lcd(p21, p22, p23, p24, p25, p26); // re, e, d0, d1, d2, d3


DigitalOut Dummy1(p15); //doing this to help stabilise the analog readings
DigitalOut Dummy2(p16); //doing this to help stabilise the analog readings
DigitalOut Dummy3(p17); //doing this to help stabilise the analog readings
DigitalOut Dummy4(p18); //doing this to help stabilise the analog readings

//Setup variables
int numberOfSamples = 3000;


// CT: Voltage depends on current, burden resistor, and turns
#define CT_BURDEN_RESISTOR      62
#define CT_TURNS                1800

//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 ICAL     = 1.046;


double I_RATIO      = (long double)CT_TURNS / CT_BURDEN_RESISTOR * 5 / 1024 * ICAL;

//Sample variables
int lastSampleI,sampleI;  // was int, converted to float

//Filter variables
double lastFilteredI, filteredI;
double filterTemp;



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

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




// this is for getCurrent
float getCurrent() {
    return CurAnalog.read();
};
// end of getCurrent


int main() {

    int n;

    while(1) {
    
        //Reset accumulators - THIS SHOULD ALWAYS HAVE BEEN FIRST, NOT LAST
        sumI    = 0;
        sampleI = 0;
    
        for (n=0; n<numberOfSamples; n++)
        {
        
            //Used for offset removal
            lastSampleI=sampleI;
            
            //Read in current samples.
            sampleI = (int)(getCurrent()*1024);
            
            //Used for offset removal
            lastFilteredI = filteredI;
            
            //Digital high pass filters to remove 1.65V DC offset.
            filteredI = 0.996*( lastFilteredI + (double)(sampleI-lastSampleI) );
            
            //Root-mean-square method current
            //1) square current values
            sqI = (double)(filteredI * filteredI);
            
            //2) sum
            sumI += sqI;
            
        }
        
        Irms = (double)(I_RATIO*sqrt(sumI / (double)numberOfSamples));
        
        lcd.printf(" %f\n",  (float)Irms);  // strictly speaking the cast to float isn't needed, but always good to be good
         
        wait(1);

    }
    
}

06 Jan 2012

Hi Leo,

Trying to work through this - always hard to debug other peoples code.

I did notice...

//Sample variables
int lastSampleI,sampleI;  // was int, converted to float

These are still integers not floats.

Also...

//Read in current samples.
sampleI = (int)(getCurrent()*1024);

Where it runs off to the function to read the pin could be simplified to

//Read in current samples.
sampleI = (int)(CurAnalog.read()*1024);   // This will give between 0 and 1024

But I seriously doubt that this is your problem.

How much current are you measuring? Or rather what is the max. and min. voltages your measuring? If they are >3V3 or <0V when they reach the mbed then this would mess things up.

Also not sure about the high pass filter - your keeping all the noise and rejecting the signal? This would not remove the 1.65V offset would it? For this I would try...

float no_offset;

no_offset = sampleI - 1.65;

Hope this helps you out.

Martin

06 Jan 2012

I would recomend that you either use an oscilloscope, to test the ACTUAL Output from your sensor.

But if dont have one, or accses to one, then you need to try this;

Sample the voltage from your sensor, with at least 4 different currents. Save as a text/csv file and load into excell.

I am guessing that the O / P will be positive, as well as negative. Unless you have have cicuitry to shift the offset.

Alturnatly, you should be able to get a dedicated chip,

Hope this helps

Enjoy

Ceri

07 Jan 2012

Yes,

That filter is not necessary. Since we know that the midpoint of a waveform with zero offset is at 1.65, we can just subtract. This will also give you a true representation of the waveform. If your incoming voltage does have an offset, it will still be there and the RMS value will be more representative of the actual waveform.

When you filter, you lose information.

Also, if you can afford the extra overhead, do everything in floats. it's easier to debug that way. :). You can always optimize later.

Edit:

I just noticed that you are already doing most of it in floats. I am not sure why you get the current sample as an int.