Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of ADE7758 by
ade7758.cpp
00001 #include "mbed.h" 00002 #include "ade7758.h" 00003 #include "SWSPI.h" 00004 00005 // public 00006 ADE7758::ADE7758(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName interrupt): 00007 _ADE7758SPI(mosi, miso, sclk), _ADESS(cs), _ADEINT(interrupt) 00008 { 00009 _ADESS = 1; 00010 } 00011 00012 void ADE7758::begin() 00013 { 00014 enableChip(); 00015 //normal mode 00016 _ADE7758SPI.format(8, 1); // pha 0, pol 1 00017 _ADE7758SPI.frequency(1000000); 00018 write8bits(OPMODE, 0x04); 00019 } 00020 00021 void ADE7758::calibrateVI(uint8_t numSamples) 00022 { 00023 write8bits(LCYCMODE, 0x38); 00024 write24bits(MASK, 0xE00); 00025 long AVRMSBuffer = 0, BVRMSBuffer = 0, CVRMSBuffer = 0; 00026 long AIRMSBuffer = 0, BIRMSBuffer = 0, CIRMSBuffer = 0; 00027 for (uint8_t i=0; i<numSamples; i++) { 00028 read24bits(RSTATUS); 00029 while ( _ADEINT != 0 ) { } // wait until INT go low 00030 AVRMSBuffer += VRMS(PHASE_A); 00031 BVRMSBuffer += VRMS(PHASE_B); 00032 CVRMSBuffer += VRMS(PHASE_C); 00033 AIRMSBuffer += IRMS(PHASE_A); 00034 BIRMSBuffer += IRMS(PHASE_B); 00035 CIRMSBuffer += IRMS(PHASE_C); 00036 } 00037 AVRMSCalib = AVRMSBuffer/numSamples; 00038 BVRMSCalib = BVRMSBuffer/numSamples; 00039 CVRMSCalib = CVRMSBuffer/numSamples; 00040 AIRMSCalib = AIRMSBuffer/numSamples; 00041 BIRMSCalib = BIRMSBuffer/numSamples; 00042 CIRMSCalib = CIRMSBuffer/numSamples; 00043 } 00044 00045 void ADE7758::writeRMSOffset(uint16_t AIRMSOSValue, uint16_t BIRMSOSValue, uint16_t CIRMSOSValue, uint16_t AVRMSOSValue, uint16_t BVRMSOSValue, uint16_t CVRMSOSValue) { 00046 // Collect for ITEST & VNOM, IMIN & VMIN 00047 // Calculate these values in an Excel sheet according to page 00048 // Write the results to the xIRMSOS and xVRMSOS registers 00049 write16bits(AIRMSOS, AIRMSOSValue); // Current channel A 00050 write16bits(BIRMSOS, BIRMSOSValue); // Current channel B 00051 write16bits(CIRMSOS, CIRMSOSValue); // Current channel C 00052 write16bits(AVRMSOS, AVRMSOSValue); // Voltage channel A 00053 write16bits(BVRMSOS, BVRMSOSValue); // Voltage channel B 00054 write16bits(CVRMSOS, CVRMSOSValue); // Voltage channel C 00055 } 00056 00057 void ADE7758::calibrateGain(char phase) { // see datasheet ADE 7758 page 49 of 72 00058 // 1. Clear xWG, xVARG, xVAG 00059 write16bits(AWG, 0x0000); 00060 write16bits(BWG, 0x0000); 00061 write16bits(CWG, 0x0000); 00062 write16bits(AVARG, 0x0000); 00063 write16bits(BVARG, 0x0000); 00064 write16bits(CVARG, 0x0000); 00065 write16bits(AVAG, 0x0000); 00066 write16bits(BVAG, 0x0000); 00067 write16bits(CVAG, 0x0000); 00068 00069 // 2. Select phase for line period measurement 00070 lineFreq(phase); 00071 00072 // 3. Configure LCYCMODE register with 0xBF 00073 write8bits(LCYCMODE, 0xBF); 00074 00075 // 4. Set number of half line cycles 00076 write16bits(LINECYC, 0x800); 00077 00078 // 5. Set LENERGY bit in MASK register for interrupt 00079 uint16_t mask; 00080 mask = read16bits(MASK); 00081 write24bits(MASK, mask | (1<<LENERGY)); 00082 wait_ms(10); 00083 00084 // 6. Environment setting 00085 // set environment - ITEST and VNOM 00086 00087 // 7. Reset RSTATUS 00088 read24bits(RSTATUS); 00089 00090 // 8. Wait LENERGY interrupt and read 6 energy registers 00091 while ( _ADEINT != 0 ) { } // wait until INT go low 00092 int AWATTHRTemp = getWattHR(PHASE_A); 00093 int AVAHRTemp = getVAHR(PHASE_A); 00094 int BWATTHRTemp = getWattHR(PHASE_B); 00095 int BVAHRTemp = getVAHR(PHASE_B); 00096 int CWATTHRTemp = getWattHR(PHASE_C); 00097 int CVAHRTemp = getVAHR(PHASE_C); 00098 00099 // 9. Calculate Wh/LSB and VAh/LSB 00100 float accumTime = getAccumulationTime(PHASE_A); 00101 float tempEnergy = ITEST*VNOM*accumTime; 00102 AWhLSB = tempEnergy/(3600*AWATTHRTemp); 00103 BWhLSB = tempEnergy/(3600*BWATTHRTemp); 00104 CWhLSB = tempEnergy/(3600*CWATTHRTemp); 00105 AVAhLSB = tempEnergy/(3600*AVAHRTemp); 00106 BVAhLSB = tempEnergy/(3600*BVAHRTemp); 00107 CVAhLSB = tempEnergy/(3600*CVAHRTemp); 00108 00109 // 10. Clear and wait LENERGY interrupt and read 6 energy registers 00110 wait_ms(10); 00111 read24bits(RSTATUS); 00112 while ( _ADEINT != 0 ) { } // wait until INT go low 00113 int AWHREXPECTED = getWattHR(PHASE_A); 00114 int AVAHREXPECTED = getVAHR(PHASE_A); 00115 int BWHREXPECTED = getWattHR(PHASE_B); 00116 int BVAHREXPECTED = getVAHR(PHASE_B); 00117 int CWHREXPECTED = getWattHR(PHASE_C); 00118 int CVAHREXPECTED = getVAHR(PHASE_C); 00119 00120 // 11. Calculate xWG and xVAG values 00121 AWGCalib = ((float)(AWHREXPECTED/AWATTHRTemp) - 1)*4096; 00122 BWGCalib = ((float)(BWHREXPECTED/BWATTHRTemp) - 1)*4096; 00123 CWGCalib = ((float)(CWHREXPECTED/CWATTHRTemp) - 1)*4096; 00124 AVAGCalib = ((float)(AVAHREXPECTED/AVAHRTemp) - 1)*4096; 00125 BVAGCalib = ((float)(BVAHREXPECTED/BVAHRTemp) - 1)*4096; 00126 CVAGCalib = ((float)(CVAHREXPECTED/CVAHRTemp) - 1)*4096; 00127 00128 // 10. Write the values to xWG and xVAG 00129 write16bits(AWG, AWGCalib); 00130 write16bits(BWG, BWGCalib); 00131 write16bits(CWG, CWGCalib); 00132 write16bits(AVAG, AVAGCalib); 00133 write16bits(BVAG, BVAGCalib); 00134 write16bits(CVAG, CVAGCalib); 00135 } 00136 00137 float ADE7758::getAccumulationTime(char phase) { 00138 uint16_t frequency = lineFreq(phase); 00139 uint16_t LineCYC = read16bits(LINECYC); 00140 write8bits(LCYCMODE, 0xBF); 00141 float LineFrequency = 1/(frequency*0.0000096); 00142 return LineCYC/(2*LineFrequency*3); 00143 } 00144 00145 int ADE7758::getWattHR(char phase) 00146 { 00147 return read16bits(AWATTHR+phase); 00148 } 00149 00150 int ADE7758::getVARHR(char phase) 00151 { 00152 return read16bits(AVARHR+phase); 00153 } 00154 00155 int ADE7758::getVAHR(char phase) 00156 { 00157 return read16bits(AVAHR+phase); 00158 } 00159 00160 int ADE7758::WattHR(char phase) 00161 { 00162 return getWattHR(phase); 00163 } 00164 00165 int ADE7758::VARHR(char phase) 00166 { 00167 return getVARHR(phase); 00168 } 00169 00170 int ADE7758::VAHR(char phase) 00171 { 00172 return getVAHR(phase); 00173 } 00174 00175 long ADE7758::VRMS(char phase) 00176 { 00177 char i=0; 00178 long volts=0; 00179 getVRMS(phase);//Ignore first reading 00180 for(i=0;i<10;++i){ 00181 volts+=getVRMS(phase); 00182 wait_us(50); 00183 } 00184 //average 00185 return volts/10; 00186 } 00187 00188 long ADE7758::IRMS(char phase) 00189 { 00190 char i=0; 00191 long current=0; 00192 getIRMS(phase);//Ignore first reading 00193 for(i=0;i<10;++i){ 00194 current+=getIRMS(phase); 00195 wait_us(50); 00196 } 00197 //average 00198 return current/10; 00199 } 00200 00201 00202 float ADE7758::calculateIRMS(char phase) { 00203 long IRMSBuffer = 0; 00204 float AvgIRMS = 0; 00205 for (char i=0; i<NUMSAMPLES; i++) { 00206 IRMSBuffer += IRMS(phase); 00207 } 00208 AvgIRMS = IRMSBuffer/NUMSAMPLES; 00209 00210 if ( phase == PHASE_A ) { 00211 return AvgIRMS * 0.0000125; 00212 } 00213 else if ( phase == PHASE_B ) { 00214 return AvgIRMS * 0.0000123; 00215 } 00216 else if ( phase == PHASE_C ) { 00217 return AvgIRMS * 0.0000124; 00218 } 00219 else { return 0; } 00220 } 00221 00222 float ADE7758::calculateVRMS(char phase) { 00223 long VRMSBuffer = 0; 00224 float AvgVRMS = 0; 00225 for (char i=0; i<NUMSAMPLES; i++) { 00226 VRMSBuffer += VRMS(phase); 00227 } 00228 AvgVRMS = VRMSBuffer/NUMSAMPLES; 00229 00230 if ( phase == PHASE_A ) { 00231 return AvgVRMS * 0.000158; 00232 } 00233 else if ( phase == PHASE_B ) { 00234 return AvgVRMS * 0.000157; 00235 } 00236 else if ( phase == PHASE_C ) { 00237 return AvgVRMS * 0.000156; 00238 } 00239 else { return 0; } 00240 } 00241 00242 void ADE7758::getEnergy(char phase, uint8_t samplingPeriod, float *AWattHr, float *BWattHr, float *CWattHr, float *AVAHr, float *BVAHr, float *CVAHr) { 00243 float period = 0; 00244 long AWattHrSum = 0; 00245 long BWattHrSum = 0; 00246 long CWattHrSum = 0; 00247 long AVAHrSum = 0; 00248 long BVAHrSum = 0; 00249 long CVAHrSum = 0; 00250 00251 uint16_t AWattHrValue, BWattHrValue, CWattHrValue, AVAHrValue, BVAHrValue, CVAHrValue; 00252 while (period < samplingPeriod*60.0) { 00253 period += ADE.getAccumulationTime(PHASE_A); 00254 ADE7758::getAccumulatedEnergy(phase, &AWattHrValue, &BWattHrValue, &CWattHrValue, &AVAHrValue, &BVAHrValue, &CVAHrValue); 00255 AWattHrSum += AWattHrValue; 00256 BWattHrSum += BWattHrValue; 00257 CWattHrSum += CWattHrValue; 00258 AVAHrSum += AVAHrValue; 00259 BVAHrSum += BVAHrValue; 00260 CVAHrSum += CVAHrValue; 00261 } 00262 *AWattHr = AWattHrSum * AWhLSB; 00263 *BWattHr = BWattHrSum * BWhLSB; 00264 *CWattHr = CWattHrSum * CWhLSB; 00265 00266 *AVAHr = AVAHrSum * AVAhLSB; 00267 *BVAHr = BVAHrSum * BVAhLSB; 00268 *CVAHr = CVAHrSum * CVAhLSB; 00269 } 00270 00271 void ADE7758::getAccumulatedEnergy(char phase, uint16_t *AWattHr, uint16_t *BWattHr, uint16_t *CWattHr, uint16_t *AVAHr, uint16_t *BVAHr, uint16_t *CVAHr) 00272 { 00273 // 1. Set phase used for line zero cross detection 00274 lineFreq(phase); 00275 00276 // 2. Configure LCYCMODE register with 0xBF 00277 write8bits(LCYCMODE, 0xBF); 00278 00279 // 3. Set number of half line cycles 00280 write16bits(LINECYC, 0x800); 00281 00282 // 4. Set LENERGY bit in MASK register for interrupt 00283 uint16_t mask; 00284 mask = read16bits(MASK); 00285 write24bits(MASK, mask | (1<<LENERGY)); 00286 wait_ms(10); 00287 00288 // 5. Reset RSTATUS 00289 read24bits(RSTATUS); 00290 00291 // 6. Wait LENERGY interrupt and read 6 energy registers 00292 while ( _ADEINT != 0 ) { } // wait until INT go low 00293 *AWattHr = getWattHR(PHASE_A); 00294 *AVAHr = getVAHR(PHASE_A); 00295 *BWattHr = getWattHR(PHASE_B); 00296 *BVAHr = getVAHR(PHASE_B); 00297 *CWattHr = getWattHR(PHASE_C); 00298 *CVAHr = getVAHR(PHASE_C); 00299 } 00300 00301 long ADE7758::waveform(char phase,char source) 00302 { 00303 return 1; 00304 } 00305 00306 void ADE7758::powerOff() 00307 { 00308 00309 } 00310 00311 void ADE7758::powerON() 00312 { 00313 00314 } 00315 00316 void ADE7758::sleep() 00317 { 00318 00319 } 00320 00321 void ADE7758::wakeUp() 00322 { 00323 00324 } 00325 00326 long ADE7758::getInterruptStatus(void){ 00327 return read24bits(STATUS); 00328 } 00329 00330 long ADE7758::getResetInterruptStatus(void){ 00331 return read24bits(RSTATUS); 00332 } 00333 00334 int ADE7758::lineFreq(char phase){ 00335 uint8_t mmode; 00336 mmode = read8bits(MMODE); 00337 write8bits(MMODE,( mmode&0xFC )| phase); 00338 wait_ms(10); 00339 return read16bits(FREQ); 00340 } 00341 // private 00342 00343 void ADE7758::enableChip() 00344 { 00345 _ADESS = 0; 00346 } 00347 00348 void ADE7758::disableChip() 00349 { 00350 _ADESS = 1; 00351 } 00352 00353 void ADE7758::write8bits(char reg, unsigned char data) 00354 { 00355 enableChip(); 00356 00357 wait_ms(10); 00358 _ADE7758SPI.write(REG_WRITE(reg)); 00359 wait_ms(2); 00360 00361 _ADE7758SPI.write(data); 00362 00363 wait_ms(1); 00364 00365 disableChip(); 00366 } 00367 00368 void ADE7758::write16bits(char reg, unsigned int data) 00369 { 00370 enableChip(); 00371 00372 wait_ms(10); 00373 _ADE7758SPI.write(REG_WRITE(reg)); 00374 wait_ms(2); 00375 _ADE7758SPI.write((unsigned char)((data>>8)&0xFF)); 00376 wait_ms(2); 00377 _ADE7758SPI.write((unsigned char)(data&0xFF)); 00378 wait_ms(1); 00379 00380 disableChip(); 00381 } 00382 00383 void ADE7758::write24bits(char reg, unsigned int data) 00384 { 00385 enableChip(); 00386 00387 wait_ms(10); 00388 _ADE7758SPI.write(REG_WRITE(reg)); 00389 wait_ms(2); 00390 _ADE7758SPI.write((unsigned char)((data>>16)&0xFF)); 00391 wait_ms(2); 00392 _ADE7758SPI.write((unsigned char)((data>>8)&0xFF)); 00393 wait_ms(2); 00394 _ADE7758SPI.write((unsigned char)(data&0xFF)); 00395 wait_ms(1); 00396 00397 disableChip(); 00398 } 00399 00400 unsigned char ADE7758::read8bits(char reg) 00401 { 00402 enableChip(); 00403 00404 unsigned char ret; 00405 wait_ms(10); 00406 _ADE7758SPI.write(REG_READ(reg)); 00407 wait_ms(2); 00408 ret=_ADE7758SPI.write(0x00); 00409 wait_ms(1); 00410 00411 disableChip(); 00412 00413 return ret; 00414 } 00415 00416 unsigned int ADE7758::read16bits(char reg) 00417 { 00418 enableChip(); 00419 unsigned int ret=0; 00420 unsigned char ret0=0; 00421 wait_ms(10); 00422 _ADE7758SPI.write(REG_READ(reg)); 00423 wait_ms(2); 00424 ret=_ADE7758SPI.write(0x00); 00425 wait_ms(2); 00426 ret0=_ADE7758SPI.write(0x00); 00427 wait_ms(1); 00428 00429 disableChip(); 00430 ret= (ret<<8)|ret0; 00431 return ret; 00432 } 00433 00434 unsigned long ADE7758::read24bits(char reg) 00435 { 00436 enableChip(); 00437 unsigned long ret=0; 00438 unsigned int ret1=0; 00439 unsigned char ret0=0; 00440 wait_ms(10); 00441 _ADE7758SPI.write(REG_READ(reg)); 00442 wait_ms(2); 00443 ret=_ADE7758SPI.write(0x00); 00444 wait_ms(2); 00445 ret1=_ADE7758SPI.write(0x00); 00446 wait_ms(2); 00447 ret0=_ADE7758SPI.write(0x00); 00448 wait_ms(1); 00449 00450 disableChip(); 00451 ret= (ret<<16)|(ret1<<8)| ret0; 00452 return ret; 00453 } 00454 00455 long ADE7758::getIRMS(char phase) 00456 { 00457 return read24bits(AIRMS+phase); 00458 } 00459 00460 long ADE7758::getVRMS(char phase) 00461 { 00462 return read24bits(AVRMS+phase); 00463 } 00464 00465 // ADE7758 ADE(mosi, miso, sclk, cs);
Generated on Wed Jul 13 2022 11:36:54 by
1.7.2
