/*
AC Power Calculations
Average Power, Apparent Power, Reactive Power, Irms, Vrms, Power Factor, Power Factor Angle
Date: Dec. 11, 2009
Line Current is measured using a current transformer from CR Magnetics.
CR8410-1000 @ http://www.crmagnetics.com/8400.pdf
Line voltage measurement via a standard AC step down transformer
Author: peter c
*/
#include <string.h>
#include <LCD4Bit.h>
#include <ACSignal.h>
#include <PowerSignal.h>
#define LCD_DISPLAY_WIDTH 16
#define LCD_DEGREE_CHAR 0xF2
#define CURRENT_BLACK_PIN 1 // current 1st 100 AMP input pin (black )
#define CURRENT_RED_PIN 3 // current 1st 100 AMP input pin (red )
#define VOLTAGEPIN 2 // voltage signal input pin
#define DC_OFFSET 2.5 // signal shifted 2.5 above ground
#define Te 2011 // current transformer effective turns ratio from speck sheet
#define CT_VMAX 2.5 // maximum level shifted voltage from CT to input e.g. 7.2 v rms to 2.5 v-pp offset
#define CT_VRATED 10.1823 // Max rated RMS voltage * sqrt(2) of CT from spec sheed
#define CT_LOAD_RES 2000 // current transformer load resistor to create a voltage drop
#define MAX_SAMPLES 2000 // Samples per Calculation
#define PEAK_LINE_VOLTAGE 170 //120 * sqrt(2)
#define PEAK_VOLTAGE_TRANSFORMER 2.5 // input to A2D max AC value
#define BLACK_INDEX 0 // offsets into array for holding power values
#define RED_INDEX 1
#define MAX_PRECISION 5
//create object to control an LCD.
//number of lines in display=1
LCD4Bit lcd = LCD4Bit(2);
ACSignal voltageSignal( VOLTAGEPIN, PEAK_LINE_VOLTAGE/PEAK_VOLTAGE_TRANSFORMER, DC_OFFSET );
ACSignal currentSignalBlack( CURRENT_BLACK_PIN, Te / CT_LOAD_RES * CT_VRATED / CT_VMAX, DC_OFFSET );
//ACSignal currentSignalRed( CURRENT_RED_PIN, Te / CT_LOAD_RES * CT_VRATED / CT_VMAX, DC_OFFSET );
PowerSignal panelBlack( voltageSignal, currentSignalBlack );
// Simplistic Float to Alhpa used for displaying floats on the LCD
// decimal is good for 1 to 5. no error checks. garbage in - garbage out.
// problem: number like 1.01 => 1.009 need to look into that later.
char *poor_ftoa( char *a_buffer, float a_number, int a_decimals )
{
int l_decPart;
int l_precision = a_decimals;
char l_buffer[ MAX_PRECISION + 1];
int l_multiplier;
float x;
l_multiplier = 10;
x=a_number - (int)a_number;
if( x < 0 )
x *= -1;
for( int i=0; i<a_decimals; i++ )
{
x *= l_multiplier;
l_buffer [ i ] = '0' + (int) ( x );
x -= (int) x;
}
l_buffer[ a_decimals ] = '\0';
sprintf(a_buffer,"%0d.%s", (int)a_number, l_buffer);
return( a_buffer );
}
void setup()
{
lcd.init();
Serial.begin(9600); // start serial communication
//debugging info. comma separated to make it easier to import into excel
Serial.print( "currentSignalBlack.getDCOffset()," );
Serial.print( "currentSignalBlack.getRMSValue( )," );
Serial.print( "voltageSignal.getDCOffset()," );
Serial.print( "voltageSignal.getRMSValue()," );
Serial.print( "l_averagePower," );
Serial.print( "l_apparentPower," );
Serial.print( "l_reactivePower," );
Serial.print( "l_powerFactor," );
Serial.print( "l_powerFactorAngle *180 / PI," );
Serial.print( "Voltage Crest factor," );
Serial.println( "CurrentBlack Crest factor," );
}
void loop()
{
float l_sumForAveragePower[2];
float l_averagePower[2];
float l_apparentPower[2];
float l_powerFactor[2];
float l_powerFactorAngle[2];
float l_reactivePower[2];
voltageSignal.beginSampling();
currentSignalBlack.beginSampling();
panelBlack.reset();
for( int i=0; i<MAX_SAMPLES; i++)
{
voltageSignal.acquireSignalSample();
currentSignalBlack.acquireSignalSample();
panelBlack.updateAccumulator();
}
voltageSignal.endSampling();
currentSignalBlack.endSampling();
l_averagePower[ BLACK_INDEX ] = panelBlack.computeAveragePower();
l_apparentPower[ BLACK_INDEX ] = panelBlack.computeApparentPower();
l_powerFactor[ BLACK_INDEX ] = panelBlack.computePowerFactor();
l_powerFactorAngle[ BLACK_INDEX ] = panelBlack.computePowerFactorAngle( PS_RADIANS );
l_reactivePower[ BLACK_INDEX ] = panelBlack.computeReactivePower();
...
...
...
[...] Power Measurement [...]