ADE120x Library Files
ADE120x.cpp
- Committer:
- mlambe
- Date:
- 2019-10-03
- Revision:
- 1:2eb9d6296ec3
- Parent:
- 0:952a6272c495
- Child:
- 2:f9a986799375
File content as of revision 1:2eb9d6296ec3:
/** * @file ADE120x.cpp * @brief ADE120x library. This file contains all ADE120x library functions. * @version V0.0.1 * @author ADI * @date October 2019 * @par Revision History: * * Copyright (c) 2017-2019 Analog Devices, Inc. All Rights Reserved. * * This software is proprietary to Analog Devices, Inc. and its licensors. * By using this software you agree to the terms of the associated * Analog Devices Software License Agreement. **/ #include "ADE120x.h" /*! \mainpage ADE120x Library Introduction * * # Introduction * * The documentation is for ADE120x library and examples. * TBD */ /* Constructor for ADE120x; intializes the SPI interface only */ ADE120x::ADE120x( PinName mosi,PinName miso,PinName sclk,PinName cs) : spi_(mosi, miso, sclk), nCS_(cs) { //5MHz, allowed up to 10MHz nCS_ = 1; spi_.frequency(5000000); spi_.format(16, 3); } /** @brief Write to ADE120x register through SPI. @param addr: The address of the ADE120x device. @param reg_addr: register address @param data: register data @return received data. **/ void ADE120x::WriteReg(uint8_t addr, uint32_t reg_addr, uint32_t data) { int cmd; nCS_ = 0; wait_us(1); cmd = reg_addr * 0x0010 + addr; //R/nW bit set to 0 spi_.write(cmd); spi_.write(data); wait_us(1); nCS_ = 1; } /** @brief Read ADE120x register through SPI. @param addr: The address of the ADE120x device. @param reg_addr: register address @return received data. **/ uint32_t ADE120x::ReadReg(uint8_t addr, uint32_t reg_addr) { int cmd; int resp; nCS_ = 0; wait_us(1); //cmd = REG*0x0020 + 0x18 + addr; //R/nW bit set to 0 cmd = reg_addr*0x0010 + 0x8 + addr; spi_.write(cmd); resp = spi_.write(0xFFFF); wait_us(1); nCS_ = 1; return resp; } /** @brief Reset ADE120x. @param addr: The address of the ADE120x device. @return return none. **/ uint8_t ADE120x::Reset(uint8_t addr) { UnLock(addr); WriteReg(addr, REG_CTRL, 0x0010); //wait until RSTDONE bit is set while ((ReadReg(addr, REG_INT_STATUS) & INTSRC_RSTDONE) == 0) { } return 0; } /** @brief Read back device ID. @param addr: The address of the ADE120x device. @return device ID. **/ uint16_t ADE120x::GetDevID(uint8_t addr) { uint16_t response; response = ReadReg(addr, REG_CTRL); return response; } /** @brief Lock ADE120x. When device is locked all register writes are ignored @param addr: The address of the ADE120x device. @return none. **/ void ADE120x::Lock(uint8_t addr) { WriteReg(addr, REG_LOCK, DEV_LOCK); } /** @brief Unlock ADE120x. Unlock device before writing to registers @param addr: The address of the ADE120x device. @return none. **/ void ADE120x::UnLock(uint8_t addr) { WriteReg(addr, REG_LOCK, DEV_UNLOCK); wait_us(100); } /** @brief Configure interrupt. @param addr: the address of the ADE120x device. @param IntSrcSel: Interrupt source to enable. @return Status. **/ void ADE120x::SetInt(uint8_t addr, uint16_t IntSrcSel) { WriteReg(addr, REG_MASK, IntSrcSel); } /** @brief Clear interrupt status. @param addr: the address of the ADE120x device. @param IntSrcSel: Interrupt source to clear. @return Status. **/ void ADE120x::ClearIntStatus(uint8_t addr, uint16_t IntSrcSel) { WriteReg(addr, REG_INT_STATUS, IntSrcSel); } /** @brief Get Interrupt Status. @param addr: the address of the ADE120x device. @return Status. **/ uint16_t ADE120x::GetIntStatus(uint8_t addr) { uint16_t status; status = ReadReg(addr, REG_INT_STATUS); return status; } /** @brief Configure ADC PGA gain. @param addr: the address of the ADE120x device. @param Gain: Select from the following ADCPGA_1, ADCPGA_2, ADCPGA_5, ADCPGA_10. @return Status. **/ void ADE120x::SetPgaGain(uint8_t addr, uint16_t gain) { UnLock(addr); WriteReg(addr, REG_PGA_GAIN, gain); Lock(addr); } /** @brief Read ADC data. @param addr: the address of the ADE120x device. @param src: ADC source, ADC_DECIMATOR to select decimator output. ADC_RAW for raw output. @return Status. **/ uint8_t ADE120x::ReadADC(uint8_t addr, int8_t src) { uint8_t code; if(src == ADC_DECIMATOR) code = ReadReg(addr, REG_ADCDEC); else code = ReadReg(addr, REG_ADC); return code; } /** @brief Convert ADC Code to voltage. @param ADCCode: ADC code. @param ADCPga: the actual 1.82V reference voltage. @param VOLTAGE_Gain: THe gain factor set by the external resistor divider network @return Voltage in volt. **/ float ADE120x::ADCCode2Volt(uint32_t ADCCode, uint8_t ADCPga, float VOLTAGE_Gain) { float tmp = 0.0; float fVolt = 0.0; tmp = (ADCCode&0xFF); tmp = 1.25 * (tmp/255) / VOLTAGE_Gain; switch(ADCPga) { case ADCPGA_1: fVolt = tmp; break; case ADCPGA_2: fVolt = tmp/2; break; case ADCPGA_5: fVolt = tmp/5; break; case ADCPGA_10: fVolt = tmp/10; break; default:break; } return fVolt; } /** @brief Set binary Threshold. @param addr: the address of the ADE120x device. @param thresh: Threshold value. @return none. **/ void ADE120x::SetBinaryThresh(uint8_t addr, uint16_t thresh) { WriteReg(addr, REG_BIN_THR, thresh); } /** @brief Calculate threshold register code. @param V_Thresh: Threshold value in volts. @param ADCPga: PGA gain value @param V_Gain: Gain of external voltage divider circuit @return 0. **/ uint8_t ADE120x::CalculateThreshCode(float V_Thresh, uint8_t ADCPga, float V_Gain) { uint8_t code; float tmp; tmp = (V_Thresh * V_Gain * ADCPga * 255)/1.25 + 0.5; code = (uint8_t)tmp; return code; } /** @brief Configure threshold fvoltage for BIN, WARNA, WARNB and WARNC. @param addr: the address of the ADE120x device. @param pCfg: Pointer to structure @return 0. **/ uint8_t ADE120x::ThresholdCfg(uint8_t addr, THRESHCfg_Type *pCfg) { uint8_t Thresh_H, Thresh_L; uint16_t bin_ctrl, tmp; UnLock(addr); Thresh_H = CalculateThreshCode(pCfg->BIN_HighThresh, pCfg->ADCPga, pCfg->VGain); Thresh_L = CalculateThreshCode(pCfg->BIN_LowThresh, pCfg->ADCPga, pCfg->VGain); WriteReg(addr, REG_BIN_THR, (Thresh_L<<8)|Thresh_H); Thresh_H = CalculateThreshCode(pCfg->WARNA_HighThresh, pCfg->ADCPga, pCfg->VGain); Thresh_L = CalculateThreshCode(pCfg->WARNA_LowThresh, pCfg->ADCPga, pCfg->VGain); WriteReg(addr, REG_WARNA_THR , (Thresh_L<<8)|Thresh_H); Thresh_H = CalculateThreshCode(pCfg->WARNB_HighThresh, pCfg->ADCPga, pCfg->VGain); Thresh_L = CalculateThreshCode(pCfg->WARNB_LowThresh, pCfg->ADCPga, pCfg->VGain); WriteReg(addr, REG_WARNB_THR, (Thresh_L<<8)|Thresh_H); Thresh_H = CalculateThreshCode(pCfg->WARNC_HighThresh, pCfg->ADCPga, pCfg->VGain); Thresh_L = CalculateThreshCode(pCfg->WARNC_LowThresh, pCfg->ADCPga, pCfg->VGain); WriteReg(addr, REG_WARNC_THR, (Thresh_L<<8)|Thresh_H); bin_ctrl = (pCfg->BIN_Mode<<6)|(pCfg->WARNA_Mode<<8)|(pCfg->WARNB_Mode<<10)|(pCfg->WARNC_Mode<<12); tmp = ReadReg(addr, REG_BIN_CTRL); tmp &= 0xFFFF&~(0xFF<<6); WriteReg(addr, REG_BIN_CTRL, tmp|bin_ctrl); tmp = ReadReg(addr, REG_BIN_CTRL); return 0; } /** @brief Configure programmable load. @param addr: the address of the ADE120x device. @param pCfg: Pointer to structure @return 0. **/ uint8_t ADE120x::ProgrammableLoadCfg(uint8_t addr, PLOADCfg_Type *pCfg) { float tmp; WriteReg(addr, REG_PL_CTRL, pCfg->mode); if(pCfg->mode == LOW_IDLE) WriteReg(addr, REG_PL_RISE_THR, CalculateThreshCode(pCfg->VoltThresh, pCfg->ADCPga, pCfg->VGain)); tmp = (pCfg->HighCurrent/0.2) + 0.5f; /* add 0.5 to round up */ WriteReg(addr, REG_PL_HIGH_CODE, (uint16_t)tmp); tmp = (pCfg->HighTime/10) + 0.5f; WriteReg(addr, REG_PL_HIGH_TIME, (uint16_t)tmp); tmp = (pCfg->LowCurrent/0.1) + 0.5f; WriteReg(addr, REG_PL_LOW_CODE, (uint16_t)tmp); if(pCfg->enable == CH1_Enable) WriteReg(addr, REG_PL_EN, PL_CH1_ENABLE); if(pCfg->enable == CH2_Enable) WriteReg(addr, REG_PL_EN, PL_CH2_ENABLE); if(pCfg->enable == CH1_CH2_Enable) WriteReg(addr, REG_PL_EN, PL_CH2_ENABLE|PL_CH1_ENABLE); if(pCfg->enable == CH1_Disable) WriteReg(addr, REG_PL_EN, 0); return 0; } /** @brief Configure Energy Meter. @param addr: the address of the ADE120x device. @param pCfg: Pointer to structure @return 0. **/ uint8_t ADE120x::EnergyMtrCfg(uint8_t addr, EnergyMtrCfg_Type *pCfg) { float pulse_enrgy, AvgADCCode, tmp; uint16_t reg_val, reg_mtr_ctrl; AvgADCCode = (255*pCfg->WorkingVoltage*pCfg->VGain*pCfg->ADCPga)/1.25; /* Step 1: Calculate pulse energy in Jules: (Pulse time * Working Current * Voltage) / 1000 */ pulse_enrgy = (pCfg->PulseMagnitude * pCfg->FET_Energy * pCfg->PulseTime)/1000; /* Step 2: Calculate ENERGY_MTR register value: */ tmp = (AvgADCCode * (pCfg->PulseTime/1000))/(128 * pCfg->SampleRate)+0.5; reg_val = (uint16_t)tmp; WriteReg(addr, REG_EGY_MTR_THR, reg_val); reg_mtr_ctrl = (pCfg->Cooldown_Decr<<8)|pCfg->Cooldown_Sec|(pCfg->Cooldown_TimeStep<<4)|(pCfg->Ov_Scale<<6); WriteReg(addr, REG_EGY_MTR_CTRL, reg_mtr_ctrl); return 1; } /** @brief Read all ADE120xregisters. @param addr: the address of the ADE120x device. @return 0. **/ void ADE120x::GetRegisterData(uint8_t addr, RegisterData_Type *pBuff) { uint16_t reg_addr[] = { REG_CTRL, REG_BIN_CTRL, REG_BIN_THR, REG_WARNA_THR, REG_WARNB_THR, REG_WARNC_THR, REG_BIN_FILTER, REG_WARNA_FILTER, REG_WARNB_FILTER, REG_WARNC_FILTER, REG_MASK, REG_PL_CTRL, REG_PL_RISE_THR, REG_PL_LOW_CODE, REG_PL_HIGH_CODE, REG_PL_HIGH_TIME, REG_EGY_MTR_CTRL, REG_EGY_MTR_THR, REG_PL_EN, REG_PGA_GAIN}; uint8_t reg_addr_size = sizeof(reg_addr)/sizeof(*reg_addr); uint8_t i = 0; while(i<reg_addr_size) { pBuff[i].reg_addr = reg_addr[i]; pBuff[i].reg_data = ReadReg(addr, reg_addr[i]); i++; wait_us(1000); } } /** @brief Configure Device with default settings. @param addr: the address of the ADE120x device. @return 0. **/ uint8_t ADE120x::DefaultConfig(uint8_t addr) { /** Array defined for configuration ***/ uint16_t config[] = { //REG_CTRL, 0x04, // REG_BIN_CTRL, 0x0000, REG_BIN_THR, 0x757d, // fail REG_WARNA_THR, 0xcccc, REG_WARNB_THR, 0x5a88, REG_WARNC_THR, 0x2d2d, REG_BIN_FILTER, BIN_FILTER_VAL, //fail using this register to validate against unintended resets in the DOUT validate REG_WARNA_FILTER, 0x80fa, REG_WARNB_FILTER, 0x80fa, REG_WARNC_FILTER, 0x80fa, REG_MASK, 0x4000, REG_PL_CTRL, 0x0000, REG_PL_RISE_THR, 0x007d, // fail REG_PL_LOW_CODE, 0x001e, REG_PL_HIGH_CODE, 0x000f, // fail REG_PL_HIGH_TIME, 0x0001, // fail REG_EGY_MTR_CTRL, 0x0505, REG_EGY_MTR_THR, 0x9ba3, REG_PL_EN, 0xC000, //fail REG_PGA_GAIN, ADCPGA_10 }; //fail uint8_t config_size = sizeof(config)/sizeof(*config); uint8_t i = 0; int resp; wait_us(10000); while(i<config_size-1) { WriteReg(addr, config[i], config[i+1]); resp = ReadReg(addr, config[i]); if (resp != config[i+1]) { printf("Register 0x%x write failed: Expected: 0x%x , Actual: 0x%x \r\n", config[i], config[i+1], resp); return 255; } // printf("Register 0x%x write passed: Expected: 0x%x , Actual: 0x%x \r\n", config[i], config[i+1], resp); i+=2; wait_us(1000); } return 0; }