Post Go back to editing

Looking to measure current noise in EIS - AD5941

Category: Software
Product Number: AD5941

Hi, I'm looking to measure open-circuit current noise for EIS using the AD5941. Can you please confirm if the following methods are correct?

My protocol is to run a two-wire setup for a known resistor across SE, RE, and CE. 

I run an EIS measurement at a set frequency and set RTIA, and then obtain the DFT values of that known resistor. From there, I use the following equation: 

I_{RMS} = (DFT_{MAGNITUDE} * V_{DD}) / ((2^{16} - 1) * R_{TIA})

Is that equation correct for calculating the I_RMS using the DFT? I know that I don't need to measure RCAL since I'm only measuring current, but I wanted to ask to make sure.

Lastly, is the theoretical value for the I_RMS equivalent to the AC Voltage RMS divided by the sum of the known resistor and the 100 Ohms in series with SE? 

Thank you!



Added AD5941 to title.
[edited by: kbaudue at 3:31 PM (GMT -5) on 6 Feb 2024]
Parents
  • Hi,

    Since you are measuring only current,

    if using EIS example code in GitHub,

    1) you may remove below sections:

    - /* RLOAD Measurement */

    -   /* RCAL Measurement */ 

    inside measure sequence (AppIMPSeqMeasureGen()).

    2) To reduce complexity, you may not enable DFT block in measure sequence:

    AD5940_AFECtrlS(AFECTRL_ADCCNV|AFECTRL_DFT, bTRUE);  /* Start ADC convert and DFT */

    3) You may just do data process as below. It returns current input from SE. (load includes the 100ohm resistor at SE)

    static AD5940Err AppIMPDataProcess(int32_t * const pData, uint32_t *pDataCount)
    {
    uint32_t i, datacount;
    datacount = *pDataCount;
    float *pOut = (float *)pData;
    for(i=0;i<datacount;i++)
    {
    pData[i] &= 0xffff;
    pOut[i] = AppAMPCalcCurrent(pData[i]);
    }
    return AD5940ERR_OK;
    }

  • Hi Akila, 

    Is this still accounting for the AC amplitude? If I understand correctly, I use the following method: 

    1. Apply AC signal at set frequency to two-electrode configuration

    2. Poll the ADC register and NOT the DFT one

    3. Use the Current and Voltage code from the Amperometry example 

    I also have a few questions about the amperometry example: ad5940-examples/examples/AD5940_Amperometric/Amperometric.c at master · analogdevicesinc/ad5940-examples (github.com)

    AppAMPCalcVoltage uses a k-factor: 1.835/1.82 - what is the origin of these values?

    It also uses a 1.8V Ref Voltage, what pin do I measure that from? 

    The RTIA magnitude it uses, in the EIS case, is this just the RTIA I set for that measurement?

    From the current measurements, how would I obtain RMS from these values since I'm using an AC signal instead of the DC one used in Amperometry? 

    Thank you!

  • Hi,

      If you want to measure just open circuit current noise at AIN3, without providing any excitation to load, 

     sw_cfg.Dswitch = SWD_OPEN;
      sw_cfg.Pswitch = SWP_RE0;
      sw_cfg.Nswitch = SWN_SE0;
      sw_cfg.Tswitch = SWT_AIN3|SWT_SE0LOAD;
     AD5940_ADCMuxCfgS(ADCMUXP_HSTIA_P, ADCMUXN_HSTIA_N);
    1) To obtain magnitude and phase of measured current,
    Dataprocess can be defined as below:
    static AD5940Err AppIMPDataProcess(int32_t * const pData, uint32_t *pDataCount)
    {
    uint32_t DataCount = *pDataCount;
    uint32_t ImpCurrentCount = DataCount/2;

    fImpPol_Type * const pOut = (fImpPol_Type*)pData;
    iImpCar_Type * pSrcData = (iImpCar_Type*)pData;

    *pDataCount = 0;

    DataCount = (DataCount/2)*2;/* One DFT result has two data in FIFO, real part and imaginary part. */

    /* Convert DFT result to int32_t type */
    for(uint32_t i=0; i<DataCount; i++)
    {
    pData[i] &= 0x3ffff; /* @todo option to check ECC */
    if(pData[i]&(1<<17)) /* Bit17 is sign bit */
    {
    pData[i] |= 0xfffc0000; /* Data is 18bit in two's complement, bit17 is the sign bit */
    }
    }
    for(uint32_t i=0; i<ImpCurrentCount; i++)
    {
    iImpCar_Type *pDftVolt, *pDftCurr;

    pDftCurr = pSrcData++;

    CurrMag = sqrt((float)pDftCurr->Real*pDftCurr->Real+(float)pDftCurr->Image*pDftCurr->Image);
    CurrPhase = atan2(-pDftCurr->Image,pDftCurr->Real);

    AD5940_HSRtiaCal(&AppIMPCfg, AppIMPCfg.RtiaCurrValue); //get the calibrated value of RTIA

    CurrMag = CurrMag/AppIMPCfg.RtiaCurrValue[0];
    CurrPhase = CurrPhase + AppIMPCfg.RtiaCurrValue[1];

    pOut[i].Magnitude = CurrMag;
    pOut[i].Phase = CurrPhase;
    }
    *pDataCount = ImpCurrentCount;

    return AD5940ERR_OK;
    }
    2) To obtain just variance of measured current,
    you may use AD5940_StatisticCfgS(&stat_cfg) as mentioned in the thread above and do AppAMPCalcCurrent() of the measured output FIFO data.
  • Hi Akila, 

    I am sorry for the inconvenience, but I don't think we're currently on the same understanding in measuring current, and I'd like to try from the start again.

    I looked at the ADC_Polling.c example as a reference, which falls in line with what you recommended for Voltage measurement (OCP, open circuit potential) using the AD5940 resp. ADuCM355 - Q&A - Precision ADCs - EngineerZone (analog.com). The problem is, that method doesn't utilize the HSTIA and samples directly from the ADC, so I'm not really getting to measure the noise due to the HSTIA. 

    Now, I don't want to run a discrete fourier transform to have to get the current from the HSTIA. I can get the voltage from the HSTIA (and therefore get accurate measurements for current noise) using this: 

     adc_base.ADCMuxP = ADCMUXP_HSTIA_P;
     adc_base.ADCMuxN = ADCMUXN_HSTIA_N;
    To measure VSE0, I use the ADC_Polling.c code along with the following switch matrix configuration:
     sw_cfg.Dswitch = SWD_CE0;
     sw_cfg.Pswitch = SWP_RE0;
     sw_cfg.Nswitch = SWN_SE0;
     sw_cfg.Tswitch = SWT_SE0LOAD|SWT_TRTIA;
    The ADC code is valid because I am not using Vzero, I'm using the 1.11V reference, which is what ADCMUXN_HSTIA_P is connected to as the default Vzero setting on SE0. 
     
    I've printed the outputs and I'm not sure I'm able to get VSE0 measurements. SWD and SWP don't matter in this case because I only care about VSE0 and I disabled the waveform generator, but changing Vzero for SE0 doesn't indicate the changes in measurement.
    Additionally, the problem is that Vocp requires VRE0 since that's the reference (VSE0 w.r.t VRE0), and I just measured VSE0 w.r.t GND and 1.11V reference. 
    What I would really appreciate is a way to measure VRE0 w.r.t GND and the 1.11V reference that still uses the HSTIA and the proper switch configuration for it so I can adequately compare them, without having to do a DFT. The switch configuration you provided for me regarding AIN3 doesn't really work.
    Or is this a valid formula for evaluating the current noise through the HSTIA, and can you please explain why because I'm happy to use it, I just don't know if it's an appropriate method for finding the noise through the HSTIA. I've been able to get good results with it, however, which is why I'm asking. It is the method you also propose in the other threads.

     (1) AD5940_ADCMuxCfgS (ADCMUXP_VSE0 ,ADCMUXN_VZERO0); // for measurement of SE0 w.r.t. VZERO0

     (2) AD5940_ADCMuxCfgS (ADCMUXP_VRE0 ,ADCMUXN_VZERO0); // for measurement of RE0 w.r.t. VZERO0

    I_OCP =  [(1) - (2) ] / R_HSTIA, and should the 100 Ohm resistor for SE0Load be accounted for in this equation. If so, how? 

    I'd greatly appreciate the help. You've been a fantastic resource in this process. 

    Kevin 

  • Hi Akila, 

    I figured out a solution that makes sense to me. Showing this here for anyone else who would want to do so.

    The method below uses a two-electrode setup with the following switch configuration: 

      sw_cfg.Dswitch = SWD_CE0;
      sw_cfg.Pswitch = SWP_RE0;
      sw_cfg.Nswitch = SWN_SE0;
      sw_cfg.Tswitch = SWT_SE0LOAD|SWT_TRTIA;
      AD5940_SWMatrixCfgS(&sw_cfg);
    And uses the following filter settings: 
      adc_filter.ADCSinc3Osr = ADCSINC3OSR_4;
      adc_filter.ADCSinc2Osr = ADCSINC2OSR_1333;
      adc_filter.ADCAvgNum = ADCAVGNUM_2;         /* Don't care about it. Average function is only used for DFT */
      adc_filter.ADCRate = ADCRATE_800KHZ;        /* If ADC clock is 32MHz, then set it to ADCRATE_1P6MHZ. Default is 16MHz, use ADCRATE_800KHZ. */
      adc_filter.BpNotch = bTRUE;                 /* SINC2+Notch is one block, when bypass notch filter, we can get fresh data from SINC2 filter. */
      adc_filter.BpSinc3 = bTRUE;                /* Bypassing SINC3 Filter */  
      adc_filter.Sinc2NotchEnable = bTRUE;        /* Enable the SINC2+Notch block. You can also use function AD5940_AFECtrlS */
      AD5940_ADCFilterCfgS(&adc_filter);
    Here, CE0 and RE0 are tied together to have the same common-mode / bias voltage as SE0. See below: 

    I set the HSTIA common-mode voltage to be at 1.11V using the 1.11V reference (HsLoopCfg.HsTiaCfg.HstiaBias = HSTIABIAS_1P1), and measure the voltage through SE0 through the following switch configuration: 

      adc_base.ADCMuxP = ADCMUXP_HSTIA_P;
      adc_base.ADCMuxN = ADCMUXN_HSTIA_N;
      adc_base.ADCPga = ADCPGA_1;
    Then I sample it through a similar method using ADCPolling.c by reading
    AD5940_ReadAfeResult(AFEResult_SINC3). Even though SINC2NotchEnable is on, SINC3 is bypassed. By reading SINC3, we actually read the raw ADC codes. 
     This gives me VSE0 w.r.t. HSTIA_N, which is 1.11 V as per the datasheet. 
    To measure VRE0, I use the ADC using the following MUX configuration: 
          adc_base.ADCMuxP = ADCMUXP_VRE0;
          adc_base.ADCMuxN = ADCMUXN_VREF1P1;
          adc_base.ADCPga = ADCPGA_1;
    This is valid because RE0 and CE0 are tied together and set at the same baseline voltage as the HSTIA common-mode, which is also the 1.11V reference. 
    Then I sample it again using a similar method as ADCPolling.c, also reading the SINC3 filter result. This gives me VRE0 w.r.t. 1.11V, also equivalent to HSTIA_N. 
    Thus, we achieve VOCP = VSE0 - VRE0. I've confirmed this differential measurement with a DMM at the SE0 and RE0/CE0 (tied together pins) and got the similar values between the DMM and the calculated VOCP using this method. 
    This method utilizes the HSTIA to measure input current noise through SE0, which is what makes sense to me for measuring input current noise. 
    Hope this helps! please confirm if this is a valid method!
    Thank you for your help, Akila!
  • Hi Kevin,

    Yes. It is a valid method.

    If the aim is to measure only open circuit current,

    I was just wondering why VRE0 is required to be measured here as open circuit current input can be measured at SE0 alone and processed.

    Since this is open circuit, CE0 is irrelevant as there is no excitation.

    RE0 is irrelevant as this feedback is not going to be used by excitation amplifier for providing any excitation.

    Of course, for measuring Open circuit voltage across RE0/CE0 and SE0, your method is perfect.

  • Oh that's interesting. So if I just wanted open-circuit current input noise, I can just measure at SE0 using: 

     sw_cfg.Dswitch = SWD_CE0;
      sw_cfg.Pswitch = SWP_RE0;
      sw_cfg.Nswitch = SWN_SE0;
      sw_cfg.Tswitch = SWT_SE0LOAD|SWT_TRTIA;
      AD5940_SWMatrixCfgS(&sw_cfg);
      adc_base.ADCMuxP = ADCMUXP_HSTIA_P;
      adc_base.ADCMuxN = ADCMUXN_HSTIA_N;
      adc_base.ADCPga = ADCPGA_1;
    And I would be able to get the input current noise this way?
  • Hi,

    Yes. To ensure that no excitation is given to the load, sw_cfg.Dswitch can be set to SWD_OPEN.

  • Oh okay, I see. And this is valid even with 1.11V at the HSTIA_N because the SE0_Pin also has the same zero voltage? One last question though, can you explain further why we aren't accounting for RE0 in measuring current noise here since it is the reference when we do electrochemical measurements, but we account for it when we calculate OCP? 

    Thanks Akila!

  • Hi,

    RE0 is an input to AD5940. It is not used anywhere in current measurement.

    (I assumed that no bias potential is required for the electrochemical to generate this open circuit current.

    If my assumption is wrong. then CE/RE play role is providing the bias potential to the electrochemical)

  • Hi, 

    When using the HSTIA, isn't the cell always biased at 1.11V when there is no external bias is applied? 

    Given this, and that CE/RE do play a role, shouldn't the method be measuring Vocp and then dividing by the HSTIA as I've addressed above? 

  • Hi,

      adc_base.ADCMuxP = ADCMUXP_HSTIA_P;
      adc_base.ADCMuxN = ADCMUXN_HSTIA_N

    Differential voltage measured by ADC = VHSTIA_P  - VHSTIA_N 

                                                                 = VHSTIA_P  - VSE0

                                                                 = Open circuit Input current X RTIA

    Therefore, Open circuit input current = ADC Measured value / RTIA

    CE/RE doesn't come into picture here if no bias or excitation potential is required to control the current.

Reply
  • Hi,

      adc_base.ADCMuxP = ADCMUXP_HSTIA_P;
      adc_base.ADCMuxN = ADCMUXN_HSTIA_N

    Differential voltage measured by ADC = VHSTIA_P  - VHSTIA_N 

                                                                 = VHSTIA_P  - VSE0

                                                                 = Open circuit Input current X RTIA

    Therefore, Open circuit input current = ADC Measured value / RTIA

    CE/RE doesn't come into picture here if no bias or excitation potential is required to control the current.

Children