Post Go back to editing

Best way to take 2 CA measurements simultaneously with AD594X

Thread Summary

The user inquires about performing two simultaneous chronoamperometry (CA) measurements using a single AD5940 chip. The final answer confirms that the AD5940 cannot support parallel CA measurements due to having only one LPTIA. The ADuCM355, which has 2 independent channels, is recommended as an alternative.
AI Generated Content
Category: Hardware
Product Number: AD5940

We’re working on a prototype that needs to perform two independent chronoamperometry (CA) measurements on separate working electrodes. These electrodes may or may not share the same counter electrode. Since the AD594x has only one SE0 pin for a working electrode, we’re exploring our options.

Can a single AD594x support two simultaneous CA measurements, or would we need to use two AD594x chips to enable this functionality?

To clarify, the two CA measurements will have different voltage profiles and durations, but they must run concurrently for research purposes.

Thank you,

Kevin

Parents
  • Hi,

     Since AD5940 has only one LPTIA, 2 parallel current measurements cannot be done. Working electrode can be SE or RE, one measured at a time.

    You may check out ADuCM355 which has 2 independent channels.

  • Hi  , I understand that it is not possible to perform two truly parallel current measurements using the LPTIA, but have two queries below:

    1. I was wondering whether it would be feasible to use two separate loops, which are the LPDAC–LPTIA and HSDAC–HSTIA loops, to obtain two current measurements that operate nearly in parallel?
    2. Alternatively, could I use just one TIA, either the LPTIA or HSTIA, and I rapidly switch between two working electrodes using to approximate parallel operation? (that said, I suspect this approach may not work well, since it would likely be difficult to maintain a stable voltage on one channel while measuring the other).

    Please let me know your thoughts. Thanks in advance.

  • Hi,

    The DACs can be run simultaneously. Sampling can be done either form LPTIA or HSTIA, one at a time, as there is only one ADC.

    In both above cases, ADC inputs need to be switched for each channel measurement, though voltage on TIA output is stable in first case.

  • Hi  , I managed to modify the AD5940_Amperometric example to enable HSTIA for current measurement. I was using the ADICUP3029 microcontroller and a standalone AD5941 IC on a customised breakout board with all the required capacitors as specified in the datasheet. I was trying to apply a 300 mV voltage bias on a 1kohm resistor (tolerance 1%) and measure the current response.

    When I measured the current using the typical LP route, which is LPDAC -> LPPA -> CE0-RE0 -> R1kohm -> SE0 (LP_RLoad=0ohm) -> LPTIA (LP_RTIA=1kohm) -> ADC, I managed to obtain current response of 329uA in average.

    However, when I tried to work on the route of LPDAC -> LPPA -> CE0-RE0 -> R1kohm -> DE0 (HS_RLoad=0ohm) -> HSTIA (HS_RTIA=1kohm) -> ADC (switch matrix config for DE0 is shown in the attached picture below), the current response was 273uA in average. I had tried to use AIN0 to replace DE0 but the current response is still around 270uA. The current responses are so different while measuring using the typical LP route and LPDAC->HSTIA route.

    1. Could you advise any methods to reduce the current difference please? Or is it supposed to have such big difference while using LPTIA and HSTIA for?

    2. Is such current difference caused by the HS_CTIA as shown in Figure 36? If yes, is there anyway to open (disconnect) the CTIA?

    3. Is there any example to calibrate the HSRTIA so that I can obtain the calibrated HS_RTIA value? I am currently using the calibrated LP_RTIA value for current conversion and I think this might be one of the issues as well.


    Please let me know if you require more information. Thanks in advance.

    -------------------------------------------------------
    Update: I managed to include AD5940_HSRtiaCal() function to calibrate the HSRtia. The calibrated RTIA values which I printed directly after calibration are shown as below:

    The HS_RTIA is 1147.717407ohm
    The LP_RTIA is 1112.000610ohm

    The Rload for LPTIA was shorted, and for HSTIA the AIN0 pin was used.The error is quite big as compared to 1000ohm. May I know if this is normal?

  • Hi,

    The difference in calibrated RTIA values you got is expected.

    But final current measured must be same whether it is LPTIA or HSTIA since RTIA is cancelled out.

  • Hi  , thanks for replying. 

    Unfortunately, my current responses from LPTIA and HSTIA are not the same, like what I have mentioned above. Below is the printed Serial output for your reference (Target Vbias of 0.3V on 1kohm resistor):

    LPPA-LPTIA Route:
    Hello AD5940-Build Time:15:48:52
    This AD594x!
    Note: Current Silicon is S2
    AD5940LIB Version:v0.2.1
    Freq:33067.292969
    The HS_RTIA is 1146.321167ohm
    The LP_RTIA is 1110.390503
    index:0, Current:320.448059uA
    index:0, Current:319.069550uA
    index:0, Current:317.119507uA
    index:0, Current:319.338531uA
    index:0, Current:316.144470uA
    index:0, Current:318.733337uA

    * Actual Vbias is 0.316V measured using multimeter

    LPPA-HSTIA Route:
    Hello AD5940-Build Time:15:50:58
    This AD594x!
    Note: Current Silicon is S2
    AD5940LIB Version:v0.2.1
    Freq:33069.175781
    The HS_RTIA is 1148.861572ohm
    The LP_RTIA is 1108.828125
    index:0, Current:264.775757uA
    index:0, Current:265.588135uA
    index:0, Current:266.433014uA
    index:0, Current:265.620636uA
    index:0, Current:263.800842uA
    index:0, Current:264.450806uA

    * Actual Vbias is 0.299V measured using multimeter

    Both codes are the same. I only modify the ADCMuxN and ADCMuxP to control the ADC input.

    Could you advise any debugging steps please?

    Thanks in advance.

  • Are you using Vzero as +ve  input of TIA in both cases?

    Current measured (I) = (TIA output - V+ve)/RTIA

    where V+ve = +ve input to TIA.

  • Hi  , yes I have configured Vzero as +ve input of TIA in both cases as shown below:

    lp_loop.LpDacCfg.LpdacSel = LPDAC0;
    lp_loop.LpDacCfg.LpDacSrc = LPDACSRC_MMR;
    lp_loop.LpDacCfg.LpDacSW = LPDACSW_VBIAS2LPPA|LPDACSW_VBIAS2PIN|LPDACSW_VZERO2LPTIA|LPDACSW_VZERO2PIN|LPDACSW_VZERO2HSTIA;
    lp_loop.LpDacCfg.LpDacVzeroMux = LPDACVZERO_6BIT;
    lp_loop.LpDacCfg.LpDacVbiasMux = LPDACVBIAS_12BIT;
    lp_loop.LpDacCfg.LpDacRef = LPDACREF_2P5;
    lp_loop.LpDacCfg.DataRst = bFALSE;
    lp_loop.LpDacCfg.PowerEn = bTRUE;
    lp_loop.LpDacCfg.DacData6Bit = (uint32_t)((AppAMPCfg.Vzero-200)/DAC6BITVOLT_1LSB);
    lp_loop.LpDacCfg.DacData12Bit =(int32_t)((AppAMPCfg.SensorBias)/DAC12BITVOLT_1LSB) + lp_loop.LpDacCfg.DacData6Bit*64;
    if(lp_loop.LpDacCfg.DacData12Bit>lp_loop.LpDacCfg.DacData6Bit*64)
    lp_loop.LpDacCfg.DacData12Bit--;
    lp_loop.LpAmpCfg.LpAmpSel = LPAMP0;
    lp_loop.LpAmpCfg.LpAmpPwrMod = LPAMPPWR_NORM;
    lp_loop.LpAmpCfg.LpPaPwrEn = bTRUE;
    lp_loop.LpAmpCfg.LpTiaPwrEn = bTRUE;
    lp_loop.LpAmpCfg.LpTiaRf = AppAMPCfg.LpTiaRf;
    lp_loop.LpAmpCfg.LpTiaRload = AppAMPCfg.LpTiaRl;
    lp_loop.LpAmpCfg.LpTiaRtia = AppAMPCfg.LptiaRtiaSel;
    lp_loop.LpAmpCfg.LpTiaSW = LPTIASW(5)|LPTIASW(2)|LPTIASW(4)|LPTIASW(12)|LPTIASW(13);
    AD5940_LPLoopCfgS(&lp_loop);

    HsLoopCfg.HsTiaCfg.DiodeClose = bFALSE;
    HsLoopCfg.HsTiaCfg.HstiaBias = HSTIABIAS_VZERO0;
    HsLoopCfg.HsTiaCfg.HstiaCtia = 31; /* 31pF + 2pF */
    HsLoopCfg.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN;
    HsLoopCfg.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_OPEN;
    HsLoopCfg.HsTiaCfg.HstiaRtiaSel = AppAMPCfg.HstiaRtiaSel; //HSTIARTIA_1K
    HsLoopCfg.SWMatCfg.Dswitch = AppAMPCfg.DswitchSel;
    HsLoopCfg.SWMatCfg.Pswitch = AppAMPCfg.PswitchSel;
    HsLoopCfg.SWMatCfg.Nswitch = AppAMPCfg.NswitchSel;
    HsLoopCfg.SWMatCfg.Tswitch = SWT_TRTIA|AppAMPCfg.TswitchSel;
    AD5940_HSLoopCfgS(&HsLoopCfg);

    I have no idea why the actual bias voltages as well as the measured current response are so different. Do you have any idea please?

    Below is my current measurement code:

    float AppAMPCalcCurrent(uint32_t ADCcode)
    {
    float fCurrent, fVoltage = 0.0;
    fVoltage = AppAMPCalcVoltage(ADCcode);

    /* select current measurement channel */
    // fCurrent = fVoltage/AppAMPCfg.RtiaCalValue.Magnitude; //LPTIA
    fCurrent = fVoltage/AppAMPCfg.RtiaCurrValue[0]; //HSTIA

    return -fCurrent*1000000;
    }

    Thank you.

  • What are D, P, N, T switches that you have set?

  • Hi  , below are my D, P, N, T switches:

    pAMPCfg->DswitchSel = SWD_OPEN;
    pAMPCfg->PswitchSel = SWP_OPEN;
    pAMPCfg->NswitchSel = SWN_OPEN;
    pAMPCfg->TswitchSel = SWT_TRTIA|SWT_AIN0;

    Please have a look.

  • Is the 1k resistor connected across CE0 and SE0?

    If so, set 

    pAMPCfg->TswitchSel = SWT_TRTIA|SWT_SE0LOAD;

    or

    close switches N9 and NL to remove Rload.

    Where are you connecting RE0? Since this is only 2-wire measurement.

  • Hi  , I am trying to use two dummy cells for two TIA pathways. Below is my setup:

    Based on my setup, If I set "pAMPCfg->TswitchSel = SWT_TRTIA|SWT_SE0LOAD;", the HSTIA channel will get zero current, because there is a fixed Rload=100ohm for HSTIA and the Rload for LPTIA is set to be zero so the HSTIA channel will be bypassed and get zero current response as shown below:

    Hello AD5940-Build Time:16:46:34
    This AD594x!
    Note: Current Silicon is S2
    AD5940LIB Version:v0.2.1
    Freq:33050.191406
    The HS_RTIA is 1147.359497ohm
    The LP_RTIA is 1111.570313
    index:0, Current:-6.084670uA
    index:0, Current:-6.735436uA
    index:0, Current:-6.507668uA
    index:0, Current:-6.475129uA

    If I set the Rload of LPTIA to 100ohm to match the Rload of HSTIA, both 1kohm resistors will become parallel and the expected current response will be around ~150uA (~136uA if includes both Rloads) as shown below:

    Hello AD5940-Build Time:16:55:06
    This AD594x!
    Note: Current Silicon is S2
    AD5940LIB Version:v0.2.1
    Freq:33055.218750
    The HS_RTIA is 1143.559082ohm
    The LP_RTIA is 1111.508545
    index:0, Current:120.748291uA
    index:0, Current:120.949814uA
    index:0, Current:121.520821uA
    index:0, Current:121.923859uA
    index:0, Current:121.252106uA
    index:0, Current:120.647522uA

    If I set "close switches N9 and NL to remove Rload.",

    pAMPCfg->DswitchSel = SWD_OPEN;
    pAMPCfg->PswitchSel = SWP_OPEN;
    pAMPCfg->NswitchSel = SWN_SE0|SWN_NL;
    pAMPCfg->TswitchSel = SWT_OPEN;

    I was expecting results like the parallel case above but it turns out HSTIA is bypassed again as shown below:

    Hello AD5940-Build Time:17:09:01
    This AD594x!
    Note: Current Silicon is S2
    AD5940LIB Version:v0.2.1
    Freq:33032.496094
    The HS_RTIA is 1145.684448ohm
    The LP_RTIA is 1110.651733
    index:0, Current:-1.368608uA
    index:0, Current:-0.651718uA
    index:0, Current:-0.651718uA
    index:0, Current:-0.684304uA
    index:0, Current:-1.042749uA
    index:0, Current:-1.270850uA

    Could you advise please?

    Thank you.

