Calibrate and get energy readings from ADE7758 IC from Analog Devices

Fork of ADE7758 by Emma

Currently this library can be used to calibrate and get VRMS, IRMS, active, and apparent energy. I havent worked on reactive energy measurement.

Revision:
4:5547bb32eb32
Parent:
3:4fad91cf047a
diff -r 4fad91cf047a -r 5547bb32eb32 ade7758.cpp
--- a/ade7758.cpp	Mon Apr 13 02:40:41 2015 +0000
+++ b/ade7758.cpp	Mon Apr 13 06:22:08 2015 +0000
@@ -39,17 +39,19 @@
     CVRMSCalib = CVRMSBuffer/numSamples;
     AIRMSCalib = AIRMSBuffer/numSamples;
     BIRMSCalib = BIRMSBuffer/numSamples;
-    CIRMSCalib = CIRMSBuffer/numSamples;    
-    
+    CIRMSCalib = CIRMSBuffer/numSamples;
+}
+
+void ADE7758::writeRMSOffset(uint16_t AIRMSOSValue, uint16_t BIRMSOSValue, uint16_t CIRMSOSValue, uint16_t AVRMSOSValue, uint16_t BVRMSOSValue, uint16_t CVRMSOSValue) {
     // Collect for ITEST & VNOM, IMIN & VMIN
     // Calculate these values in an Excel sheet according to page
     // Write the results to the xIRMSOS and xVRMSOS registers
-//    write16bits(AIRMSOS, 0xF5B); // Current channel A
-//    write16bits(BIRMSOS, 0xF52); // Current channel B
-//    write16bits(CIRMSOS, 0xF6C); // Current channel C
-    write16bits(AVRMSOS, 0xF5B); // Voltage channel A
-    write16bits(BVRMSOS, 0xF52); // Voltage channel B
-    write16bits(CVRMSOS, 0xF6C); // Voltage channel C
+    write16bits(AIRMSOS, AIRMSOSValue); // Current channel A
+    write16bits(BIRMSOS, BIRMSOSValue); // Current channel B
+    write16bits(CIRMSOS, CIRMSOSValue); // Current channel C
+    write16bits(AVRMSOS, AVRMSOSValue); // Voltage channel A
+    write16bits(BVRMSOS, BVRMSOSValue); // Voltage channel B
+    write16bits(CVRMSOS, CVRMSOSValue); // Voltage channel C
 }
 
 void ADE7758::calibrateGain(char phase) { // see datasheet ADE 7758 page 49 of 72
@@ -104,7 +106,9 @@
     BVAhLSB = tempEnergy/(3600*BVAHRTemp);
     CVAhLSB = tempEnergy/(3600*CVAHRTemp);
 
-    // 10. Wait LENERGY interrupt and read 6 energy registers
+    // 10. Clear and wait LENERGY interrupt and read 6 energy registers
+    wait_ms(10);
+    read24bits(RSTATUS);
     while ( _ADEINT != 0 ) { } // wait until INT go low
     int AWHREXPECTED = getWattHR(PHASE_A);
     int AVAHREXPECTED = getVAHR(PHASE_A);
@@ -114,20 +118,20 @@
     int CVAHREXPECTED = getVAHR(PHASE_C);
 
     // 11. Calculate xWG and xVAG values
-    int AWGValue = ((AWHREXPECTED/AWATTHRTemp) - 1)*4096;
-    int BWGValue = ((BWHREXPECTED/BWATTHRTemp) - 1)*4096;
-    int CWGValue = ((CWHREXPECTED/CWATTHRTemp) - 1)*4096;
-    int AVAGValue = ((AVAHREXPECTED/AVAHRTemp) - 1)*4096;
-    int BVAGValue = ((BVAHREXPECTED/BVAHRTemp) - 1)*4096;
-    int CVAGValue = ((CVAHREXPECTED/CVAHRTemp) - 1)*4096;
+    AWGCalib = ((float)(AWHREXPECTED/AWATTHRTemp) - 1)*4096;
+    BWGCalib = ((float)(BWHREXPECTED/BWATTHRTemp) - 1)*4096;
+    CWGCalib = ((float)(CWHREXPECTED/CWATTHRTemp) - 1)*4096;
+    AVAGCalib = ((float)(AVAHREXPECTED/AVAHRTemp) - 1)*4096;
+    BVAGCalib = ((float)(BVAHREXPECTED/BVAHRTemp) - 1)*4096;
+    CVAGCalib = ((float)(CVAHREXPECTED/CVAHRTemp) - 1)*4096;
 
     // 10. Write the values to xWG and xVAG
-    write16bits(AWG, AWGValue);
-    write16bits(BWG, BWGValue);
-    write16bits(CWG, CWGValue);
-    write16bits(AVAG, AVAGValue);
-    write16bits(BVAG, BVAGValue);
-    write16bits(CVAG, CVAGValue);
+    write16bits(AWG, AWGCalib);
+    write16bits(BWG, BWGCalib);
+    write16bits(CWG, CWGCalib);
+    write16bits(AVAG, AVAGCalib);
+    write16bits(BVAG, BVAGCalib);
+    write16bits(CVAG, CVAGCalib);
 }
 
 float ADE7758::getAccumulationTime(char phase) {
@@ -204,13 +208,13 @@
     AvgIRMS = IRMSBuffer/NUMSAMPLES;
 
     if ( phase == PHASE_A ) {
-        return AvgIRMS * 0.00000967;
+        return AvgIRMS * 0.0000125;
     }
     else if ( phase == PHASE_B ) {
-        return AvgIRMS * 0.00000955;
+        return AvgIRMS * 0.0000123;
     }    
     else if ( phase == PHASE_C ) {
-        return AvgIRMS * 0.00000958;
+        return AvgIRMS * 0.0000124;
     }
     else { return 0; }
 }
