Commit Iniziale, progetto funzionante caricato su box ETcontroller in
cantina
This commit is contained in:
213
TEnergyMonitor/TEnergyMonitor.cpp
Normal file
213
TEnergyMonitor/TEnergyMonitor.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* TEnergyMonitor.cpp
|
||||
*
|
||||
* Created on: 07 apr 2018
|
||||
* Author: Emanuele
|
||||
*/
|
||||
|
||||
#include "TEnergyMonitor.h"
|
||||
|
||||
TEnergyMonitor::TEnergyMonitor(Serial* _pc){
|
||||
pc=_pc;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Sets the pins to be used for voltage and current sensors
|
||||
//--------------------------------------------------------------------------------------
|
||||
void TEnergyMonitor::voltage(PinName _inPinV, double _VCAL, double _PHASECAL)
|
||||
{
|
||||
inPinV = _inPinV;
|
||||
VCAL = _VCAL;
|
||||
PHASECAL = _PHASECAL;
|
||||
offsetV = ADC_COUNTS>>1;
|
||||
adcV = new AnalogIn(inPinV);
|
||||
}
|
||||
|
||||
void TEnergyMonitor::current(PinName _inPinI, double _ICAL)
|
||||
{
|
||||
inPinI = _inPinI;
|
||||
ICAL = _ICAL;
|
||||
offsetI = ADC_COUNTS>>1;
|
||||
adcI = new AnalogIn(inPinI);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Sets the pins to be used for voltage and current sensors based on emontx pin map
|
||||
//--------------------------------------------------------------------------------------
|
||||
//void TEnergyMonitor::voltageTX(double _VCAL, double _PHASECAL)
|
||||
//{
|
||||
// inPinV = 2;
|
||||
// VCAL = _VCAL;
|
||||
// PHASECAL = _PHASECAL;
|
||||
// offsetV = ADC_COUNTS>>1;
|
||||
//}
|
||||
//
|
||||
//void TEnergyMonitor::currentTX(unsigned int _channel, double _ICAL)
|
||||
//{
|
||||
// if (_channel == 1) inPinI = 3;
|
||||
// if (_channel == 2) inPinI = 0;
|
||||
// if (_channel == 3) inPinI = 1;
|
||||
// ICAL = _ICAL;
|
||||
// offsetI = ADC_COUNTS>>1;
|
||||
//}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// emon_calc procedure
|
||||
// Calculates realPower,apparentPower,powerFactor,Vrms,Irms,kWh increment
|
||||
// From a sample window of the mains AC voltage and current.
|
||||
// The Sample window length is defined by the number of half wavelengths or crossings we choose to measure.
|
||||
//--------------------------------------------------------------------------------------
|
||||
void TEnergyMonitor::calcVI(unsigned int crossings, unsigned int timeout)
|
||||
{
|
||||
#if defined emonTxV3
|
||||
int SupplyVoltage=3300;
|
||||
#else
|
||||
int SupplyVoltage = readVcc();
|
||||
#endif
|
||||
|
||||
unsigned int crossCount = 0; //Used to measure number of times threshold is crossed.
|
||||
unsigned int numberOfSamples = 0; //This is now incremented
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------
|
||||
// 1) Waits for the waveform to be close to 'zero' (mid-scale adc) part in sin curve.
|
||||
//-------------------------------------------------------------------------------------------------------------------------
|
||||
bool st=false; //an indicator to exit the while loop
|
||||
|
||||
unsigned long start = millis(); //millis()-start makes sure it doesnt get stuck in the loop if there is an error.
|
||||
|
||||
while(st==false) //the while loop...
|
||||
{
|
||||
startV = adcV->read_u16(); //using the voltage waveform
|
||||
if ((startV < (ADC_COUNTS*0.55)) && (startV > (ADC_COUNTS*0.45))) st=true; //check its within range
|
||||
if ((millis()-start)>timeout) st = true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------
|
||||
// 2) Main measurement loop
|
||||
//-------------------------------------------------------------------------------------------------------------------------
|
||||
start = millis();
|
||||
|
||||
while ((crossCount < crossings) && ((millis()-start)<timeout))
|
||||
{
|
||||
numberOfSamples++; //Count number of times looped.
|
||||
lastFilteredV = filteredV; //Used for delay/phase compensation
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A) Read in raw voltage and current samples
|
||||
//-----------------------------------------------------------------------------
|
||||
sampleV = adcV->read_u16(); //Read in raw voltage signal
|
||||
sampleI = adcI->read_u16(); //Read in raw current signal
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// B) Apply digital low pass filters to extract the 2.5 V or 1.65 V dc offset,
|
||||
// then subtract this - signal is now centred on 0 counts.
|
||||
//-----------------------------------------------------------------------------
|
||||
offsetV = offsetV + ((sampleV-offsetV)/1024);
|
||||
filteredV = sampleV - offsetV;
|
||||
offsetI = offsetI + ((sampleI-offsetI)/1024);
|
||||
filteredI = sampleI - offsetI;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// C) Root-mean-square method voltage
|
||||
//-----------------------------------------------------------------------------
|
||||
sqV= filteredV * filteredV; //1) square voltage values
|
||||
sumV += sqV; //2) sum
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// D) Root-mean-square method current
|
||||
//-----------------------------------------------------------------------------
|
||||
sqI = filteredI * filteredI; //1) square current values
|
||||
sumI += sqI; //2) sum
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// E) Phase calibration
|
||||
//-----------------------------------------------------------------------------
|
||||
phaseShiftedV = lastFilteredV + PHASECAL * (filteredV - lastFilteredV);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// F) Instantaneous power calc
|
||||
//-----------------------------------------------------------------------------
|
||||
instP = phaseShiftedV * filteredI; //Instantaneous Power
|
||||
sumP +=instP; //Sum
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// G) Find the number of times the voltage has crossed the initial voltage
|
||||
// - every 2 crosses we will have sampled 1 wavelength
|
||||
// - so this method allows us to sample an integer number of half wavelengths which increases accuracy
|
||||
//-----------------------------------------------------------------------------
|
||||
lastVCross = checkVCross;
|
||||
if (sampleV > startV) checkVCross = true;
|
||||
else checkVCross = false;
|
||||
if (numberOfSamples==1) lastVCross = checkVCross;
|
||||
|
||||
if (lastVCross != checkVCross) crossCount++;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------------------
|
||||
// 3) Post loop calculations
|
||||
//-------------------------------------------------------------------------------------------------------------------------
|
||||
//Calculation of the root of the mean of the voltage and current squared (rms)
|
||||
//Calibration coefficients applied.
|
||||
|
||||
double V_RATIO = VCAL *((SupplyVoltage/1000.0) / (ADC_COUNTS));
|
||||
Vrms = V_RATIO * sqrt(sumV / numberOfSamples);
|
||||
|
||||
double I_RATIO = ICAL *((SupplyVoltage/1000.0) / (ADC_COUNTS));
|
||||
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;
|
||||
//--------------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
double TEnergyMonitor::calcIrms(unsigned int timeout)
|
||||
{
|
||||
|
||||
#if defined emonTxV3
|
||||
int SupplyVoltage=3300;
|
||||
#else
|
||||
int SupplyVoltage = readVcc();
|
||||
#endif
|
||||
|
||||
//Reset accumulators
|
||||
sumI = 0;
|
||||
unsigned long NumberOfSamples=0;
|
||||
unsigned long start=millis();
|
||||
|
||||
while ((millis()-start)<timeout*1000)
|
||||
{
|
||||
sampleI = adcI->read_u16();
|
||||
|
||||
// Digital low pass filter extracts the 2.5 V or 1.65 V dc offset,
|
||||
// then subtract this - signal is now centered on 0 counts.
|
||||
offsetI = (offsetI + (sampleI-offsetI)/1024);
|
||||
filteredI = sampleI - offsetI;
|
||||
|
||||
// Root-mean-square method current
|
||||
// 1) square current values
|
||||
sqI = filteredI * filteredI;
|
||||
// 2) sum
|
||||
sumI += sqI;
|
||||
NumberOfSamples++;
|
||||
}
|
||||
|
||||
double I_RATIO = ICAL *((SupplyVoltage/1000.0) / (ADC_COUNTS));
|
||||
Irms = I_RATIO * sqrt(sumI / NumberOfSamples);
|
||||
return Irms;
|
||||
}
|
||||
|
||||
long TEnergyMonitor::readVcc(){
|
||||
return 3340;
|
||||
}
|
||||
|
||||
|
||||
|
||||
78
TEnergyMonitor/TEnergyMonitor.h
Normal file
78
TEnergyMonitor/TEnergyMonitor.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* TEnergyMonitor.h
|
||||
*
|
||||
* Created on: 07 apr 2018
|
||||
* Author: Emanuele
|
||||
*/
|
||||
|
||||
#ifndef TENERGYMONITOR_H_
|
||||
#define TENERGYMONITOR_H_
|
||||
|
||||
#define ADC_BITS 16
|
||||
#define ADC_COUNTS (1<<ADC_BITS)
|
||||
#define VSUPPLY 3300
|
||||
|
||||
#include "mbed.h"
|
||||
#include "millis.h"
|
||||
|
||||
class TEnergyMonitor {
|
||||
|
||||
public:
|
||||
TEnergyMonitor(Serial* _pc);
|
||||
|
||||
void voltage(PinName _inPinV, double _VCAL, double _PHASECAL);
|
||||
void current(PinName _inPinI, double _ICAL);
|
||||
|
||||
void voltageTX(double _VCAL, double _PHASECAL);
|
||||
void currentTX(unsigned int _channel, double _ICAL);
|
||||
|
||||
void calcVI(unsigned int crossings, unsigned int timeout);
|
||||
double calcIrms(unsigned int NUMBER_OF_SAMPLES);
|
||||
void serialprint();
|
||||
|
||||
long readVcc();
|
||||
//Useful value variables
|
||||
double realPower,
|
||||
apparentPower,
|
||||
powerFactor,
|
||||
Vrms,
|
||||
Irms;
|
||||
|
||||
private:
|
||||
|
||||
Serial* pc;
|
||||
|
||||
//Set Voltage and current input pins
|
||||
PinName inPinV;
|
||||
PinName inPinI;
|
||||
AnalogIn *adcV;
|
||||
AnalogIn *adcI;
|
||||
//Calibration coefficients
|
||||
//These need to be set in order to obtain accurate results
|
||||
double VCAL;
|
||||
double ICAL;
|
||||
double PHASECAL;
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
// Variable declaration for emon_calc procedure
|
||||
//--------------------------------------------------------------------------------------
|
||||
unsigned int sampleV; //sample_ holds the raw analog read value
|
||||
unsigned int sampleI;
|
||||
|
||||
double lastFilteredV,filteredV; //Filtered_ is the raw analog value minus the DC offset
|
||||
double filteredI;
|
||||
double offsetV; //Low-pass filter output
|
||||
double offsetI; //Low-pass filter output
|
||||
|
||||
double phaseShiftedV; //Holds the calibrated phase shifted voltage.
|
||||
|
||||
double sqV,sumV,sqI,sumI,instP,sumP; //sq = squared, sum = Sum, inst = instantaneous
|
||||
|
||||
int startV; //Instantaneous voltage at start of sample window.
|
||||
|
||||
bool lastVCross, checkVCross; //Used to measure number of times threshold is crossed.
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif /* TENERGYMONITOR_H_ */
|
||||
Reference in New Issue
Block a user