Post Go back to editing

ADE9000 THD

I'm testing the ADE9000 using the evaluation board.  I'm connecting to the board using an Arduino.  I have successfully retrieved waveform data, 10cycle RMS voltage, 1/2 cycle RMS voltage.  I don't get a valid value for AVTHD, BVTHD or CVTHD.  I'm connecting to a 120V single phase circuit on phase A, B and C.  I found the app note AN-1483 to get THD.  I believe I'm following the steps correctly.  So far it doesn't matter what I do, values returned are 400% if the voltage is applied and 0 if there is no voltage. 

I found the answer to set ENERGY_PWR_EN, this value is set to EP_CFG 0x0011

Is there something else that I need to do?

Thanks

Parents
  • Hi Swoods,

    I have been developing the ADE9000 by Arduino, I have doubt in ADE9000 Arduino calibration and how do you convert raw values into Actual meter readings?.

    Can you share any reference materials( calibration excel sheet, Arduino sketch)

  • The only calibration I have done is on A phase voltage.  That was an estimation from readings with a hand held voltage meter.  I'm using the ADE9000API_Test sketch that was with the resource documentation from the website with the shield support files.  I have enabled the values I could find to enable THD calculation.  I have read values from the THD registers "VTHD=(ade9000.SPI_Read_32(ADDR_AVTHD))*pow(2,-27)*100" and the "ade9000.ReadVoltageTHDRegsnValues(&voltageTHDRegsnValues)"

    If I have voltage applied I get max 400% THD, if voltage is not applied I get 0 THD.  I'm able to download waveforms and RMS values without trouble.

    Below is the test sketch that I have been modifying to use the ADE9000.  I tried to use the insert code feature on the forum, but I couldn't get it to insert.  So I inserted the code as text between the <> characters below.

    Thanks

    <


    #include <SPI.h>
    #include  <ADE9000RegMap.h>
    #include <ADE9000API.h>

    /*Basic initializations*/
    ADE9000Class ade9000;
    #define SPI_SPEED 5000000     //SPI Speed
    #define CS_PIN 0 //8-->Arduino Zero. 16-->ESP8266 //*changed to 0 for mkr1000
    #define ADE9000_RESET_PIN 5 //Reset Pin on HW
    #define PM_1 4              //PM1 Pin: 4-->Arduino Zero. 15-->ESP8266

    /*Structure decleration */
    struct ActivePowerRegs powerRegs;     // Declare powerRegs of type ActivePowerRegs to store Active Power Register data
    struct CurrentRMSRegs curntRMSRegs;   //Current RMS
    struct VoltageRMSRegs vltgRMSRegs;    //Voltage RMS
    struct VoltageTHDRegs voltageTHDRegsnValues; //Voltage THD
    struct ResampledWfbData resampledData; // Resampled Data

    /*Function Decleration*/
    void readRegisterData(void);
    void readResampledData(void);
    void resetADE9000(void);

    double AVRMS1012 =0;
    double AVRMS1 =0;
    double BVRMS1 =0;
    double CVRMS1 =0;
    long AVTHD=0;
    int second =1000;
    int second_60=60000;
    unsigned long PrevMill=0;
    unsigned long PrevMill_60=0;
    void setup()
    {
      Serial.begin(115200);
      pinMode(PM_1, OUTPUT);    //Set PM1 pin as output
      digitalWrite(PM_1, LOW);   //Set PM1 select pin low for PSM0 mode
      pinMode(ADE9000_RESET_PIN, OUTPUT);
      digitalWrite(ADE9000_RESET_PIN, HIGH);
      void resetADE9000();
      delay(1000);
      ade9000.SPI_Init(SPI_SPEED,CS_PIN); //Initialize SPI
      ade9000.SetupADE9000();             //Initialize ADE9000 registers according to values in ADE9000API.h
      //ade9000.SPI_Write_16(ADDR_RUN,0x1); //Set RUN=1 to turn on DSP. Uncomment if SetupADE9000 function is not used
      Serial.print("RUN Register: ");
      Serial.println(ade9000.SPI_Read_16(ADDR_RUN),HEX);
    //ADE9000.SPI_Write_32(uint16_t Address , uint32_t Data );
     ade9000.SPI_Write_32(ADDR_AVGAIN,0xA71775);
     Serial.print("AVGAIN: ");
    Serial.println(ade9000.SPI_Read_32(ADDR_AVGAIN),HEX); // AVGAIN
    Serial.println(ade9000.SPI_Read_32(ADDR_ACCMODE),BIN); // AVGAIN
    Serial.println(ade9000.SPI_Read_16(ADDR_RUN),BIN); // AVGAIN
    //Serial.print("WFB_CFG:");
    //Serial.println(ade9000.SPI_Read_32(ADDR_WFB_CFG),HEX);
    //ade9000.SPI_Write_16(ADDR_WFB_CFG,0x3F0);
    Serial.println("Energy Power Reg");
    Serial.println(ade9000.SPI_Read_16(ADDR_EP_CFG),HEX);  //Energy Power REG
    }

    void loop() {
      unsigned long currentmills = millis();
      if ((unsigned long)(currentmills - PrevMill) >= second)
      {
        PrevMill=currentmills;
       // ade9000.SPI_Write_16(ADDR_WFB_CFG,0x3F0);
        //delay(2000);
         readRegisterData();
         //ade9000.SPI_Write_16(ADDR_WFB_CFG,0x1000);
      }
      if ((unsigned long)(currentmills -PrevMill_60) >=second_60)
      {
        PrevMill_60=currentmills;

        ade9000.SPI_Write_16(ADDR_WFB_CFG,0x1000);
      ade9000.SPI_Write_16(ADDR_WFB_CFG,0x3F0);
      delay(100);
         //readResampledData();
      }
     
     // delay(1000);
    }

    void readRegisterData()
    {
     /*Read and Print Specific Register using ADE9000 SPI Library */
    //  Serial.print("AIRMS: ");
    //  Serial.println(ade9000.SPI_Read_32(ADDR_AIRMS),HEX); // AIRMS
    //AVRMSONE
    /*
     * Phase A current fast rms½ calculation, one cycle rms updated every half cycle.
     */

     AVRMS1=(ade9000.SPI_Read_32(ADDR_AVRMS));//*1.1/100000;
        Serial.print("A_VRMSONE: ");
      //Serial.println((ade9000.SPI_Read_32(ADDR_AVRMSONE)),HEX); // A VRMS ONE  ADDR_AVFRMS
      AVRMS1=AVRMS1/100000;
      Serial.println(AVRMS1,DEC); // A VRMS ONE

      BVRMS1=(ade9000.SPI_Read_32(ADDR_BVRMSONE));//*1.1/100000;
        Serial.print("B_VRMSONE: ");
      //Serial.println((ade9000.SPI_Read_32(ADDR_BVRMSONE)),HEX); // B VRMS ONE
      BVRMS1=BVRMS1/100000;
      Serial.println(BVRMS1,DEC); // B VRMS ONE

      CVRMS1=(ade9000.SPI_Read_32(ADDR_CVRMSONE));//*1.1/100000;
        Serial.print("C_VRMSONE: ");
      //Serial.println((ade9000.SPI_Read_32(ADDR_CVRMSONE)),HEX); // C VRMS ONE
      CVRMS1=CVRMS1/100000;
      Serial.println(CVRMS1,DEC); // C VRMS ONE

     
      /* AVRMS1012=(ade9000.SPI_Read_32(ADDR_AVRMS1012));
     Serial.print("AVRM1012: ");
      AVRMS1012=AVRMS1012/100000;
      Serial.println(AVRMS1012,DEC); // AVRMS1012
     */
    // ADDR_AVTHD

    Serial.println("Energy Power Reg");
    Serial.println(ade9000.SPI_Read_16(ADDR_EP_CFG),HEX);  //Energy Power REG

     //ade9000.SPI_Write_16(ADDR_WFB_CFG,0x1000);
      //ade9000.SPI_Write_16(ADDR_WFB_CFG,0x3F0);
      //delay(100); //approximate time to fill the waveform buffer with 4 line cycles
    Serial.print("WFB_CFG:");
    Serial.println(ade9000.SPI_Read_16(ADDR_WFB_CFG),HEX);
    AVTHD=(ade9000.SPI_Read_32(ADDR_AVTHD))*pow(2,-27)*100;
    //ADDR_VPEAK//ADDR_AVTHD
    Serial.print("AVTHD:     ");
      //AVTHD=AVTHD*pow(2,-27)*100;
      Serial.println(AVTHD); // ADDR_AVTHD

      AVTHD=(ade9000.SPI_Read_32(ADDR_BVTHD))*pow(2,-27)*100;
      Serial.print("BVTHD:     ");
      Serial.println(AVTHD); // ADDR_AVTHD

      AVTHD=(ade9000.SPI_Read_32(ADDR_CVTHD))*pow(2,-27)*100;
      Serial.print("CVTHD:     ");
      Serial.println(AVTHD); // ADDR_AVTHD

    //AVRMS
    /*-Phase A voltage fast 10 cycle rms/12 cycle rms calculation. The calculation is
     *performed over 10 cycles if SELFREQ = 0 for a 50 Hz network or over 12 cycles if
     *SELFREQ = 1 for a 60 Hz network, in the ACCMODE register.
     */

     /*
      * AVRMSONEOS
      * Phase A voltage rms offset for the fast rms½ AVRMSONE calculation.
      */
     /*Read and Print RMS & WATT Register using ADE9000 Read Library*/
     //struct VoltageTHDRegs voltageTHDRegsnValues; //Voltage THD
     //struct VoltageRMSRegs vltgRMSRegs;    //Voltage RMS
     
     ade9000.ReadVoltageTHDRegsnValues(&voltageTHDRegsnValues);
      Serial.print("ATHDREG:");       
      Serial.println(voltageTHDRegsnValues.VoltageTHDValue_A); //Print AVRMS register
     
     // ade9000.ReadVoltageRMSRegs(&vltgRMSRegs);    //Template to read Power registers from ADE9000 and store data in Arduino MCU
    //  ade9000.ReadActivePowerRegs(&powerRegs);
    //  Serial.print("AVRMS:");
    //  AVRMS1012=vltgRMSRegs.VoltageRMSReg_A;
      //AVRMS1012=(AVRMS1012*1.1)/100000;  
    //  AVRMS1012=(AVRMS1012);  
    //  Serial.println(AVRMS1012); //Print AVRMS register
     // delay(100);
    //  Serial.print("BVRMS:");       
    //  Serial.println(powerRegs.VoltageRMSReg_B); //Print AWATT register
    //  delay(100);
    //  Serial.print("CVRMS:");       
    //  Serial.println(powerRegs.VoltageRMSReg_C); //Print AWATT register
    }

    void readResampledData()
    {
      uint32_t temp;
    /*Read and Print Resampled data*/
      /*Start the Resampling engine to acquire 4 cycles of resampled data*/
      ade9000.SPI_Write_16(ADDR_WFB_CFG,0x1000);
      ade9000.SPI_Write_16(ADDR_WFB_CFG,0x1010);
      delay(100); //approximate time to fill the waveform buffer with 4 line cycles 
      /*Read Resampled data into Arduino Memory*/
      ade9000.SPI_Burst_Read_Resampled_Wfb(0x800,WFB_ELEMENT_ARRAY_SIZE,&resampledData);   // Burst read function
     
      for(temp=0;temp<WFB_ELEMENT_ARRAY_SIZE;temp++)
        {
          Serial.print("VA: ");
          Serial.println(resampledData.VA_Resampled[temp],DEC);
          //Serial.print("IA: ");
         // Serial.println(resampledData.IA_Resampled[temp],HEX);
         // Serial.print("VB: ");
         // Serial.println(resampledData.VB_Resampled[temp],HEX);
        //  Serial.print("IB: ");
        //  Serial.println(resampledData.IB_Resampled[temp],HEX);
        //  Serial.print("VC: ");
       //   Serial.println(resampledData.VC_Resampled[temp],HEX);
        //  Serial.print("IC: ");
       //   Serial.println(resampledData.IC_Resampled[temp],HEX);
       //   Serial.print("IN: ");
       //   Serial.println(resampledData.IN_Resampled[temp],HEX);
       }

    }

    void resetADE9000(void)
    {
     digitalWrite(ADE9000_RESET_PIN, LOW);
     delay(50);
     digitalWrite(ADE9000_RESET_PIN, HIGH);
     delay(1000);
     Serial.println("Reset Done");
    }

    >

  • Hi Swoods,

    I had found this Calibration excel,  this could help to find the actual meter readings, I have been trying to configure ADE9000 to 3wire DELTA connection, In star connection, I had read successfully the voltage, current and power values.

    ADE9000-Calibration-Tool.zip