@@ -235,7 +239,36 @@
     else { return 0; }
 }
 
-void ADE7758::calculateEnergy(char phase)
+void ADE7758::getEnergy(char phase, uint8_t samplingPeriod, float *AWattHr, float *BWattHr, float *CWattHr, float *AVAHr, float *BVAHr, float *CVAHr) {    
+    float period = 0;
+    long AWattHrSum = 0;
+    long BWattHrSum = 0;    
+    long CWattHrSum = 0;
+    long AVAHrSum = 0;
+    long BVAHrSum = 0;    
+    long CVAHrSum = 0;
+        
+    uint16_t AWattHrValue, BWattHrValue, CWattHrValue, AVAHrValue, BVAHrValue, CVAHrValue;
+    while (period < samplingPeriod*60.0) {
+        period += ADE.getAccumulationTime(PHASE_A);
+        ADE7758::getAccumulatedEnergy(phase, &AWattHrValue, &BWattHrValue, &CWattHrValue, &AVAHrValue, &BVAHrValue, &CVAHrValue);
+        AWattHrSum += AWattHrValue;
+        BWattHrSum += BWattHrValue;
+        CWattHrSum += CWattHrValue;
+        AVAHrSum += AVAHrValue;
+        BVAHrSum += BVAHrValue; 
+        CVAHrSum += CVAHrValue;
+    }
+    *AWattHr = AWattHrSum * AWhLSB;
+    *BWattHr = BWattHrSum * BWhLSB;
+    *CWattHr = CWattHrSum * CWhLSB;
+    
+    *AVAHr = AVAHrSum * AVAhLSB;
+    *BVAHr = BVAHrSum * BVAhLSB;
+    *CVAHr = CVAHrSum * CVAhLSB;
+}
+
+void ADE7758::getAccumulatedEnergy(char phase, uint16_t *AWattHr, uint16_t *BWattHr, uint16_t *CWattHr, uint16_t *AVAHr, uint16_t *BVAHr, uint16_t *CVAHr)
 {
     // 1. Set phase used for line zero cross detection
     lineFreq(phase);
@@ -257,12 +290,12 @@
     
     // 6. Wait LENERGY interrupt and read 6 energy registers
     while ( _ADEINT != 0 ) { } // wait until INT go low
-    int AWATTHRValue = getWattHR(PHASE_A);
-    int AVAHRValue = getVAHR(PHASE_A);
-    int BWATTHRValue = getWattHR(PHASE_B);
-    int BVAHRValue = getVAHR(PHASE_B);
-    int CWATTHRValue = getWattHR(PHASE_C);
-    int CVAHRValue = getVAHR(PHASE_C);
+    *AWattHr = getWattHR(PHASE_A);
+    *AVAHr = getVAHR(PHASE_A);
+    *BWattHr = getWattHR(PHASE_B);
+    *BVAHr = getVAHR(PHASE_B);
+    *CWattHr = getWattHR(PHASE_C);
+    *CVAHr = getVAHR(PHASE_C);
 }
 
 long ADE7758::waveform(char phase,char source)