ADE120x Library Files

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ADE120x.cpp Source File

ADE120x.cpp

Go to the documentation of this file.
00001 /**  
00002  @file       ADE120x.cpp
00003  @brief      ADE120x library. This file contains all ADE120x library functions. 
00004  @version    V0.0.1
00005  @author     ADI
00006  @date       October 2019
00007  @par Revision History:
00008  
00009  Copyright (c) 2017-2019 Analog Devices, Inc. All Rights Reserved.
00010  
00011  This software is proprietary to Analog Devices, Inc. and its licensors.
00012  By using this software you agree to the terms of the associated
00013  Analog Devices Software License Agreement. 
00014 *****************************************************************************/
00015 
00016 #include "ADE120x.h"
00017  
00018  /* Constructor for ADE120x; intializes the SPI interface only */
00019 ADE120x::ADE120x(   PinName mosi,PinName miso,PinName sclk,PinName cs) : spi_(mosi, miso, sclk), nCS_(cs) {
00020                     //5MHz, allowed up to 10MHz
00021                     nCS_ = 1;
00022                     spi_.frequency(5000000);
00023                     spi_.format(16, 3);             
00024                 }
00025 
00026 /**
00027     @brief Write to ADE120x register through SPI. 
00028     @param addr: The address of the ADE120x device.
00029     @param reg_addr: register address 
00030     @param data: register data
00031     @return received data.
00032 **/
00033 void ADE120x::WriteReg(uint8_t addr, uint32_t reg_addr, uint32_t data)
00034 {
00035     int cmd;
00036     nCS_ = 0;
00037     wait_us(1);
00038     cmd = reg_addr * 0x0010 + addr;    //R/nW bit set to 0
00039     spi_.write(cmd);
00040     spi_.write(data);
00041     wait_us(1);
00042     nCS_ = 1;
00043 }
00044 /**
00045     @brief Read ADE120x register through SPI. 
00046     @param addr: The address of the ADE120x device.
00047     @param reg_addr: register address 
00048     @return received data.
00049 **/
00050 uint32_t ADE120x::ReadReg(uint8_t addr, uint32_t reg_addr)
00051 {
00052     int cmd;
00053     int resp;    
00054     nCS_ = 0;
00055     wait_us(1);
00056     //cmd = REG*0x0020 + 0x18 + addr;    //R/nW bit set to 0
00057     cmd = reg_addr*0x0010 + 0x8 + addr;      
00058     spi_.write(cmd);
00059     resp = spi_.write(0xFFFF);
00060     wait_us(1);
00061     nCS_ = 1;
00062     return resp;
00063 }
00064 
00065 /**
00066   @brief Reset ADE120x. 
00067   @param addr: The address of the ADE120x device.
00068   @return return none.
00069 **/
00070 uint8_t ADE120x::Reset(uint8_t addr)
00071 {
00072     UnLock(addr);
00073     WriteReg(addr, REG_CTRL, 0x0010);
00074     //wait until RSTDONE bit is set
00075     while ((ReadReg(addr, REG_INT_STATUS) & INTSRC_RSTDONE) == 0)
00076     {  }
00077     return 0;
00078 }
00079 
00080 /**
00081   @brief Read back device ID. 
00082   @param addr: The address of the ADE120x device.
00083   @return device ID.
00084 **/
00085 uint16_t ADE120x::GetDevID(uint8_t addr)
00086 {
00087     uint16_t response;
00088     response = ReadReg(addr, REG_CTRL);
00089     return response;
00090 }
00091 
00092 /**
00093   @brief Lock ADE120x. When device is locked all register writes are ignored
00094   @param addr: The address of the ADE120x device.
00095   @return none.
00096 **/
00097 void ADE120x::Lock(uint8_t addr)
00098 {
00099     WriteReg(addr, REG_LOCK, DEV_LOCK);
00100 }
00101 
00102 /**
00103   @brief Unlock ADE120x. Unlock device before writing to registers
00104   @param addr: The address of the ADE120x device.
00105   @return none.
00106 **/
00107 void ADE120x::UnLock(uint8_t addr)
00108 {
00109     WriteReg(addr, REG_LOCK, DEV_UNLOCK);
00110     wait_us(100);
00111 }
00112 
00113 /**
00114     @brief Configure interrupt. 
00115     @param addr: the address of the ADE120x device.
00116     @param IntSrcSel: Interrupt source to enable.
00117     @return Status.
00118 **/
00119 void ADE120x::SetInt(uint8_t addr, uint16_t IntSrcSel)
00120 {
00121     WriteReg(addr, REG_MASK, IntSrcSel);
00122 }
00123 
00124 /**
00125     @brief Clear interrupt status. 
00126     @param addr: the address of the ADE120x device.
00127     @param IntSrcSel: Interrupt source to clear.
00128     @return Status.
00129 **/
00130 void ADE120x::ClearIntStatus(uint8_t addr, uint16_t IntSrcSel)
00131 {
00132     WriteReg(addr, REG_INT_STATUS, IntSrcSel);
00133 }
00134 
00135 /**
00136   @brief Get Interrupt Status. 
00137   @param addr: the address of the ADE120x device.
00138   @return Status.
00139 **/
00140 uint16_t ADE120x::GetIntStatus(uint8_t addr)
00141 {
00142     uint16_t status;
00143     status = ReadReg(addr, REG_INT_STATUS);
00144     return status;
00145 }
00146 
00147 /**
00148     @brief Configure ADC PGA gain. 
00149     @param addr: the address of the ADE120x device.
00150     @param Gain: Select from the following
00151                             ADCPGA_1, ADCPGA_2, ADCPGA_5, ADCPGA_10.
00152     @return Status.
00153 **/
00154 void ADE120x::SetPgaGain(uint8_t addr, uint16_t gain)
00155 {
00156     UnLock(addr);
00157     WriteReg(addr, REG_PGA_GAIN, gain);
00158     Lock(addr);
00159 }
00160 
00161 /**
00162     @brief Read ADC data. 
00163     @param addr: the address of the ADE120x device.
00164     @param src: ADC source, ADC_DECIMATOR to select decimator output. ADC_RAW for raw output.
00165     @return Status.
00166 **/
00167 uint8_t ADE120x::ReadADC(uint8_t addr, int8_t src)
00168 {
00169     uint8_t code;
00170     if(src == ADC_DECIMATOR)
00171         code = ReadReg(addr, REG_ADCDEC);
00172     else
00173         code = ReadReg(addr, REG_ADC);
00174     return code;
00175 }
00176 
00177 /**
00178   @brief Set binary Threshold. 
00179   @param addr: the address of the ADE120x device.
00180   @param thresh: Threshold value.
00181   @return none.
00182 **/
00183 void ADE120x::SetBinaryThresh(uint8_t addr, uint16_t thresh)
00184 {
00185     WriteReg(addr, REG_BIN_THR, thresh);
00186 }
00187 
00188 /**
00189   @brief Calculate threshold register code. 
00190   @param V_Thresh: Threshold value in volts.
00191   @param ADCPga: PGA gain value
00192   @param V_Gain: Gain of external voltage divider circuit
00193   @return 0.
00194 **/
00195 uint8_t ADE120x::CalculateThreshCode(float V_Thresh, uint8_t ADCPga, float V_Gain)
00196 {
00197     uint8_t code;
00198     float tmp;
00199     tmp = (V_Thresh * V_Gain * ADCPga * 255)/1.25 + 0.5;
00200     code = (uint8_t)tmp;
00201     return code;
00202 }
00203 
00204 /**
00205   @brief Configure threshold voltage for BIN, WARNA, WARNB and WARNC. 
00206   @param addr: the address of the ADE120x device.
00207   @param pCfg: Pointer to structure
00208   @return 0.
00209 **/
00210 uint8_t ADE120x::ThresholdCfg(uint8_t addr, THRESHCfg_Type *pCfg)
00211 {
00212     uint8_t Thresh_H, Thresh_L;
00213     uint16_t bin_ctrl, tmp;
00214     UnLock(addr);
00215     Thresh_H = CalculateThreshCode(pCfg->BIN_HighThresh, pCfg->ADCPga, pCfg->VGain);
00216     Thresh_L = CalculateThreshCode(pCfg->BIN_LowThresh, pCfg->ADCPga, pCfg->VGain);
00217     WriteReg(addr, REG_BIN_THR, (Thresh_L<<8)|Thresh_H);
00218     
00219     Thresh_H = CalculateThreshCode(pCfg->WARNA_HighThresh, pCfg->ADCPga, pCfg->VGain);
00220     Thresh_L = CalculateThreshCode(pCfg->WARNA_LowThresh, pCfg->ADCPga, pCfg->VGain);
00221     WriteReg(addr, REG_WARNA_THR , (Thresh_L<<8)|Thresh_H);
00222     
00223     Thresh_H = CalculateThreshCode(pCfg->WARNB_HighThresh, pCfg->ADCPga, pCfg->VGain);
00224     Thresh_L = CalculateThreshCode(pCfg->WARNB_LowThresh, pCfg->ADCPga, pCfg->VGain);
00225     WriteReg(addr, REG_WARNB_THR, (Thresh_L<<8)|Thresh_H);
00226     
00227     Thresh_H = CalculateThreshCode(pCfg->WARNC_HighThresh, pCfg->ADCPga, pCfg->VGain);
00228     Thresh_L = CalculateThreshCode(pCfg->WARNC_LowThresh, pCfg->ADCPga, pCfg->VGain);
00229     WriteReg(addr, REG_WARNC_THR, (Thresh_L<<8)|Thresh_H);
00230     
00231     bin_ctrl = (pCfg->BIN_Mode<<6)|(pCfg->WARNA_Mode<<8)|(pCfg->WARNB_Mode<<10)|(pCfg->WARNC_Mode<<12);
00232     tmp = ReadReg(addr, REG_BIN_CTRL);
00233     tmp &= 0xFFFF&~(0xFF<<6);
00234     WriteReg(addr, REG_BIN_CTRL, tmp|bin_ctrl);
00235     tmp = ReadReg(addr, REG_BIN_CTRL);
00236     return 0;
00237 }
00238 
00239 /**
00240   @brief Configure programmable load. 
00241   @param addr: the address of the ADE120x device.
00242   @param pCfg: Pointer to structure
00243   @return 0.
00244 **/
00245 uint8_t ADE120x::ProgrammableLoadCfg(uint8_t addr, PLOADCfg_Type *pCfg)
00246 {
00247     float tmp;
00248     WriteReg(addr, REG_PL_CTRL, pCfg->mode);
00249     if(pCfg->mode == LOW_IDLE)
00250         WriteReg(addr, REG_PL_RISE_THR, 
00251                     CalculateThreshCode(pCfg->VoltThresh, pCfg->ADCPga, pCfg->VGain));
00252     
00253     tmp = (pCfg->HighCurrent/0.2) + 0.5f; /* add 0.5 to round up */
00254    WriteReg(addr, REG_PL_HIGH_CODE, (uint16_t)tmp);
00255     
00256     tmp = (pCfg->HighTime/10) + 0.5f;
00257     WriteReg(addr, REG_PL_HIGH_TIME, (uint16_t)tmp);
00258     
00259     tmp = (pCfg->LowCurrent/0.1) + 0.5f;
00260     WriteReg(addr, REG_PL_LOW_CODE, (uint16_t)tmp);
00261     
00262     if(pCfg->enable == CH1_Enable)
00263         WriteReg(addr, REG_PL_EN, PL_CH1_ENABLE);
00264     if(pCfg->enable == CH2_Enable)
00265         WriteReg(addr, REG_PL_EN, PL_CH2_ENABLE);
00266     if(pCfg->enable == CH1_CH2_Enable)
00267         WriteReg(addr, REG_PL_EN, PL_CH2_ENABLE|PL_CH1_ENABLE);
00268     if(pCfg->enable == CH1_Disable)
00269        WriteReg(addr, REG_PL_EN, 0);
00270     
00271     return 0;
00272 }
00273 
00274 /**
00275   @brief Configure Energy Meter. 
00276   @param addr: the address of the ADE120x device.
00277   @param pCfg: Pointer to structure
00278   @return 0.
00279 **/
00280 uint8_t ADE120x::EnergyMtrCfg(uint8_t addr, EnergyMtrCfg_Type *pCfg)
00281 {
00282     float pulse_enrgy, AvgADCCode, tmp;
00283     uint16_t reg_val, reg_mtr_ctrl;
00284     AvgADCCode = (255*pCfg->WorkingVoltage*pCfg->VGain*pCfg->ADCPga)/1.25;
00285     /* Step 1: Calculate pulse energy in Jules: (Pulse time * Working Current * Voltage) / 1000 */
00286     pulse_enrgy = (pCfg->PulseMagnitude * pCfg->FET_Energy * pCfg->PulseTime)/1000;
00287     
00288     /* Step 2: Calculate ENERGY_MTR register value:  */
00289     tmp = (AvgADCCode * (pCfg->PulseTime/1000))/(128 * pCfg->SampleRate)+0.5;
00290     reg_val = (uint16_t)tmp;
00291     WriteReg(addr, REG_EGY_MTR_THR, reg_val);
00292 
00293 
00294     reg_mtr_ctrl = (pCfg->Cooldown_Decr<<8)|pCfg->Cooldown_Sec|(pCfg->Cooldown_TimeStep<<4)|(pCfg->Ov_Scale<<6);
00295     WriteReg(addr, REG_EGY_MTR_CTRL, reg_mtr_ctrl);
00296     
00297     return 1;
00298 }
00299 
00300 /**
00301   @brief Read all ADE120xregisters. 
00302   @param addr: the address of the ADE120x device.
00303   @return 0.
00304 **/
00305 void ADE120x::GetRegisterData(uint8_t addr, RegisterData_Type *pBuff)
00306 {
00307     uint16_t reg_addr[] = {
00308         REG_CTRL, 
00309         REG_BIN_CTRL,       
00310         REG_BIN_THR,        
00311         REG_WARNA_THR,          
00312         REG_WARNB_THR,     
00313         REG_WARNC_THR,      
00314         REG_BIN_FILTER,     
00315         REG_WARNA_FILTER,   
00316         REG_WARNB_FILTER,   
00317         REG_WARNC_FILTER,   
00318         REG_MASK,          
00319         REG_PL_CTRL,        
00320         REG_PL_RISE_THR,   
00321         REG_PL_LOW_CODE,    
00322         REG_PL_HIGH_CODE,   
00323         REG_PL_HIGH_TIME,   
00324         REG_EGY_MTR_CTRL,   
00325         REG_EGY_MTR_THR,    
00326         REG_PL_EN, 
00327         REG_PGA_GAIN};
00328     
00329     uint8_t reg_addr_size = sizeof(reg_addr)/sizeof(*reg_addr);
00330     uint8_t i = 0;
00331     while(i<reg_addr_size)
00332     {
00333         pBuff[i].reg_addr = reg_addr[i]; 
00334         pBuff[i].reg_data = ReadReg(addr, reg_addr[i]);
00335         i++;
00336         wait_us(1000);     
00337     }
00338 }
00339 
00340 /**
00341   @brief Convert ADC Code to voltage. 
00342   @param ADCCode: ADC code.
00343   @param ADCPga: the actual 1.82V reference voltage.
00344   @param VOLTAGE_Gain: THe gain factor set by the external resistor divider network 
00345   @return Voltage in volt.
00346 **/
00347 float ADE120x::ADCCode2Volt(uint32_t ADCCode, uint8_t ADCPga, float VOLTAGE_Gain)
00348 {
00349     float tmp = 0.0;
00350     float fVolt = 0.0;
00351     tmp = (ADCCode&0xFF);
00352     tmp = 1.25 * (tmp/255) / VOLTAGE_Gain;
00353     switch(ADCPga)
00354     {
00355         case ADCPGA_1:
00356         fVolt = tmp;
00357         break;
00358         case ADCPGA_2:
00359         fVolt = tmp/2;
00360         break;
00361         case ADCPGA_5:
00362         fVolt = tmp/5; 
00363         break;
00364         case ADCPGA_10:
00365         fVolt = tmp/10; 
00366         break;
00367         default:break;
00368         }
00369         return fVolt;
00370 }