Reply
  • Hi  , I am trying to use two dummy cells for two TIA pathways. Below is my setup:

    Based on my setup, If I set "pAMPCfg->TswitchSel = SWT_TRTIA|SWT_SE0LOAD;", the HSTIA channel will get zero current, because there is a fixed Rload=100ohm for HSTIA and the Rload for LPTIA is set to be zero so the HSTIA channel will be bypassed and get zero current response as shown below:

    Hello AD5940-Build Time:16:46:34
    This AD594x!
    Note: Current Silicon is S2
    AD5940LIB Version:v0.2.1
    Freq:33050.191406
    The HS_RTIA is 1147.359497ohm
    The LP_RTIA is 1111.570313
    index:0, Current:-6.084670uA
    index:0, Current:-6.735436uA
    index:0, Current:-6.507668uA
    index:0, Current:-6.475129uA

    If I set the Rload of LPTIA to 100ohm to match the Rload of HSTIA, both 1kohm resistors will become parallel and the expected current response will be around ~150uA (~136uA if includes both Rloads) as shown below:

    Hello AD5940-Build Time:16:55:06
    This AD594x!
    Note: Current Silicon is S2
    AD5940LIB Version:v0.2.1
    Freq:33055.218750
    The HS_RTIA is 1143.559082ohm
    The LP_RTIA is 1111.508545
    index:0, Current:120.748291uA
    index:0, Current:120.949814uA
    index:0, Current:121.520821uA
    index:0, Current:121.923859uA
    index:0, Current:121.252106uA
    index:0, Current:120.647522uA

    If I set "close switches N9 and NL to remove Rload.",

    pAMPCfg->DswitchSel = SWD_OPEN;
    pAMPCfg->PswitchSel = SWP_OPEN;
    pAMPCfg->NswitchSel = SWN_SE0|SWN_NL;
    pAMPCfg->TswitchSel = SWT_OPEN;

    I was expecting results like the parallel case above but it turns out HSTIA is bypassed again as shown below:

    Hello AD5940-Build Time:17:09:01
    This AD594x!
    Note: Current Silicon is S2
    AD5940LIB Version:v0.2.1
    Freq:33032.496094
    The HS_RTIA is 1145.684448ohm
    The LP_RTIA is 1110.651733
    index:0, Current:-1.368608uA
    index:0, Current:-0.651718uA
    index:0, Current:-0.651718uA
    index:0, Current:-0.684304uA
    index:0, Current:-1.042749uA
    index:0, Current:-1.270850uA

    Could you advise please?

    Thank you.