Reply Children
  • I didn't see anything in the excel calibration sheet that would help me get VTHD values.  The RMS voltage registers give me valid values.  I do need to divide the value by 100000 to scale it to 120 volt base.  Could it be the high pass or low pass filters?  Or will it not calculate THD from a single phase source?  

  • Hi Swods

    In ADE9000API.cpp, they have applied the formulas for AVTHD and AITHD,  You can directly print this 

    void ADE9000Class:: ReadVoltageTHDRegsnValues(VoltageTHDRegs *Data)
    {
    	uint32_t tempReg;
    	float tempValue;
    	
    	tempReg=int32_t (SPI_Read_32(ADDR_AVTHD)); //Read THD register
    	Data->VoltageTHDReg_A = tempReg;
    	tempValue=(float)tempReg*100/(float)134217728; //Calculate THD in %
    	Data->VoltageTHDValue_A=tempValue;	
    	tempReg=int32_t (SPI_Read_32(ADDR_BVTHD)); //Read THD register
    	Data->VoltageTHDReg_B = tempReg;
    	tempValue=(float)tempReg*100/(float)134217728; //Calculate THD in %
    	Data->VoltageTHDValue_B=tempValue;		
    	tempReg=int32_t (SPI_Read_32(ADDR_CVTHD)); //Read THD register
    	Data->VoltageTHDReg_C = tempReg;
    	tempValue=(float)tempReg*100/(float)134217728; //Calculate THD in %
    	Data->VoltageTHDValue_C=tempValue;			
    }
     

    values using 

    Serial.print(VoltageTHDRegs.VoltageTHDRegsnValues);
    . i didn't tried this.

    But I have successfully calibrated 3wire delta configuration and read Total  VRMS,IRMS, Active power. and trying to get PF, VAR, VA and Line frequencies. 

Before You Switch


Switching languages will make ADI Explorer unavailable. Resume your session by switching back to English and reopening ADI Explorer.