Calibrate and get energy readings from ADE7758 IC from Analog Devices
Fork of ADE7758 by
Currently this library can be used to calibrate and get VRMS, IRMS, active, and apparent energy. I havent worked on reactive energy measurement.
ade7758.cpp@4:5547bb32eb32, 2015-04-13 (annotated)
- Committer:
- bonchenko
- Date:
- Mon Apr 13 06:22:08 2015 +0000
- Revision:
- 4:5547bb32eb32
- Parent:
- 3:4fad91cf047a
xIRMS, xVRMS, xWh, xVAh works. Possibly need several calibration
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
bonchenko | 0:cf3dc3c5156b | 1 | #include "mbed.h" |
bonchenko | 0:cf3dc3c5156b | 2 | #include "ade7758.h" |
bonchenko | 0:cf3dc3c5156b | 3 | #include "SWSPI.h" |
bonchenko | 0:cf3dc3c5156b | 4 | |
bonchenko | 0:cf3dc3c5156b | 5 | // public |
bonchenko | 1:f5e8c8591449 | 6 | ADE7758::ADE7758(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName interrupt): |
bonchenko | 1:f5e8c8591449 | 7 | _ADE7758SPI(mosi, miso, sclk), _ADESS(cs), _ADEINT(interrupt) |
bonchenko | 0:cf3dc3c5156b | 8 | { |
bonchenko | 0:cf3dc3c5156b | 9 | _ADESS = 1; |
bonchenko | 0:cf3dc3c5156b | 10 | } |
bonchenko | 0:cf3dc3c5156b | 11 | |
bonchenko | 0:cf3dc3c5156b | 12 | void ADE7758::begin() |
bonchenko | 0:cf3dc3c5156b | 13 | { |
bonchenko | 0:cf3dc3c5156b | 14 | enableChip(); |
bonchenko | 0:cf3dc3c5156b | 15 | //normal mode |
bonchenko | 1:f5e8c8591449 | 16 | _ADE7758SPI.format(8, 1); // pha 0, pol 1 |
bonchenko | 1:f5e8c8591449 | 17 | _ADE7758SPI.frequency(1000000); |
bonchenko | 1:f5e8c8591449 | 18 | write8bits(OPMODE, 0x04); |
bonchenko | 1:f5e8c8591449 | 19 | } |
bonchenko | 1:f5e8c8591449 | 20 | |
bonchenko | 2:ea36884772ae | 21 | void ADE7758::calibrateVI(uint8_t numSamples) |
bonchenko | 1:f5e8c8591449 | 22 | { |
bonchenko | 1:f5e8c8591449 | 23 | write8bits(LCYCMODE, 0x38); |
bonchenko | 1:f5e8c8591449 | 24 | write24bits(MASK, 0xE00); |
bonchenko | 1:f5e8c8591449 | 25 | long AVRMSBuffer = 0, BVRMSBuffer = 0, CVRMSBuffer = 0; |
bonchenko | 1:f5e8c8591449 | 26 | long AIRMSBuffer = 0, BIRMSBuffer = 0, CIRMSBuffer = 0; |
bonchenko | 1:f5e8c8591449 | 27 | for (uint8_t i=0; i<numSamples; i++) { |
bonchenko | 1:f5e8c8591449 | 28 | read24bits(RSTATUS); |
bonchenko | 1:f5e8c8591449 | 29 | while ( _ADEINT != 0 ) { } // wait until INT go low |
bonchenko | 1:f5e8c8591449 | 30 | AVRMSBuffer += VRMS(PHASE_A); |
bonchenko | 1:f5e8c8591449 | 31 | BVRMSBuffer += VRMS(PHASE_B); |
bonchenko | 1:f5e8c8591449 | 32 | CVRMSBuffer += VRMS(PHASE_C); |
bonchenko | 1:f5e8c8591449 | 33 | AIRMSBuffer += IRMS(PHASE_A); |
bonchenko | 1:f5e8c8591449 | 34 | BIRMSBuffer += IRMS(PHASE_B); |
bonchenko | 1:f5e8c8591449 | 35 | CIRMSBuffer += IRMS(PHASE_C); |
bonchenko | 1:f5e8c8591449 | 36 | } |
bonchenko | 1:f5e8c8591449 | 37 | AVRMSCalib = AVRMSBuffer/numSamples; |
bonchenko | 1:f5e8c8591449 | 38 | BVRMSCalib = BVRMSBuffer/numSamples; |
bonchenko | 1:f5e8c8591449 | 39 | CVRMSCalib = CVRMSBuffer/numSamples; |
bonchenko | 1:f5e8c8591449 | 40 | AIRMSCalib = AIRMSBuffer/numSamples; |
bonchenko | 1:f5e8c8591449 | 41 | BIRMSCalib = BIRMSBuffer/numSamples; |
bonchenko | 4:5547bb32eb32 | 42 | CIRMSCalib = CIRMSBuffer/numSamples; |
bonchenko | 4:5547bb32eb32 | 43 | } |
bonchenko | 4:5547bb32eb32 | 44 | |
bonchenko | 4:5547bb32eb32 | 45 | void ADE7758::writeRMSOffset(uint16_t AIRMSOSValue, uint16_t BIRMSOSValue, uint16_t CIRMSOSValue, uint16_t AVRMSOSValue, uint16_t BVRMSOSValue, uint16_t CVRMSOSValue) { |
bonchenko | 2:ea36884772ae | 46 | // Collect for ITEST & VNOM, IMIN & VMIN |
bonchenko | 2:ea36884772ae | 47 | // Calculate these values in an Excel sheet according to page |
bonchenko | 2:ea36884772ae | 48 | // Write the results to the xIRMSOS and xVRMSOS registers |
bonchenko | 4:5547bb32eb32 | 49 | write16bits(AIRMSOS, AIRMSOSValue); // Current channel A |
bonchenko | 4:5547bb32eb32 | 50 | write16bits(BIRMSOS, BIRMSOSValue); // Current channel B |
bonchenko | 4:5547bb32eb32 | 51 | write16bits(CIRMSOS, CIRMSOSValue); // Current channel C |
bonchenko | 4:5547bb32eb32 | 52 | write16bits(AVRMSOS, AVRMSOSValue); // Voltage channel A |
bonchenko | 4:5547bb32eb32 | 53 | write16bits(BVRMSOS, BVRMSOSValue); // Voltage channel B |
bonchenko | 4:5547bb32eb32 | 54 | write16bits(CVRMSOS, CVRMSOSValue); // Voltage channel C |
bonchenko | 2:ea36884772ae | 55 | } |
bonchenko | 2:ea36884772ae | 56 | |
bonchenko | 2:ea36884772ae | 57 | void ADE7758::calibrateGain(char phase) { // see datasheet ADE 7758 page 49 of 72 |
bonchenko | 2:ea36884772ae | 58 | // 1. Clear xWG, xVARG, xVAG |
bonchenko | 2:ea36884772ae | 59 | write16bits(AWG, 0x0000); |
bonchenko | 2:ea36884772ae | 60 | write16bits(BWG, 0x0000); |
bonchenko | 3:4fad91cf047a | 61 | write16bits(CWG, 0x0000); |
bonchenko | 2:ea36884772ae | 62 | write16bits(AVARG, 0x0000); |
bonchenko | 2:ea36884772ae | 63 | write16bits(BVARG, 0x0000); |
bonchenko | 2:ea36884772ae | 64 | write16bits(CVARG, 0x0000); |
bonchenko | 2:ea36884772ae | 65 | write16bits(AVAG, 0x0000); |
bonchenko | 2:ea36884772ae | 66 | write16bits(BVAG, 0x0000); |
bonchenko | 2:ea36884772ae | 67 | write16bits(CVAG, 0x0000); |
bonchenko | 2:ea36884772ae | 68 | |
bonchenko | 2:ea36884772ae | 69 | // 2. Select phase for line period measurement |
bonchenko | 2:ea36884772ae | 70 | lineFreq(phase); |
bonchenko | 2:ea36884772ae | 71 | |
bonchenko | 2:ea36884772ae | 72 | // 3. Configure LCYCMODE register with 0xBF |
bonchenko | 2:ea36884772ae | 73 | write8bits(LCYCMODE, 0xBF); |
bonchenko | 2:ea36884772ae | 74 | |
bonchenko | 2:ea36884772ae | 75 | // 4. Set number of half line cycles |
bonchenko | 2:ea36884772ae | 76 | write16bits(LINECYC, 0x800); |
bonchenko | 2:ea36884772ae | 77 | |
bonchenko | 2:ea36884772ae | 78 | // 5. Set LENERGY bit in MASK register for interrupt |
bonchenko | 2:ea36884772ae | 79 | uint16_t mask; |
bonchenko | 2:ea36884772ae | 80 | mask = read16bits(MASK); |
bonchenko | 2:ea36884772ae | 81 | write24bits(MASK, mask | (1<<LENERGY)); |
bonchenko | 2:ea36884772ae | 82 | wait_ms(10); |
bonchenko | 2:ea36884772ae | 83 | |
bonchenko | 2:ea36884772ae | 84 | // 6. Environment setting |
bonchenko | 2:ea36884772ae | 85 | // set environment - ITEST and VNOM |
bonchenko | 2:ea36884772ae | 86 | |
bonchenko | 2:ea36884772ae | 87 | // 7. Reset RSTATUS |
bonchenko | 2:ea36884772ae | 88 | read24bits(RSTATUS); |
bonchenko | 2:ea36884772ae | 89 | |
bonchenko | 2:ea36884772ae | 90 | // 8. Wait LENERGY interrupt and read 6 energy registers |
bonchenko | 2:ea36884772ae | 91 | while ( _ADEINT != 0 ) { } // wait until INT go low |
bonchenko | 2:ea36884772ae | 92 | int AWATTHRTemp = getWattHR(PHASE_A); |
bonchenko | 2:ea36884772ae | 93 | int AVAHRTemp = getVAHR(PHASE_A); |
bonchenko | 2:ea36884772ae | 94 | int BWATTHRTemp = getWattHR(PHASE_B); |
bonchenko | 2:ea36884772ae | 95 | int BVAHRTemp = getVAHR(PHASE_B); |
bonchenko | 2:ea36884772ae | 96 | int CWATTHRTemp = getWattHR(PHASE_C); |
bonchenko | 2:ea36884772ae | 97 | int CVAHRTemp = getVAHR(PHASE_C); |
bonchenko | 2:ea36884772ae | 98 | |
bonchenko | 3:4fad91cf047a | 99 | // 9. Calculate Wh/LSB and VAh/LSB |
bonchenko | 3:4fad91cf047a | 100 | float accumTime = getAccumulationTime(PHASE_A); |
bonchenko | 3:4fad91cf047a | 101 | float tempEnergy = ITEST*VNOM*accumTime; |
bonchenko | 3:4fad91cf047a | 102 | AWhLSB = tempEnergy/(3600*AWATTHRTemp); |
bonchenko | 3:4fad91cf047a | 103 | BWhLSB = tempEnergy/(3600*BWATTHRTemp); |
bonchenko | 3:4fad91cf047a | 104 | CWhLSB = tempEnergy/(3600*CWATTHRTemp); |
bonchenko | 3:4fad91cf047a | 105 | AVAhLSB = tempEnergy/(3600*AVAHRTemp); |
bonchenko | 3:4fad91cf047a | 106 | BVAhLSB = tempEnergy/(3600*BVAHRTemp); |
bonchenko | 3:4fad91cf047a | 107 | CVAhLSB = tempEnergy/(3600*CVAHRTemp); |
bonchenko | 2:ea36884772ae | 108 | |
bonchenko | 4:5547bb32eb32 | 109 | // 10. Clear and wait LENERGY interrupt and read 6 energy registers |
bonchenko | 4:5547bb32eb32 | 110 | wait_ms(10); |
bonchenko | 4:5547bb32eb32 | 111 | read24bits(RSTATUS); |
bonchenko | 3:4fad91cf047a | 112 | while ( _ADEINT != 0 ) { } // wait until INT go low |
bonchenko | 3:4fad91cf047a | 113 | int AWHREXPECTED = getWattHR(PHASE_A); |
bonchenko | 3:4fad91cf047a | 114 | int AVAHREXPECTED = getVAHR(PHASE_A); |
bonchenko | 3:4fad91cf047a | 115 | int BWHREXPECTED = getWattHR(PHASE_B); |
bonchenko | 3:4fad91cf047a | 116 | int BVAHREXPECTED = getVAHR(PHASE_B); |
bonchenko | 3:4fad91cf047a | 117 | int CWHREXPECTED = getWattHR(PHASE_C); |
bonchenko | 3:4fad91cf047a | 118 | int CVAHREXPECTED = getVAHR(PHASE_C); |
bonchenko | 2:ea36884772ae | 119 | |
bonchenko | 3:4fad91cf047a | 120 | // 11. Calculate xWG and xVAG values |
bonchenko | 4:5547bb32eb32 | 121 | AWGCalib = ((float)(AWHREXPECTED/AWATTHRTemp) - 1)*4096; |
bonchenko | 4:5547bb32eb32 | 122 | BWGCalib = ((float)(BWHREXPECTED/BWATTHRTemp) - 1)*4096; |
bonchenko | 4:5547bb32eb32 | 123 | CWGCalib = ((float)(CWHREXPECTED/CWATTHRTemp) - 1)*4096; |
bonchenko | 4:5547bb32eb32 | 124 | AVAGCalib = ((float)(AVAHREXPECTED/AVAHRTemp) - 1)*4096; |
bonchenko | 4:5547bb32eb32 | 125 | BVAGCalib = ((float)(BVAHREXPECTED/BVAHRTemp) - 1)*4096; |
bonchenko | 4:5547bb32eb32 | 126 | CVAGCalib = ((float)(CVAHREXPECTED/CVAHRTemp) - 1)*4096; |
bonchenko | 2:ea36884772ae | 127 | |
bonchenko | 2:ea36884772ae | 128 | // 10. Write the values to xWG and xVAG |
bonchenko | 4:5547bb32eb32 | 129 | write16bits(AWG, AWGCalib); |
bonchenko | 4:5547bb32eb32 | 130 | write16bits(BWG, BWGCalib); |
bonchenko | 4:5547bb32eb32 | 131 | write16bits(CWG, CWGCalib); |
bonchenko | 4:5547bb32eb32 | 132 | write16bits(AVAG, AVAGCalib); |
bonchenko | 4:5547bb32eb32 | 133 | write16bits(BVAG, BVAGCalib); |
bonchenko | 4:5547bb32eb32 | 134 | write16bits(CVAG, CVAGCalib); |
bonchenko | 2:ea36884772ae | 135 | } |
bonchenko | 2:ea36884772ae | 136 | |
bonchenko | 3:4fad91cf047a | 137 | float ADE7758::getAccumulationTime(char phase) { |
bonchenko | 2:ea36884772ae | 138 | uint16_t frequency = lineFreq(phase); |
bonchenko | 2:ea36884772ae | 139 | uint16_t LineCYC = read16bits(LINECYC); |
bonchenko | 2:ea36884772ae | 140 | write8bits(LCYCMODE, 0xBF); |
bonchenko | 2:ea36884772ae | 141 | float LineFrequency = 1/(frequency*0.0000096); |
bonchenko | 2:ea36884772ae | 142 | return LineCYC/(2*LineFrequency*3); |
bonchenko | 0:cf3dc3c5156b | 143 | } |
bonchenko | 0:cf3dc3c5156b | 144 | |
bonchenko | 0:cf3dc3c5156b | 145 | int ADE7758::getWattHR(char phase) |
bonchenko | 0:cf3dc3c5156b | 146 | { |
bonchenko | 0:cf3dc3c5156b | 147 | return read16bits(AWATTHR+phase); |
bonchenko | 0:cf3dc3c5156b | 148 | } |
bonchenko | 0:cf3dc3c5156b | 149 | |
bonchenko | 0:cf3dc3c5156b | 150 | int ADE7758::getVARHR(char phase) |
bonchenko | 0:cf3dc3c5156b | 151 | { |
bonchenko | 0:cf3dc3c5156b | 152 | return read16bits(AVARHR+phase); |
bonchenko | 0:cf3dc3c5156b | 153 | } |
bonchenko | 0:cf3dc3c5156b | 154 | |
bonchenko | 0:cf3dc3c5156b | 155 | int ADE7758::getVAHR(char phase) |
bonchenko | 0:cf3dc3c5156b | 156 | { |
bonchenko | 0:cf3dc3c5156b | 157 | return read16bits(AVAHR+phase); |
bonchenko | 0:cf3dc3c5156b | 158 | } |
bonchenko | 0:cf3dc3c5156b | 159 | |
bonchenko | 0:cf3dc3c5156b | 160 | int ADE7758::WattHR(char phase) |
bonchenko | 0:cf3dc3c5156b | 161 | { |
bonchenko | 2:ea36884772ae | 162 | return getWattHR(phase); |
bonchenko | 0:cf3dc3c5156b | 163 | } |
bonchenko | 0:cf3dc3c5156b | 164 | |
bonchenko | 0:cf3dc3c5156b | 165 | int ADE7758::VARHR(char phase) |
bonchenko | 0:cf3dc3c5156b | 166 | { |
bonchenko | 2:ea36884772ae | 167 | return getVARHR(phase); |
bonchenko | 0:cf3dc3c5156b | 168 | } |
bonchenko | 0:cf3dc3c5156b | 169 | |
bonchenko | 0:cf3dc3c5156b | 170 | int ADE7758::VAHR(char phase) |
bonchenko | 0:cf3dc3c5156b | 171 | { |
bonchenko | 2:ea36884772ae | 172 | return getVAHR(phase); |
bonchenko | 0:cf3dc3c5156b | 173 | } |
bonchenko | 0:cf3dc3c5156b | 174 | |
bonchenko | 0:cf3dc3c5156b | 175 | long ADE7758::VRMS(char phase) |
bonchenko | 0:cf3dc3c5156b | 176 | { |
bonchenko | 2:ea36884772ae | 177 | char i=0; |
bonchenko | 2:ea36884772ae | 178 | long volts=0; |
bonchenko | 2:ea36884772ae | 179 | getVRMS(phase);//Ignore first reading |
bonchenko | 2:ea36884772ae | 180 | for(i=0;i<10;++i){ |
bonchenko | 2:ea36884772ae | 181 | volts+=getVRMS(phase); |
bonchenko | 2:ea36884772ae | 182 | wait_us(50); |
bonchenko | 2:ea36884772ae | 183 | } |
bonchenko | 2:ea36884772ae | 184 | //average |
bonchenko | 2:ea36884772ae | 185 | return volts/10; |
bonchenko | 0:cf3dc3c5156b | 186 | } |
bonchenko | 0:cf3dc3c5156b | 187 | |
bonchenko | 0:cf3dc3c5156b | 188 | long ADE7758::IRMS(char phase) |
bonchenko | 0:cf3dc3c5156b | 189 | { |
bonchenko | 0:cf3dc3c5156b | 190 | char i=0; |
bonchenko | 0:cf3dc3c5156b | 191 | long current=0; |
bonchenko | 0:cf3dc3c5156b | 192 | getIRMS(phase);//Ignore first reading |
bonchenko | 0:cf3dc3c5156b | 193 | for(i=0;i<10;++i){ |
bonchenko | 0:cf3dc3c5156b | 194 | current+=getIRMS(phase); |
bonchenko | 0:cf3dc3c5156b | 195 | wait_us(50); |
bonchenko | 0:cf3dc3c5156b | 196 | } |
bonchenko | 0:cf3dc3c5156b | 197 | //average |
bonchenko | 0:cf3dc3c5156b | 198 | return current/10; |
bonchenko | 0:cf3dc3c5156b | 199 | } |
bonchenko | 0:cf3dc3c5156b | 200 | |
bonchenko | 1:f5e8c8591449 | 201 | |
bonchenko | 2:ea36884772ae | 202 | float ADE7758::calculateIRMS(char phase) { |
bonchenko | 2:ea36884772ae | 203 | long IRMSBuffer = 0; |
bonchenko | 2:ea36884772ae | 204 | float AvgIRMS = 0; |
bonchenko | 2:ea36884772ae | 205 | for (char i=0; i<NUMSAMPLES; i++) { |
bonchenko | 2:ea36884772ae | 206 | IRMSBuffer += IRMS(phase); |
bonchenko | 2:ea36884772ae | 207 | } |
bonchenko | 2:ea36884772ae | 208 | AvgIRMS = IRMSBuffer/NUMSAMPLES; |
bonchenko | 2:ea36884772ae | 209 | |
bonchenko | 1:f5e8c8591449 | 210 | if ( phase == PHASE_A ) { |
bonchenko | 4:5547bb32eb32 | 211 | return AvgIRMS * 0.0000125; |
bonchenko | 1:f5e8c8591449 | 212 | } |
bonchenko | 1:f5e8c8591449 | 213 | else if ( phase == PHASE_B ) { |
bonchenko | 4:5547bb32eb32 | 214 | return AvgIRMS * 0.0000123; |
bonchenko | 1:f5e8c8591449 | 215 | } |
bonchenko | 1:f5e8c8591449 | 216 | else if ( phase == PHASE_C ) { |
bonchenko | 4:5547bb32eb32 | 217 | return AvgIRMS * 0.0000124; |
bonchenko | 1:f5e8c8591449 | 218 | } |
bonchenko | 3:4fad91cf047a | 219 | else { return 0; } |
bonchenko | 1:f5e8c8591449 | 220 | } |
bonchenko | 1:f5e8c8591449 | 221 | |
bonchenko | 2:ea36884772ae | 222 | float ADE7758::calculateVRMS(char phase) { |
bonchenko | 2:ea36884772ae | 223 | long VRMSBuffer = 0; |
bonchenko | 2:ea36884772ae | 224 | float AvgVRMS = 0; |
bonchenko | 2:ea36884772ae | 225 | for (char i=0; i<NUMSAMPLES; i++) { |
bonchenko | 2:ea36884772ae | 226 | VRMSBuffer += VRMS(phase); |
bonchenko | 2:ea36884772ae | 227 | } |
bonchenko | 2:ea36884772ae | 228 | AvgVRMS = VRMSBuffer/NUMSAMPLES; |
bonchenko | 2:ea36884772ae | 229 | |
bonchenko | 1:f5e8c8591449 | 230 | if ( phase == PHASE_A ) { |
bonchenko | 2:ea36884772ae | 231 | return AvgVRMS * 0.000158; |
bonchenko | 1:f5e8c8591449 | 232 | } |
bonchenko | 1:f5e8c8591449 | 233 | else if ( phase == PHASE_B ) { |
bonchenko | 2:ea36884772ae | 234 | return AvgVRMS * 0.000157; |
bonchenko | 1:f5e8c8591449 | 235 | } |
bonchenko | 1:f5e8c8591449 | 236 | else if ( phase == PHASE_C ) { |
bonchenko | 2:ea36884772ae | 237 | return AvgVRMS * 0.000156; |
bonchenko | 2:ea36884772ae | 238 | } |
bonchenko | 3:4fad91cf047a | 239 | else { return 0; } |
bonchenko | 1:f5e8c8591449 | 240 | } |
bonchenko | 1:f5e8c8591449 | 241 | |
bonchenko | 4:5547bb32eb32 | 242 | void ADE7758::getEnergy(char phase, uint8_t samplingPeriod, float *AWattHr, float *BWattHr, float *CWattHr, float *AVAHr, float *BVAHr, float *CVAHr) { |
bonchenko | 4:5547bb32eb32 | 243 | float period = 0; |
bonchenko | 4:5547bb32eb32 | 244 | long AWattHrSum = 0; |
bonchenko | 4:5547bb32eb32 | 245 | long BWattHrSum = 0; |
bonchenko | 4:5547bb32eb32 | 246 | long CWattHrSum = 0; |
bonchenko | 4:5547bb32eb32 | 247 | long AVAHrSum = 0; |
bonchenko | 4:5547bb32eb32 | 248 | long BVAHrSum = 0; |
bonchenko | 4:5547bb32eb32 | 249 | long CVAHrSum = 0; |
bonchenko | 4:5547bb32eb32 | 250 | |
bonchenko | 4:5547bb32eb32 | 251 | uint16_t AWattHrValue, BWattHrValue, CWattHrValue, AVAHrValue, BVAHrValue, CVAHrValue; |
bonchenko | 4:5547bb32eb32 | 252 | while (period < samplingPeriod*60.0) { |
bonchenko | 4:5547bb32eb32 | 253 | period += ADE.getAccumulationTime(PHASE_A); |
bonchenko | 4:5547bb32eb32 | 254 | ADE7758::getAccumulatedEnergy(phase, &AWattHrValue, &BWattHrValue, &CWattHrValue, &AVAHrValue, &BVAHrValue, &CVAHrValue); |
bonchenko | 4:5547bb32eb32 | 255 | AWattHrSum += AWattHrValue; |
bonchenko | 4:5547bb32eb32 | 256 | BWattHrSum += BWattHrValue; |
bonchenko | 4:5547bb32eb32 | 257 | CWattHrSum += CWattHrValue; |
bonchenko | 4:5547bb32eb32 | 258 | AVAHrSum += AVAHrValue; |
bonchenko | 4:5547bb32eb32 | 259 | BVAHrSum += BVAHrValue; |
bonchenko | 4:5547bb32eb32 | 260 | CVAHrSum += CVAHrValue; |
bonchenko | 4:5547bb32eb32 | 261 | } |
bonchenko | 4:5547bb32eb32 | 262 | *AWattHr = AWattHrSum * AWhLSB; |
bonchenko | 4:5547bb32eb32 | 263 | *BWattHr = BWattHrSum * BWhLSB; |
bonchenko | 4:5547bb32eb32 | 264 | *CWattHr = CWattHrSum * CWhLSB; |
bonchenko | 4:5547bb32eb32 | 265 | |
bonchenko | 4:5547bb32eb32 | 266 | *AVAHr = AVAHrSum * AVAhLSB; |
bonchenko | 4:5547bb32eb32 | 267 | *BVAHr = BVAHrSum * BVAhLSB; |
bonchenko | 4:5547bb32eb32 | 268 | *CVAHr = CVAHrSum * CVAhLSB; |
bonchenko | 4:5547bb32eb32 | 269 | } |
bonchenko | 4:5547bb32eb32 | 270 | |
bonchenko | 4:5547bb32eb32 | 271 | void ADE7758::getAccumulatedEnergy(char phase, uint16_t *AWattHr, uint16_t *BWattHr, uint16_t *CWattHr, uint16_t *AVAHr, uint16_t *BVAHr, uint16_t *CVAHr) |
bonchenko | 0:cf3dc3c5156b | 272 | { |
bonchenko | 2:ea36884772ae | 273 | // 1. Set phase used for line zero cross detection |
bonchenko | 2:ea36884772ae | 274 | lineFreq(phase); |
bonchenko | 2:ea36884772ae | 275 | |
bonchenko | 2:ea36884772ae | 276 | // 2. Configure LCYCMODE register with 0xBF |
bonchenko | 2:ea36884772ae | 277 | write8bits(LCYCMODE, 0xBF); |
bonchenko | 2:ea36884772ae | 278 | |
bonchenko | 2:ea36884772ae | 279 | // 3. Set number of half line cycles |
bonchenko | 2:ea36884772ae | 280 | write16bits(LINECYC, 0x800); |
bonchenko | 2:ea36884772ae | 281 | |
bonchenko | 2:ea36884772ae | 282 | // 4. Set LENERGY bit in MASK register for interrupt |
bonchenko | 2:ea36884772ae | 283 | uint16_t mask; |
bonchenko | 2:ea36884772ae | 284 | mask = read16bits(MASK); |
bonchenko | 2:ea36884772ae | 285 | write24bits(MASK, mask | (1<<LENERGY)); |
bonchenko | 2:ea36884772ae | 286 | wait_ms(10); |
bonchenko | 2:ea36884772ae | 287 | |
bonchenko | 2:ea36884772ae | 288 | // 5. Reset RSTATUS |
bonchenko | 2:ea36884772ae | 289 | read24bits(RSTATUS); |
bonchenko | 0:cf3dc3c5156b | 290 | |
bonchenko | 2:ea36884772ae | 291 | // 6. Wait LENERGY interrupt and read 6 energy registers |
bonchenko | 2:ea36884772ae | 292 | while ( _ADEINT != 0 ) { } // wait until INT go low |
bonchenko | 4:5547bb32eb32 | 293 | *AWattHr = getWattHR(PHASE_A); |
bonchenko | 4:5547bb32eb32 | 294 | *AVAHr = getVAHR(PHASE_A); |
bonchenko | 4:5547bb32eb32 | 295 | *BWattHr = getWattHR(PHASE_B); |
bonchenko | 4:5547bb32eb32 | 296 | *BVAHr = getVAHR(PHASE_B); |
bonchenko | 4:5547bb32eb32 | 297 | *CWattHr = getWattHR(PHASE_C); |
bonchenko | 4:5547bb32eb32 | 298 | *CVAHr = getVAHR(PHASE_C); |
bonchenko | 0:cf3dc3c5156b | 299 | } |
bonchenko | 0:cf3dc3c5156b | 300 | |
bonchenko | 0:cf3dc3c5156b | 301 | long ADE7758::waveform(char phase,char source) |
bonchenko | 0:cf3dc3c5156b | 302 | { |
bonchenko | 0:cf3dc3c5156b | 303 | return 1; |
bonchenko | 0:cf3dc3c5156b | 304 | } |
bonchenko | 0:cf3dc3c5156b | 305 | |
bonchenko | 0:cf3dc3c5156b | 306 | void ADE7758::powerOff() |
bonchenko | 0:cf3dc3c5156b | 307 | { |
bonchenko | 0:cf3dc3c5156b | 308 | |
bonchenko | 0:cf3dc3c5156b | 309 | } |
bonchenko | 0:cf3dc3c5156b | 310 | |
bonchenko | 0:cf3dc3c5156b | 311 | void ADE7758::powerON() |
bonchenko | 0:cf3dc3c5156b | 312 | { |
bonchenko | 0:cf3dc3c5156b | 313 | |
bonchenko | 0:cf3dc3c5156b | 314 | } |
bonchenko | 0:cf3dc3c5156b | 315 | |
bonchenko | 0:cf3dc3c5156b | 316 | void ADE7758::sleep() |
bonchenko | 0:cf3dc3c5156b | 317 | { |
bonchenko | 0:cf3dc3c5156b | 318 | |
bonchenko | 0:cf3dc3c5156b | 319 | } |
bonchenko | 0:cf3dc3c5156b | 320 | |
bonchenko | 0:cf3dc3c5156b | 321 | void ADE7758::wakeUp() |
bonchenko | 0:cf3dc3c5156b | 322 | { |
bonchenko | 0:cf3dc3c5156b | 323 | |
bonchenko | 0:cf3dc3c5156b | 324 | } |
bonchenko | 0:cf3dc3c5156b | 325 | |
bonchenko | 0:cf3dc3c5156b | 326 | long ADE7758::getInterruptStatus(void){ |
bonchenko | 0:cf3dc3c5156b | 327 | return read24bits(STATUS); |
bonchenko | 0:cf3dc3c5156b | 328 | } |
bonchenko | 0:cf3dc3c5156b | 329 | |
bonchenko | 0:cf3dc3c5156b | 330 | long ADE7758::getResetInterruptStatus(void){ |
bonchenko | 0:cf3dc3c5156b | 331 | return read24bits(RSTATUS); |
bonchenko | 0:cf3dc3c5156b | 332 | } |
bonchenko | 0:cf3dc3c5156b | 333 | |
bonchenko | 0:cf3dc3c5156b | 334 | int ADE7758::lineFreq(char phase){ |
bonchenko | 0:cf3dc3c5156b | 335 | uint8_t mmode; |
bonchenko | 0:cf3dc3c5156b | 336 | mmode = read8bits(MMODE); |
bonchenko | 2:ea36884772ae | 337 | write8bits(MMODE,( mmode&0xFC )| phase); |
bonchenko | 0:cf3dc3c5156b | 338 | wait_ms(10); |
bonchenko | 0:cf3dc3c5156b | 339 | return read16bits(FREQ); |
bonchenko | 0:cf3dc3c5156b | 340 | } |
bonchenko | 0:cf3dc3c5156b | 341 | // private |
bonchenko | 0:cf3dc3c5156b | 342 | |
bonchenko | 0:cf3dc3c5156b | 343 | void ADE7758::enableChip() |
bonchenko | 0:cf3dc3c5156b | 344 | { |
bonchenko | 0:cf3dc3c5156b | 345 | _ADESS = 0; |
bonchenko | 0:cf3dc3c5156b | 346 | } |
bonchenko | 0:cf3dc3c5156b | 347 | |
bonchenko | 0:cf3dc3c5156b | 348 | void ADE7758::disableChip() |
bonchenko | 0:cf3dc3c5156b | 349 | { |
bonchenko | 0:cf3dc3c5156b | 350 | _ADESS = 1; |
bonchenko | 0:cf3dc3c5156b | 351 | } |
bonchenko | 0:cf3dc3c5156b | 352 | |
bonchenko | 0:cf3dc3c5156b | 353 | void ADE7758::write8bits(char reg, unsigned char data) |
bonchenko | 0:cf3dc3c5156b | 354 | { |
bonchenko | 0:cf3dc3c5156b | 355 | enableChip(); |
bonchenko | 0:cf3dc3c5156b | 356 | |
bonchenko | 0:cf3dc3c5156b | 357 | wait_ms(10); |
bonchenko | 0:cf3dc3c5156b | 358 | _ADE7758SPI.write(REG_WRITE(reg)); |
bonchenko | 0:cf3dc3c5156b | 359 | wait_ms(2); |
bonchenko | 0:cf3dc3c5156b | 360 | |
bonchenko | 0:cf3dc3c5156b | 361 | _ADE7758SPI.write(data); |
bonchenko | 0:cf3dc3c5156b | 362 | |
bonchenko | 0:cf3dc3c5156b | 363 | wait_ms(1); |
bonchenko | 0:cf3dc3c5156b | 364 | |
bonchenko | 0:cf3dc3c5156b | 365 | disableChip(); |
bonchenko | 0:cf3dc3c5156b | 366 | } |
bonchenko | 0:cf3dc3c5156b | 367 | |
bonchenko | 0:cf3dc3c5156b | 368 | void ADE7758::write16bits(char reg, unsigned int data) |
bonchenko | 0:cf3dc3c5156b | 369 | { |
bonchenko | 0:cf3dc3c5156b | 370 | enableChip(); |
bonchenko | 0:cf3dc3c5156b | 371 | |
bonchenko | 0:cf3dc3c5156b | 372 | wait_ms(10); |
bonchenko | 0:cf3dc3c5156b | 373 | _ADE7758SPI.write(REG_WRITE(reg)); |
bonchenko | 0:cf3dc3c5156b | 374 | wait_ms(2); |
bonchenko | 0:cf3dc3c5156b | 375 | _ADE7758SPI.write((unsigned char)((data>>8)&0xFF)); |
bonchenko | 0:cf3dc3c5156b | 376 | wait_ms(2); |
bonchenko | 0:cf3dc3c5156b | 377 | _ADE7758SPI.write((unsigned char)(data&0xFF)); |
bonchenko | 0:cf3dc3c5156b | 378 | wait_ms(1); |
bonchenko | 0:cf3dc3c5156b | 379 | |
bonchenko | 0:cf3dc3c5156b | 380 | disableChip(); |
bonchenko | 0:cf3dc3c5156b | 381 | } |
bonchenko | 0:cf3dc3c5156b | 382 | |
bonchenko | 1:f5e8c8591449 | 383 | void ADE7758::write24bits(char reg, unsigned int data) |
bonchenko | 1:f5e8c8591449 | 384 | { |
bonchenko | 1:f5e8c8591449 | 385 | enableChip(); |
bonchenko | 1:f5e8c8591449 | 386 | |
bonchenko | 1:f5e8c8591449 | 387 | wait_ms(10); |
bonchenko | 1:f5e8c8591449 | 388 | _ADE7758SPI.write(REG_WRITE(reg)); |
bonchenko | 1:f5e8c8591449 | 389 | wait_ms(2); |
bonchenko | 1:f5e8c8591449 | 390 | _ADE7758SPI.write((unsigned char)((data>>16)&0xFF)); |
bonchenko | 1:f5e8c8591449 | 391 | wait_ms(2); |
bonchenko | 1:f5e8c8591449 | 392 | _ADE7758SPI.write((unsigned char)((data>>8)&0xFF)); |
bonchenko | 1:f5e8c8591449 | 393 | wait_ms(2); |
bonchenko | 1:f5e8c8591449 | 394 | _ADE7758SPI.write((unsigned char)(data&0xFF)); |
bonchenko | 1:f5e8c8591449 | 395 | wait_ms(1); |
bonchenko | 1:f5e8c8591449 | 396 | |
bonchenko | 1:f5e8c8591449 | 397 | disableChip(); |
bonchenko | 1:f5e8c8591449 | 398 | } |
bonchenko | 1:f5e8c8591449 | 399 | |
bonchenko | 0:cf3dc3c5156b | 400 | unsigned char ADE7758::read8bits(char reg) |
bonchenko | 0:cf3dc3c5156b | 401 | { |
bonchenko | 0:cf3dc3c5156b | 402 | enableChip(); |
bonchenko | 0:cf3dc3c5156b | 403 | |
bonchenko | 0:cf3dc3c5156b | 404 | unsigned char ret; |
bonchenko | 0:cf3dc3c5156b | 405 | wait_ms(10); |
bonchenko | 0:cf3dc3c5156b | 406 | _ADE7758SPI.write(REG_READ(reg)); |
bonchenko | 0:cf3dc3c5156b | 407 | wait_ms(2); |
bonchenko | 0:cf3dc3c5156b | 408 | ret=_ADE7758SPI.write(0x00); |
bonchenko | 0:cf3dc3c5156b | 409 | wait_ms(1); |
bonchenko | 0:cf3dc3c5156b | 410 | |
bonchenko | 0:cf3dc3c5156b | 411 | disableChip(); |
bonchenko | 0:cf3dc3c5156b | 412 | |
bonchenko | 0:cf3dc3c5156b | 413 | return ret; |
bonchenko | 0:cf3dc3c5156b | 414 | } |
bonchenko | 0:cf3dc3c5156b | 415 | |
bonchenko | 0:cf3dc3c5156b | 416 | unsigned int ADE7758::read16bits(char reg) |
bonchenko | 0:cf3dc3c5156b | 417 | { |
bonchenko | 0:cf3dc3c5156b | 418 | enableChip(); |
bonchenko | 0:cf3dc3c5156b | 419 | unsigned int ret=0; |
bonchenko | 0:cf3dc3c5156b | 420 | unsigned char ret0=0; |
bonchenko | 0:cf3dc3c5156b | 421 | wait_ms(10); |
bonchenko | 0:cf3dc3c5156b | 422 | _ADE7758SPI.write(REG_READ(reg)); |
bonchenko | 0:cf3dc3c5156b | 423 | wait_ms(2); |
bonchenko | 0:cf3dc3c5156b | 424 | ret=_ADE7758SPI.write(0x00); |
bonchenko | 0:cf3dc3c5156b | 425 | wait_ms(2); |
bonchenko | 0:cf3dc3c5156b | 426 | ret0=_ADE7758SPI.write(0x00); |
bonchenko | 0:cf3dc3c5156b | 427 | wait_ms(1); |
bonchenko | 0:cf3dc3c5156b | 428 | |
bonchenko | 0:cf3dc3c5156b | 429 | disableChip(); |
bonchenko | 0:cf3dc3c5156b | 430 | ret= (ret<<8)|ret0; |
bonchenko | 0:cf3dc3c5156b | 431 | return ret; |
bonchenko | 0:cf3dc3c5156b | 432 | } |
bonchenko | 0:cf3dc3c5156b | 433 | |
bonchenko | 0:cf3dc3c5156b | 434 | unsigned long ADE7758::read24bits(char reg) |
bonchenko | 0:cf3dc3c5156b | 435 | { |
bonchenko | 0:cf3dc3c5156b | 436 | enableChip(); |
bonchenko | 0:cf3dc3c5156b | 437 | unsigned long ret=0; |
bonchenko | 0:cf3dc3c5156b | 438 | unsigned int ret1=0; |
bonchenko | 0:cf3dc3c5156b | 439 | unsigned char ret0=0; |
bonchenko | 0:cf3dc3c5156b | 440 | wait_ms(10); |
bonchenko | 0:cf3dc3c5156b | 441 | _ADE7758SPI.write(REG_READ(reg)); |
bonchenko | 0:cf3dc3c5156b | 442 | wait_ms(2); |
bonchenko | 0:cf3dc3c5156b | 443 | ret=_ADE7758SPI.write(0x00); |
bonchenko | 0:cf3dc3c5156b | 444 | wait_ms(2); |
bonchenko | 0:cf3dc3c5156b | 445 | ret1=_ADE7758SPI.write(0x00); |
bonchenko | 0:cf3dc3c5156b | 446 | wait_ms(2); |
bonchenko | 0:cf3dc3c5156b | 447 | ret0=_ADE7758SPI.write(0x00); |
bonchenko | 0:cf3dc3c5156b | 448 | wait_ms(1); |
bonchenko | 0:cf3dc3c5156b | 449 | |
bonchenko | 0:cf3dc3c5156b | 450 | disableChip(); |
bonchenko | 1:f5e8c8591449 | 451 | ret= (ret<<16)|(ret1<<8)| ret0; |
bonchenko | 0:cf3dc3c5156b | 452 | return ret; |
bonchenko | 0:cf3dc3c5156b | 453 | } |
bonchenko | 0:cf3dc3c5156b | 454 | |
bonchenko | 0:cf3dc3c5156b | 455 | long ADE7758::getIRMS(char phase) |
bonchenko | 0:cf3dc3c5156b | 456 | { |
bonchenko | 0:cf3dc3c5156b | 457 | return read24bits(AIRMS+phase); |
bonchenko | 0:cf3dc3c5156b | 458 | } |
bonchenko | 0:cf3dc3c5156b | 459 | |
bonchenko | 0:cf3dc3c5156b | 460 | long ADE7758::getVRMS(char phase) |
bonchenko | 0:cf3dc3c5156b | 461 | { |
bonchenko | 0:cf3dc3c5156b | 462 | return read24bits(AVRMS+phase); |
bonchenko | 0:cf3dc3c5156b | 463 | } |
bonchenko | 0:cf3dc3c5156b | 464 | |
bonchenko | 0:cf3dc3c5156b | 465 | // ADE7758 ADE(mosi, miso, sclk, cs); |