Children
  • Hi,

    You may refer to below code:

    /*!
     *****************************************************************************
     @file:    Amperometric.c
     @author:  $Author: mlambe $
     @brief:   Amperometric measurement.
     @version: $Revision: 766 $
     @date:    $Date: 2018-03-21 14:09:35 +0100 (Wed, 21 Mar 2018) $
     -----------------------------------------------------------------------------
    
    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 "Amperometric.h"
    
    /* 
      Application configuration structure. Specified by user from template.
      The variables are usable in this whole application.
      It includes basic configuration for sequencer generator and application related parameters
    */
    AppAMPCfg_Type AppAMPCfg = 
    {
      .bParaChanged = bFALSE,
      .SeqStartAddr = 0,
      .MaxSeqLen = 0,
      
      .SeqStartAddrCal = 0,
      .MaxSeqLenCal = 0,
      .FifoThresh = 5,              /* Number of points for FIFO */
      
      .SysClkFreq = 16000000.0,
      .WuptClkFreq = 32000.0,
      .AdcClkFreq = 16000000.0,
      .AmpODR = 1.0,                /* Sample time in seconds. I.e. every 5 seconds make a measurement */
      .NumOfData = -1,
      .RcalVal = 10000.0,           /* RCAL = 10kOhm */
      .PwrMod = AFEPWR_LP,
      .AMPInited = bFALSE,
      .StopRequired = bFALSE,
      
      /* LPTIA Configure */
      .ExtRtia = bFALSE,            /* Set to true if using external RTIA */
      .LptiaRtiaSel = LPTIARTIA_4K, /* COnfigure RTIA */
      .LpTiaRf = LPTIARF_1M,        /* Configure LPF resistor */
      .LpTiaRl = LPTIARLOAD_100R,
      .ReDoRtiaCal = bTRUE,
      .RtiaCalValue = 0,
    	.ExtRtiaVal = 0,
      
    /*LPDAC Configure */
      .Vzero = 1100,                /* Sets voltage on SE0 and LPTIA */
      .SensorBias = 500,            /* Sets voltage between RE0 and SE0 */
      
    /* ADC Configure*/
      .ADCPgaGain = ADCPGA_1P5,
      .ADCSinc3Osr = ADCSINC3OSR_4,
      .ADCSinc2Osr = ADCSINC2OSR_22,
      .DataFifoSrc = FIFOSRC_SINC2NOTCH,
      .ADCRefVolt = 1.8162,			/* Measure voltage on ADCRefVolt pin and enter here*/
    };
    
    /**
       This function is provided for upper controllers that want to change 
       application parameters specially for user defined parameters.
    */
    AD5940Err AppAMPGetCfg(void *pCfg)
    {
      if(pCfg){
        *(AppAMPCfg_Type**)pCfg = &AppAMPCfg;
        return AD5940ERR_OK;
      }
      return AD5940ERR_PARA;
    }
    
    AD5940Err AppAMPCtrl(int32_t AmpCtrl, void *pPara)
    {
      switch (AmpCtrl)
      {
        case AMPCTRL_START:
        {
          WUPTCfg_Type wupt_cfg;
    
          AD5940_ReadReg(REG_AFE_ADCDAT); /* Any SPI Operation can wakeup AFE */
          if(AppAMPCfg.AMPInited == bFALSE)
            return AD5940ERR_APPERROR;
          /* Start it */
          wupt_cfg.WuptEn = bTRUE;
          wupt_cfg.WuptEndSeq = WUPTENDSEQ_A;
          wupt_cfg.WuptOrder[0] = SEQID_0;
          wupt_cfg.SeqxSleepTime[SEQID_0] = 1;
          wupt_cfg.SeqxWakeupTime[SEQID_0] = (uint32_t)(AppAMPCfg.WuptClkFreq/AppAMPCfg.AmpODR) - 1;
          AD5940_WUPTCfg(&wupt_cfg);
          
          AppAMPCfg.FifoDataCount = 0;  /* restart */
          break;
        }
        case AMPCTRL_STOPNOW:
        {
          AD5940_ReadReg(REG_AFE_ADCDAT); /* Any SPI Operation can wakeup AFE */
          /* Start Wupt right now */
          AD5940_WUPTCtrl(bFALSE);
          /* There is chance this operation will fail because sequencer could put AFE back 
            to hibernate mode just after waking up. Use STOPSYNC is better. */
          AD5940_WUPTCtrl(bFALSE);
          break;
        }
        case AMPCTRL_STOPSYNC:
        {
          AppAMPCfg.StopRequired = bTRUE;
          break;
        }
        case AMPCTRL_SHUTDOWN:
        {
          AppAMPCtrl(AMPCTRL_STOPNOW, 0);  /* Stop the measurement if it's running. */
          /* Turn off LPloop related blocks which are not controlled automatically by sleep operation */
          AFERefCfg_Type aferef_cfg;
          LPLoopCfg_Type lp_loop;
          memset(&aferef_cfg, 0, sizeof(aferef_cfg));
          AD5940_REFCfgS(&aferef_cfg);
          memset(&lp_loop, 0, sizeof(lp_loop));
          AD5940_LPLoopCfgS(&lp_loop);
          AD5940_EnterSleepS();  /* Enter Hibernate */
        }
        break;
        default:
        break;
      }
      return AD5940ERR_OK;
    }
    
    /* Generate init sequence */
    static AD5940Err AppAMPSeqCfgGen(void)
    {
      AD5940Err error = AD5940ERR_OK;
      uint32_t const *pSeqCmd;
      uint32_t SeqLen;
    
      AFERefCfg_Type aferef_cfg;
      LPLoopCfg_Type lp_loop;
      DSPCfg_Type dsp_cfg;
      SWMatrixCfg_Type sw_cfg;
    	HSTIACfg_Type hstia_cfg; 
    	
      /* Start sequence generator here */
      AD5940_SEQGenCtrl(bTRUE);
    
      //AD5940_AFECtrlS(AFECTRL_ALL, bFALSE);  /* Init all to disable state */
    
      aferef_cfg.HpBandgapEn = bTRUE;
      aferef_cfg.Hp1V1BuffEn = bTRUE;
      aferef_cfg.Hp1V8BuffEn = bTRUE;
      aferef_cfg.Disc1V1Cap = bFALSE;
      aferef_cfg.Disc1V8Cap = bFALSE;
      aferef_cfg.Hp1V8ThemBuff = bFALSE;
      aferef_cfg.Hp1V8Ilimit = bFALSE;
      aferef_cfg.Lp1V1BuffEn = bTRUE;
      aferef_cfg.Lp1V8BuffEn = bTRUE;
      /* LP reference control - turn off them to save power*/
      aferef_cfg.LpBandgapEn = bTRUE;
      aferef_cfg.LpRefBufEn = bTRUE;
      aferef_cfg.LpRefBoostEn = bFALSE;
      AD5940_REFCfgS(&aferef_cfg);	
    
    
    /* Configure HSTIA to measure Current on DE0 */
    	
    	hstia_cfg.DiodeClose = bFALSE;
      hstia_cfg.HstiaBias = HSTIABIAS_VZERO0;
      hstia_cfg.HstiaCtia = 31; /* 31pF + 2pF */
      hstia_cfg.HstiaDeRload = HSTIADERLOAD_OPEN;
      hstia_cfg.HstiaDeRtia = HSTIADERTIA_OPEN;
      hstia_cfg.HstiaRtiaSel = AppAMPCfg.DE0Rtia;
    	AD5940_HSTIACfgS(&hstia_cfg);
    	
    	
    	lp_loop.LpDacCfg.LpdacSel = LPDAC0;
      lp_loop.LpDacCfg.LpDacSrc = LPDACSRC_MMR;
      lp_loop.LpDacCfg.LpDacSW = LPDACSW_VBIAS2LPPA|LPDACSW_VBIAS2PIN|LPDACSW_VZERO2LPTIA|LPDACSW_VZERO2PIN|LPDACSW_VZERO2HSTIA;
      lp_loop.LpDacCfg.LpDacVzeroMux = LPDACVZERO_6BIT;
      lp_loop.LpDacCfg.LpDacVbiasMux = LPDACVBIAS_12BIT;
      lp_loop.LpDacCfg.LpDacRef = LPDACREF_2P5;
      lp_loop.LpDacCfg.DataRst = bFALSE;
      lp_loop.LpDacCfg.PowerEn = bTRUE;
      lp_loop.LpDacCfg.DacData6Bit = (uint32_t)((AppAMPCfg.Vzero-200)/DAC6BITVOLT_1LSB);
    	lp_loop.LpDacCfg.DacData12Bit =(int32_t)((AppAMPCfg.SensorBias)/DAC12BITVOLT_1LSB) + lp_loop.LpDacCfg.DacData6Bit*64;
    	if(lp_loop.LpDacCfg.DacData12Bit>lp_loop.LpDacCfg.DacData6Bit*64)
    		lp_loop.LpDacCfg.DacData12Bit--;
    	lp_loop.LpAmpCfg.LpAmpSel = LPAMP0;
      lp_loop.LpAmpCfg.LpAmpPwrMod = LPAMPPWR_NORM;
      lp_loop.LpAmpCfg.LpPaPwrEn = bTRUE;
      lp_loop.LpAmpCfg.LpTiaPwrEn = bTRUE;
      lp_loop.LpAmpCfg.LpTiaRf = AppAMPCfg.LpTiaRf;
      lp_loop.LpAmpCfg.LpTiaRload = AppAMPCfg.LpTiaRl;
      if(AppAMPCfg.ExtRtia == bTRUE)
      {
        lp_loop.LpAmpCfg.LpTiaRtia = LPTIARTIA_OPEN;
        lp_loop.LpAmpCfg.LpTiaSW = LPTIASW(9)|LPTIASW(2)|LPTIASW(4)|LPTIASW(5)|LPTIASW(12)|LPTIASW(13); 
      }else
      {
        lp_loop.LpAmpCfg.LpTiaRtia = AppAMPCfg.LptiaRtiaSel;
        lp_loop.LpAmpCfg.LpTiaSW = LPTIASW(5)|LPTIASW(2)|LPTIASW(4)|LPTIASW(12)|LPTIASW(13); 
      }
      AD5940_LPLoopCfgS(&lp_loop);
    
      
      dsp_cfg.ADCBaseCfg.ADCMuxN = ADCMUXN_VZERO0;
      dsp_cfg.ADCBaseCfg.ADCMuxP = ADCMUXP_AIN4;
      dsp_cfg.ADCBaseCfg.ADCPga = AppAMPCfg.ADCPgaGain;
      
      memset(&dsp_cfg.ADCDigCompCfg, 0, sizeof(dsp_cfg.ADCDigCompCfg));
      memset(&dsp_cfg.DftCfg, 0, sizeof(dsp_cfg.DftCfg));
      dsp_cfg.ADCFilterCfg.ADCAvgNum = ADCAVGNUM_16;  /* Don't care because it's disabled */
      dsp_cfg.ADCFilterCfg.ADCRate = ADCRATE_800KHZ;	/* Tell filter block clock rate of ADC*/
      dsp_cfg.ADCFilterCfg.ADCSinc2Osr = AppAMPCfg.ADCSinc2Osr;
      dsp_cfg.ADCFilterCfg.ADCSinc3Osr = AppAMPCfg.ADCSinc3Osr;
      dsp_cfg.ADCFilterCfg.BpSinc3 = bFALSE;
      dsp_cfg.ADCFilterCfg.BpNotch = bFALSE;
      dsp_cfg.ADCFilterCfg.Sinc2NotchEnable = bTRUE;
      
      memset(&dsp_cfg.StatCfg, 0, sizeof(dsp_cfg.StatCfg)); /* Don't care about Statistic */
      AD5940_DSPCfgS(&dsp_cfg);
      
      sw_cfg.Dswitch = 0;
      sw_cfg.Pswitch = 0;
      sw_cfg.Nswitch = 0;
      sw_cfg.Tswitch = SWT_DE0|SWT_TRTIA; 
      AD5940_SWMatrixCfgS(&sw_cfg);
        
      /* Enable all of them. They are automatically turned off during hibernate mode to save power */
      AD5940_AFECtrlS(AFECTRL_HPREFPWR|AFECTRL_SINC2NOTCH|AFECTRL_HSTIAPWR, bTRUE);
      AD5940_AFECtrlS(AFECTRL_SINC2NOTCH, bFALSE);
      AD5940_SEQGpioCtrlS(0/*AGPIO_Pin6|AGPIO_Pin5|AGPIO_Pin1*/);        //GP6->endSeq, GP5 -> AD8233=OFF, GP1->RLD=OFF .
      
      /* Sequence end. */
      AD5940_SEQGenInsert(SEQ_STOP()); /* Add one extra command to disable sequencer for initialization sequence because we only want it to run one time. */
    
      /* Stop here */
      error = AD5940_SEQGenFetchSeq(&pSeqCmd, &SeqLen);
      AD5940_SEQGenCtrl(bFALSE); /* Stop sequencer generator */
      if(error == AD5940ERR_OK)
      {
        AppAMPCfg.InitSeqInfo.SeqId = SEQID_1;
        AppAMPCfg.InitSeqInfo.SeqRamAddr = AppAMPCfg.SeqStartAddr;
        AppAMPCfg.InitSeqInfo.pSeqCmd = pSeqCmd;
        AppAMPCfg.InitSeqInfo.SeqLen = SeqLen;
        /* Write command to SRAM */
        AD5940_SEQCmdWrite(AppAMPCfg.InitSeqInfo.SeqRamAddr, pSeqCmd, SeqLen);
      }
      else
        return error; /* Error */
      return AD5940ERR_OK;
    }
    
    static AD5940Err AppAMPSeqMeasureGen(void)
    {
      AD5940Err error = AD5940ERR_OK;
      uint32_t const *pSeqCmd;
      uint32_t SeqLen;
    SWMatrixCfg_Type sw_cfg;
      uint32_t WaitClks;
      ClksCalInfo_Type clks_cal;
      
      clks_cal.DataType = DATATYPE_SINC2;
      clks_cal.DataCount = 1;
      clks_cal.ADCSinc2Osr = AppAMPCfg.ADCSinc2Osr;
      clks_cal.ADCSinc3Osr = AppAMPCfg.ADCSinc3Osr;
      clks_cal.ADCAvgNum = 0;
      clks_cal.RatioSys2AdcClk = AppAMPCfg.SysClkFreq/AppAMPCfg.AdcClkFreq;
      AD5940_ClksCalculate(&clks_cal, &WaitClks);
    
      AD5940_SEQGenCtrl(bTRUE);
      AD5940_SEQGpioCtrlS(AGPIO_Pin2);
    	/* FIrstly measure Current in SE0 */
    	AD5940_ADCMuxCfgS(ADCMUXP_LPTIA0_P, ADCMUXN_VZERO0);
      AD5940_AFECtrlS(AFECTRL_ADCPWR|AFECTRL_SINC2NOTCH, bTRUE);
      AD5940_SEQGenInsert(SEQ_WAIT(16*250));    /* wait 250us */
      AD5940_AFECtrlS(AFECTRL_ADCCNV, bTRUE);   /* Start ADC convert*/
      AD5940_SEQGenInsert(SEQ_WAIT(WaitClks));  /* wait for first data ready */
      AD5940_AFECtrlS(AFECTRL_ADCPWR|AFECTRL_ADCCNV|AFECTRL_SINC2NOTCH, bFALSE);  /* Stop ADC */
    	
    	/* Now Measure DE0 current */
    	AD5940_ADCMuxCfgS(ADCMUXP_HSTIA_P, ADCMUXN_VZERO0);
    	AD5940_AFECtrlS(AFECTRL_ADCPWR|AFECTRL_SINC2NOTCH, bTRUE);
      AD5940_SEQGenInsert(SEQ_WAIT(16*250));    /* wait 250us */
      AD5940_AFECtrlS(AFECTRL_ADCCNV, bTRUE);   /* Start ADC convert*/
      AD5940_SEQGenInsert(SEQ_WAIT(WaitClks));  /* wait for first data ready */
      AD5940_AFECtrlS(AFECTRL_ADCPWR|AFECTRL_ADCCNV|AFECTRL_SINC2NOTCH, bFALSE);  /* Stop ADC */
    	sw_cfg.Dswitch = 0;
      sw_cfg.Pswitch = 0;
      sw_cfg.Nswitch = 0;
      sw_cfg.Tswitch = SWT_DE0|SWT_TRTIA; 
      AD5940_SWMatrixCfgS(&sw_cfg);
    	
      AD5940_SEQGpioCtrlS(0);
     // AD5940_EnterSleepS();/* Goto hibernate */
    	
      /* Sequence end. */
      error = AD5940_SEQGenFetchSeq(&pSeqCmd, &SeqLen);
      AD5940_SEQGenCtrl(bFALSE); /* Stop sequencer generator */
    
      if(error == AD5940ERR_OK)
      {
        AppAMPCfg.MeasureSeqInfo.SeqId = SEQID_0;
        AppAMPCfg.MeasureSeqInfo.SeqRamAddr = AppAMPCfg.InitSeqInfo.SeqRamAddr + AppAMPCfg.InitSeqInfo.SeqLen ;
        AppAMPCfg.MeasureSeqInfo.pSeqCmd = pSeqCmd;
        AppAMPCfg.MeasureSeqInfo.SeqLen = SeqLen;
        /* Write command to SRAM */
        AD5940_SEQCmdWrite(AppAMPCfg.MeasureSeqInfo.SeqRamAddr, pSeqCmd, SeqLen);
      }
      else
        return error; /* Error */
      return AD5940ERR_OK;
    }
    static AD5940Err AppAMPRtiaCal(void)
    {
    fImpPol_Type RtiaCalValue;  /* Calibration result */
      LPRTIACal_Type lprtia_cal;
      AD5940_StructInit(&lprtia_cal, sizeof(lprtia_cal));
    
      lprtia_cal.bPolarResult = bTRUE;                /* Magnitude + Phase */
      lprtia_cal.AdcClkFreq = AppAMPCfg.AdcClkFreq;
      lprtia_cal.SysClkFreq = AppAMPCfg.SysClkFreq;
      lprtia_cal.ADCSinc3Osr = ADCSINC3OSR_4;
      lprtia_cal.ADCSinc2Osr = ADCSINC2OSR_22;        /* Use SINC2 data as DFT data source */
      lprtia_cal.DftCfg.DftNum = DFTNUM_2048;         /* Maximum DFT number */
      lprtia_cal.DftCfg.DftSrc = DFTSRC_SINC2NOTCH;   /* For frequency under 12Hz, need to optimize DFT source. Use SINC3 data as DFT source */
      lprtia_cal.DftCfg.HanWinEn = bTRUE;
      lprtia_cal.fFreq = AppAMPCfg.AdcClkFreq/4/22/2048*3;  /* Sample 3 period of signal, 13.317Hz here. Do not use DC method, because it needs ADC/PGA calibrated firstly(but it's faster) */
      lprtia_cal.fRcal = AppAMPCfg.RcalVal;
      lprtia_cal.LpTiaRtia = AppAMPCfg.LptiaRtiaSel;
      lprtia_cal.LpAmpPwrMod = LPAMPPWR_NORM;
      lprtia_cal.bWithCtia = bFALSE;
      AD5940_LPRtiaCal(&lprtia_cal, &RtiaCalValue);
      AppAMPCfg.RtiaCalValue = RtiaCalValue;
     
      return AD5940ERR_OK;
    }
    
    
    static AD5940Err AppBIARtiaCal(void)
    {
      HSRTIACal_Type hsrtia_cal;
    	float RtiaCalVal[2];
      hsrtia_cal.AdcClkFreq = AppAMPCfg.AdcClkFreq;
      hsrtia_cal.ADCSinc2Osr = AppAMPCfg.ADCSinc2Osr;
      hsrtia_cal.ADCSinc3Osr = AppAMPCfg.ADCSinc3Osr;
      hsrtia_cal.bPolarResult = bTRUE; /* We need magnitude and phase here */
      hsrtia_cal.DftCfg.DftNum = DFTNUM_8192;
      hsrtia_cal.DftCfg.DftSrc = DFTSRC_SINC2NOTCH;
      hsrtia_cal.DftCfg.HanWinEn = bTRUE;
      hsrtia_cal.fRcal= AppAMPCfg.RcalVal;
      hsrtia_cal.HsTiaCfg.DiodeClose = bFALSE;
      hsrtia_cal.HsTiaCfg.HstiaBias = HSTIABIAS_1P1;
      hsrtia_cal.HsTiaCfg.HstiaCtia = 32;
      hsrtia_cal.HsTiaCfg.HstiaDeRload = HSTIADERLOAD_OPEN;
      hsrtia_cal.HsTiaCfg.HstiaDeRtia = HSTIADERTIA_TODE;
      hsrtia_cal.HsTiaCfg.HstiaRtiaSel = AppAMPCfg.DE0Rtia;
      hsrtia_cal.SysClkFreq = AppAMPCfg.SysClkFreq;
      hsrtia_cal.fFreq = 10;
    
    
      {
        AD5940_HSRtiaCal(&hsrtia_cal, RtiaCalVal);
    		printf("RTIA: Mag:%f Ohm, Phase:%.3f\n", RtiaCalVal[0], RtiaCalVal[1]);
      }
    	AppAMPCfg.DE0RtiaCalValue.Magnitude = RtiaCalVal[0];
    	AppAMPCfg.DE0RtiaCalValue.Phase = RtiaCalVal[1];
      return AD5940ERR_OK;
    }
    
    /* This function provide application initialize.   */
    AD5940Err AppAMPInit(uint32_t *pBuffer, uint32_t BufferSize)
    {
      AD5940Err error = AD5940ERR_OK;
      SEQCfg_Type seq_cfg;
      FIFOCfg_Type fifo_cfg;
    
      if(AD5940_WakeUp(10) > 10)  /* Wakeup AFE by read register, read 10 times at most */
        return AD5940ERR_WAKEUP;  /* Wakeup Failed */
    
      /* Configure sequencer and stop it */
      seq_cfg.SeqMemSize = SEQMEMSIZE_2KB;  /* 2kB SRAM is used for sequencer, others for data FIFO */
      seq_cfg.SeqBreakEn = bFALSE;
      seq_cfg.SeqIgnoreEn = bFALSE;
      seq_cfg.SeqCntCRCClr = bTRUE;
      seq_cfg.SeqEnable = bFALSE;
      seq_cfg.SeqWrTimer = 0;
      AD5940_SEQCfg(&seq_cfg);
    
      /* Do RTIA calibration */
      if(((AppAMPCfg.ReDoRtiaCal == bTRUE) || \
          AppAMPCfg.AMPInited == bFALSE) && AppAMPCfg.ExtRtia == bFALSE)  /* Do calibration on the first initializaion */
      {
        AppAMPRtiaCal();
    		AppBIARtiaCal();
        AppAMPCfg.ReDoRtiaCal = bFALSE;
      }else
    		AppAMPCfg.RtiaCalValue.Magnitude = AppAMPCfg.ExtRtiaVal;
      
    	/* Reconfigure FIFO */
      AD5940_FIFOCtrlS(DFTSRC_SINC3, bFALSE);									/* Disable FIFO firstly */
      fifo_cfg.FIFOEn = bTRUE;
      fifo_cfg.FIFOMode = FIFOMODE_FIFO;
      fifo_cfg.FIFOSize = FIFOSIZE_4KB;                       /* 4kB for FIFO, The reset 2kB for sequencer */
      fifo_cfg.FIFOSrc = AppAMPCfg.DataFifoSrc;
      fifo_cfg.FIFOThresh = AppAMPCfg.FifoThresh;              
      AD5940_FIFOCfg(&fifo_cfg);
    
      AD5940_INTCClrFlag(AFEINTSRC_ALLINT);
      
      /* Start sequence generator */
      /* Initialize sequencer generator */
      if((AppAMPCfg.AMPInited == bFALSE)||\
           (AppAMPCfg.bParaChanged == bTRUE))
      {
        if(pBuffer == 0)  return AD5940ERR_PARA;
        if(BufferSize == 0) return AD5940ERR_PARA;   
        AD5940_SEQGenInit(pBuffer, BufferSize);
    
        /* Generate initialize sequence */
        error = AppAMPSeqCfgGen(); /* Application initialization sequence using either MCU or sequencer */
        if(error != AD5940ERR_OK) return error;
    
        /* Generate measurement sequence */
        error = AppAMPSeqMeasureGen();
        if(error != AD5940ERR_OK) return error;
    
        AppAMPCfg.bParaChanged = bFALSE; /* Clear this flag as we already implemented the new configuration */
      }
      /* Initialization sequencer  */
      AppAMPCfg.InitSeqInfo.WriteSRAM = bFALSE;
      AD5940_SEQInfoCfg(&AppAMPCfg.InitSeqInfo);
      seq_cfg.SeqEnable = bTRUE;
      AD5940_SEQCfg(&seq_cfg);  /* Enable sequencer */
      AD5940_SEQMmrTrig(AppAMPCfg.InitSeqInfo.SeqId);
      while(AD5940_INTCTestFlag(AFEINTC_1, AFEINTSRC_ENDSEQ) == bFALSE);
      
      /* Measurement sequence  */
      AppAMPCfg.MeasureSeqInfo.WriteSRAM = bFALSE;
      AD5940_SEQInfoCfg(&AppAMPCfg.MeasureSeqInfo);
    
    //  seq_cfg.SeqEnable = bTRUE;
    //  AD5940_SEQCfg(&seq_cfg);  /* Enable sequencer, and wait for trigger */
    	AD5940_SEQCtrlS(bTRUE);  /* Enable sequencer, and wait for trigger. It's disabled in initialization sequence */
      AD5940_ClrMCUIntFlag();   /* Clear interrupt flag generated before */
    
      AD5940_AFEPwrBW(AppAMPCfg.PwrMod, AFEBW_250KHZ);
      AppAMPCfg.AMPInited = bTRUE;  /* AMP application has been initialized. */
      return AD5940ERR_OK;
    }
    
    /* Modify registers when AFE wakeup */
    static AD5940Err AppAMPRegModify(int32_t * const pData, uint32_t *pDataCount)
    {
      if(AppAMPCfg.NumOfData > 0)
      {
        AppAMPCfg.FifoDataCount += *pDataCount/4;
        if(AppAMPCfg.FifoDataCount >= AppAMPCfg.NumOfData)
        {
          AD5940_WUPTCtrl(bFALSE);
          return AD5940ERR_OK;
        }
      }
      if(AppAMPCfg.StopRequired == bTRUE)
      {
        AD5940_WUPTCtrl(bFALSE);
        return AD5940ERR_OK;
      }
      
      return AD5940ERR_OK;
    }
    
    /* Depending on the data type, do appropriate data pre-process before return back to controller */
    static AD5940Err AppAMPDataProcess(int32_t * const pData, uint32_t *pDataCount)
    {
      uint32_t i, datacount;
      datacount = *pDataCount;
      float *pOut = (float *)pData;
      for(i=0;i<datacount/2;i+=2)
      {
        pData[i] &= 0xffff;
    		pData[i+1] &= 0xffff;
    		
    		/*Print current iin uA */
    		printf("SE0: %f uA, DE0: %f uA\n", AppAMPCalcCurrent(pData[i], AppAMPCfg.RtiaCalValue),  AppAMPCalcCurrent(pData[i+1], AppAMPCfg.DE0RtiaCalValue));
      //  pOut[i] = AppAMPCalcCurrent(pData[i]);
      }
      return AD5940ERR_OK;
    }
    
    /**
    
    */
    AD5940Err AppAMPISR(void *pBuff, uint32_t *pCount)
    {
      uint32_t FifoCnt;
      if(AD5940_WakeUp(10) > 10)  /* Wakeup AFE by read register, read 10 times at most */
        return AD5940ERR_WAKEUP;  /* Wakeup Failed */
      AD5940_SleepKeyCtrlS(SLPKEY_LOCK);
    	
      *pCount = 0;  
      if(AD5940_INTCTestFlag(AFEINTC_0, AFEINTSRC_DATAFIFOTHRESH) == bTRUE)
      {
        FifoCnt = AD5940_FIFOGetCnt();
        AD5940_FIFORd((uint32_t *)pBuff, FifoCnt);
        AD5940_INTCClrFlag(AFEINTSRC_DATAFIFOTHRESH);
        AppAMPRegModify(pBuff, &FifoCnt);   /* If there is need to do AFE re-configure, do it here when AFE is in active state */
    		AD5940_SleepKeyCtrlS(SLPKEY_UNLOCK); 
        //AD5940_EnterSleepS();  /* Manually put AFE back to hibernate mode. This operation only takes effect when register value is ACTIVE previously */
    
        /* Process data */ 
        AppAMPDataProcess((int32_t*)pBuff,&FifoCnt); 
        *pCount = FifoCnt;
        return 0;
      }
      
      return 0;
    } 
    
    
    /* Calculate current in uA */
    float AppAMPCalcCurrent(uint32_t ADCcode, fImpPol_Type CalVal)
    {
      float fCurrent, fVoltage = 0.0;
      fVoltage = AD5940_ADCCode2Volt(ADCcode, AppAMPCfg.ADCPgaGain, 1.82);
      fCurrent = fVoltage/CalVal.Magnitude;
      
      return -fCurrent*1000000;
    }
    

    /*!
     *****************************************************************************
     @file:    Amperometric.h
     @author:  $Author: mlambe $
     @brief:   Amperometric measurement header file.
     @version: $Revision: 766 $
     @date:    $Date: 2018-03-21 14:09:35 +0100 (Wed, 21 Mar 2018) $
     -----------------------------------------------------------------------------
    
    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.
    
    *****************************************************************************/
    #ifndef _AMPEROMETRIC_H_
    #define _AMPEROMETRIC_H_
    #include "AD5940.H"
    #include "stdio.h"
    #include "string.h"
    #include "math.h"
    
    #define DAC12BITVOLT_1LSB   (2200.0f/4095)  //mV
    #define DAC6BITVOLT_1LSB    (DAC12BITVOLT_1LSB*64)  //mV
    /* 
      Note: this example will use SEQID_0 as measurement sequence, and use SEQID_1 as init sequence. 
      SEQID_3 is used for calibration.
    */
    
    typedef struct
    {
    /* Common configurations for all kinds of Application. */
      BoolFlag bParaChanged;        /* Indicate to generate sequence again. It's auto cleared by AppAMPInit */
      uint32_t SeqStartAddr;        /* Initialaztion sequence start address in SRAM of AD5940  */
      uint32_t MaxSeqLen;           /* Limit the maximum sequence.   */
      uint32_t SeqStartAddrCal;     /* Measurement sequence start address in SRAM of AD5940 */
      uint32_t MaxSeqLenCal;
      
    /* Application related parameters */ 
      BoolFlag ReDoRtiaCal;         /* Set this flag to bTRUE when there is need to do calibration. */
      float SysClkFreq;             /* The real frequency of system clock */
      float WuptClkFreq;            /* The clock frequency of Wakeup Timer in Hz. Typically it's 32kHz. Leave it here in case we calibrate clock in software method */
      float AdcClkFreq;             /* The real frequency of ADC clock */
      uint32_t FifoThresh;           /* FIFO threshold. Should be N*4 */   
      float AmpODR;                 /* in Hz. ODR decides the period of WakeupTimer who will trigger sequencer periodically.*/
      int32_t NumOfData;            /* By default it's '-1'. If you want the engine stops after get NumofData, then set the value here. Otherwise, set it to '-1' which means never stop. */
      float RcalVal;                /* Rcal value in Ohm */
      float ADCRefVolt;               /* Measured 1.82 V reference*/
      uint32_t PwrMod;              /* Control Chip power mode(LP/HP) */
      uint32_t ADCPgaGain;          /* PGA Gain select from GNPGA_1, GNPGA_1_5, GNPGA_2, GNPGA_4, GNPGA_9 !!! We must ensure signal is in range of +-1.5V which is limited by ADC input stage */   
      uint8_t ADCSinc3Osr;          /* SINC3 OSR selection. ADCSINC3OSR_2, ADCSINC3OSR_4 */
      uint8_t ADCSinc2Osr;          /* SINC2 OSR selection. ADCSINC2OSR_22...ADCSINC2OSR_1333 */
      uint32_t DataFifoSrc;         /* DataFIFO source. FIFOSRC_SINC3, FIFOSRC_DFT, FIFOSRC_SINC2NOTCH, FIFOSRC_VAR, FIFOSRC_MEAN*/
      uint32_t LptiaRtiaSel;        /* Use internal RTIA, select from RTIA_INT_200, RTIA_INT_1K, RTIA_INT_5K, RTIA_INT_10K, RTIA_INT_20K, RTIA_INT_40K, RTIA_INT_80K, RTIA_INT_160K */
      uint32_t LpTiaRf;             /* Rfilter select */
      uint32_t LpTiaRl;             /* SE0 Rload select */
    	
    	uint32_t DE0Rtia;             /* Rfilter select */
      uint32_t DE0Rload;             /* SE0 Rload select */
      
    	fImpPol_Type RtiaCalValue;           /* Calibrated Rtia value */
    	fImpPol_Type DE0RtiaCalValue;	/* Calibrated RTIA on DE0 input*/
    	
      float Vzero;                  /* Voltage on SE0 pin and Vzero, optimumly 1100mV*/
      float SensorBias;             /* Sensor bias voltage = VRE0 - VSE0 */
      BoolFlag ExtRtia;             /* Use internal or external Rtia */
      float ExtRtiaVal;							/* External Rtia value if using one */
      BoolFlag AMPInited;           /* If the program run firstly, generated sequence commands */
      SEQInfo_Type InitSeqInfo;
      SEQInfo_Type MeasureSeqInfo;
      BoolFlag StopRequired;          /* After FIFO is ready, stop the measurement sequence */
      uint32_t FifoDataCount;         /* Count how many times impedance have been measured */
    /* End */
    }AppAMPCfg_Type;
    
    /**
     * int32_t type Impedance result in Cartesian coordinate 
    */
    typedef struct
    {
      float Current;
      float Voltage;
    }fAmpRes_Type;
    
    
    
    #define AMPCTRL_START          0
    #define AMPCTRL_STOPNOW        1
    #define AMPCTRL_STOPSYNC       2
    #define AMPCTRL_SHUTDOWN       4   /* Note: shutdown here means turn off everything and put AFE to hibernate mode. The word 'SHUT DOWN' is only used here. */
    
    AD5940Err AppAMPGetCfg(void *pCfg);
    AD5940Err AppAMPInit(uint32_t *pBuffer, uint32_t BufferSize);
    AD5940Err AppAMPISR(void *pBuff, uint32_t *pCount);
    AD5940Err AppAMPCtrl(int32_t AmpCtrl, void *pPara);
    float AppAMPCalcVoltage(uint32_t ADCcode);
    float AppAMPCalcCurrent(uint32_t ADCcode, fImpPol_Type CalVal);
    
    #endif
    

  • Hi  , I have changed the AIN0 pin to DE0 pin to suit the configuration in your code.

    Unfortunately, the results are totally off as shown below. I am trying to debug your code.

    This AD594x!
    Note: Current Silicon is S2
    AD5940LIB Version:v0.2.1
    Freq:34134.035156
    RTIA: Mag:231.085083 Ohm, Phase:0.000
    index:0, Current:56.337227uA
    index:0, Current:-0.000000uA
    index:0, Current:-0.220067uA
    index:0, Current:3323862712320.000000uA
    index:0, Current:0.000000uA
    index:0, Current:3323862712320.000000uA
    index:0, Current:0.000000uA
    index:0, Current:3323862712320.000000uA

    Please feel free to comment on this.

    Actually, I tried using DE0 pin to replace AINx pins before. The difference between measured currents between LPTIA and HSTIA were still quite big, just like using the AINx pins. So I don't think switching to DE0 pin will help in this case.

  • Hi  , may I know if the code provided by you above has been verified on evaluation board or hardware? I can't make it work at all and the current outputs are always gibberish and 0.

  • Hi  , I managed to get accurate measurement for LPPA-LPTIA loop. I have changed the ADC mux configurations from

    dsp_cfg.ADCBaseCfg.ADCMuxN = ADCMUXN_VZERO0;
    dsp_cfg.ADCBaseCfg.ADCMuxP = ADCMUXP_AIN4;

    to

    dsp_cfg.ADCBaseCfg.ADCMuxN = ADCMUXN_LPTIA0_N;
    dsp_cfg.ADCBaseCfg.ADCMuxP = ADCMUXP_LPTIA0_P;

    This means that LPF at the AIN4 causes the inaccurate results for the previous measurement. After configuring the ADC to measure directly from the LPTIA, the bias voltages and measured currents are quite accurate now:

    LPPA to LPTIA, Dummy Cell: 1kohm (1%) resistor, RTIA = LPTIARTIA_1K,  Rload = LPTIARLOAD_SHORT, dsp_cfg.ADCBaseCfg.ADCMuxN = ADCMUXN_LPTIA0_N, dsp_cfg.ADCBaseCfg.ADCMuxP = ADCMUXP_LPTIA0_P (*Measured using Pro's Kit MT-1280 Multimeter)

    SensorBias

    100 mV

    300 mV

    500 mV

    1000 mV

    V_CE0/RE0 (Shorted)*

    1193 mV

    1392 mV

    1592 mV

    2093 mV

    V_SE0*

    1094 mV

    1093 mV

    1093 mV

    1177 mV

    Actual SensorBias*

    99 mV

    299 mV

    498 mV

    915 mV

    Measured Current

    100.692886uA

    301.924316uA

    503.911804uA

    923.663696uA

    However, the accuracy for LPPA-HSTIA route is still quite off as shown below:

    LPPA to HSTIA, Dummy Cell: 1kohm (1%) resistor, RTIA = HSTIARTIA_1K,  Rload = N/A, dsp_cfg.ADCBaseCfg.ADCMuxN = ADCMUXN_HSTIA_N, dsp_cfg.ADCBaseCfg.ADCMuxP = ADCMUXP_HSTIA_P (*Measured using Pro's Kit MT-1280 Multimeter)

    SensorBias

    100 mV

    300 mV

    500 mV

    1000 mV

    V_CE0/RE0 (Shorted)*

    1192 mV

    1392 mV

    1592 mV

    2092 mV

    V_AIN0*

    1099 mV

    1107 mV

    1117 mV

    1149 mV

    Actual SensorBias*

    93 mV

    284 mV

    474 mV

    942 mV

    Measured Current

    93.883163 uA

    283.418427 uA

    473.088135uA

    940.321350uA

    The ADC works very fine, but the voltage at AIN0 pin is slightly lower than the required value, which causes the actual bias voltage to be lower than the desired bias voltage. Could you advise if this is due to internal resistance or any other factor? 

    Thank you.