/*
ACSignal.h - A simplistic way to represent a AC signal for AC AC monitoring
Author: peter c
*/
#ifndef ACSignal_h
#define ACSignal_h
#include "WProgram.h"
#define PS_AD_RESOLUTION 1024.0
#define PS_VOLTS_PER_STEP 0.0048887 // 10 bit A2D reference voltage not 5 but 4.82 => 4.82/1024
#define PS_DEFAULT_DC_OFFSET 2.5 // AC signal wil be likely 2.5 +/- 2.5
#define PS_PWR_CALC_ERR -1;
#define PS_SCALING_DEFAULT 1
#define PS_DEFAULT_PORT 1
class ACSignal
{
public:
ACSignal();
ACSignal(int aPin);
ACSignal(int aPin, float aScalingValue);
ACSignal(int aPin, float aScalingValue, float aDCOffset);
void beginSampling();
void endSampling();
void setReferenceVoltage( int aReferenceVoltage );
void setCalibratedCoefficients( float aSlope, float aIntercept );
float acquireSignalSample();
void setDCOffset( float aDCOffset ); // AC signal is offset by DC value. typically half-way markt of 0-5 volts
void setScalingValue( float aScalingValye ); // this is the scaling value used to convert voltage to desired units
float getDCOffset();
float getInstantaneousValue(); // return the value of last read sample in scaled units. e.g. amps
float getMaxValue();
float getMinValue();
float getRMSValue(); // return RMS value of signal
float getScalingValue(); // this is the scaling value used to convert voltage to desired units
float getCrestFactor(); // compute crest factor ration of peak to RMS
float getCurrentVoltage(); // return current voltage read from input (0-5 v)
int getSampleCount(); // return numnre of samples taken since beginSample();
int getCurrentSampleValue(); // return current sample 0-1023
// char* toString( char* aBuffer );
// char* toDbgString( char* aBuffer );
private:
void init( int aPin, float aScalingValue, float aDCOffset );
// char* poor_atof(char *a_buffer, float a_number, int a_decimals);
protected:
int mPin;
float mMax;
float mMin;
float mAverage;
float mCurSample;
int mcurValue;
float mScalingValue;
int mSampleCount;
float mSumVoltageRaw;
float mRealVoltage;
float mSumVoltageSquared;
float mCurVoltage;
float mDCOffset;
float mVoltsPerStep;
float mCalibratedSlope;
float mCalibratedIntercept;
// char mtoStringBuffer[300];
};
#endif
BODY
/*
ACSignal.cpp - Library doing basic signal calculations
Created by Peter C, December 11, 2009
*/
#include "WProgram.h"
#include "ACSignal.h"
ACSignal::ACSignal()
{
init( PS_DEFAULT_PORT, PS_SCALING_DEFAULT, PS_DEFAULT_DC_OFFSET );
}
ACSignal::ACSignal(int aPin)
{
init( aPin, PS_SCALING_DEFAULT, PS_DEFAULT_DC_OFFSET );
}
ACSignal::ACSignal(int aPin, float aScalingValue)
{
init( aPin, aScalingValue, PS_DEFAULT_DC_OFFSET );
}
ACSignal::ACSignal(int aPin, float aScalingValue, float aDCOffset)
{
init( aPin, aScalingValue, aDCOffset );
}
float ACSignal::getRMSValue()
{
float lRMSValue = PS_PWR_CALC_ERR;
if( mSampleCount > 0 )
lRMSValue = sqrt( mSumVoltageSquared / mSampleCount );
return( lRMSValue );
}
void ACSignal::init( int aPin, float aScalingValue, float aDCOffset )
{
mPin = aPin;
pinMode( mPin, INPUT);
mScalingValue = aScalingValue;
mDCOffset = aDCOffset;
mMin = 0;
mMax = 0;
mSampleCount = 0;
mSumVoltageRaw = 0;
mSumVoltageSquared =0;
mVoltsPerStep = PS_VOLTS_PER_STEP;
mCalibratedSlope = 1.0;
mCalibratedIntercept = 0.0;
}
int ACSignal::getCurrentSampleValue()
{
return( mCurSample );
}
void ACSignal::setReferenceVoltage( int aReferenceVoltage )
{
mVoltsPerStep = aReferenceVoltage / PS_AD_RESOLUTION;
}
void ACSignal::setCalibratedCoefficients( float aSlope, float aIntercept )
{
mCalibratedSlope = aSlope;
mCalibratedIntercept = aIntercept;
}
float ACSignal::acquireSignalSample()
{
float lVal;
mCurSample = analogRead( mPin ) ;
mCurVoltage = mCurSample * PS_VOLTS_PER_STEP;
mSampleCount++;
mSumVoltageRaw += mCurVoltage;
mRealVoltage = mCurVoltage - mDCOffset; // remove DC offset from circuit voltage divider
lVal = getInstantaneousValue();
mSumVoltageSquared += lVal * lVal;
if( lVal > mMax )
mMax = lVal;
if( lVal < mMin )
mMin = lVal;
return( lVal );
}
float ACSignal::getCrestFactor()
{
float lRMSValue = getRMSValue();
float lRetVal = 0.;
if( lRMSValue > .05 )
lRetVal = getMaxValue()/getRMSValue();
return( lRetVal );
}
float ACSignal::getDCOffset()
{
return( mDCOffset );
}
void ACSignal::setDCOffset( float aDCOffset )
{
mDCOffset = aDCOffset;
}
float ACSignal::getInstantaneousValue()
{
return( mRealVoltage * mScalingValue * mCalibratedSlope + mCalibratedIntercept);
}
float ACSignal::getCurrentVoltage()
{
return( mCurVoltage );
}
void ACSignal::setScalingValue( float aScalingValue )
{
mScalingValue = aScalingValue;
}
float ACSignal::getMaxValue()
{
return( mMax );
}
float ACSignal::getMinValue()
{
return( mMin );
}
int ACSignal::getSampleCount()
{
return( mSampleCount );
}
float ACSignal::getScalingValue()
{
return( mScalingValue );
}
void ACSignal::beginSampling()
{
mSampleCount = 0;
mSumVoltageRaw =0.0;
mSumVoltageSquared =0.0;;
mMax =0;
mMin = 0;
}
void ACSignal::endSampling()
{
if( mSampleCount > 0 )
mDCOffset = mSumVoltageRaw / mSampleCount;
}