Post Go back to editing

AD5940_Amperometric example hangs when it's shutdown and restarts

On my custom board, I am seeing a system hang (interrupt does not trigger any more) when another AMP measurement is attempted following the first successful amp measurement. I modified the AD5940_Amperometric example code and was able to reproduce the same issue on my EVAL-AD5941ELCZ. I built it with KEIL uVision 5.

/examples/AD5940_Amperometric/AD5940Main.c

void AD5940_Main(void)
{
  uint32_t temp;
  uint32_t count;

restart:
  count = 0;

  AD5940PlatformCfg();
  AD5940AMPStructInit(); /* Configure your parameters in this function */
  AppAMPInit(AppBuff, APPBUFF_SIZE);    /* Initialize AMP application. Provide a buffer, which is used to store sequencer commands */
  AppAMPCtrl(AMPCTRL_START, 0);         /* Control AMP measurement to start. Second parameter has no meaning with this command. */

  while(1)
  {
    /* Check if interrupt flag which will be set when interrupt occurred. */
    if(AD5940_GetMCUIntFlag())
    {
      AD5940_ClrMCUIntFlag(); /* Clear this flag */
      temp = APPBUFF_SIZE;
      AppAMPISR(AppBuff, &temp); /* Deal with it and provide a buffer to store data we got */
      AMPShowResult((float*)AppBuff, temp); /* Show the results to UART */
      count++;
    }
    if (count == 10) {
      AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);
      goto restart;
    }
  }
}

Any idea how to debug this?

Parents
  • Hi,

        AppAMPCtrl(AMPCTRL_SHUTDOWN)

    turns OFF everything. Hence the sequences will not be run, and interrupts will not be triggered.

  • I tried the same restart experiment with AD5940 BIA example. It restarts correctly. So I think there must be some bug in the Amperometric portion of the SDK.

    void AD5940_Main(void)
    {
      static uint32_t IntCount;
      uint32_t temp;
    
    restart:
      AD5940PlatformCfg();
    
      AD5940BIAStructInit(); /* Configure your parameters in this function */
    
      AppBIAInit(AppBuff, APPBUFF_SIZE);    /* Initialize BIA application. Provide a buffer, which is used to store sequencer commands */
      AppBIACtrl(BIACTRL_START, 0);         /* Control BIA measurement to start. Second parameter has no meaning with this command. */
    
      while(1)
      {
        /* Check if interrupt flag which will be set when interrupt occurred. */
        if(AD5940_GetMCUIntFlag())
        {
          IntCount++;
          AD5940_ClrMCUIntFlag(); /* Clear this flag */
          temp = APPBUFF_SIZE;
          AppBIAISR(AppBuff, &temp); /* Deal with it and provide a buffer to store data we got */
          BIAShowResult(AppBuff, temp); /* Show the results to UART */
    
          if(IntCount == 240)
          {
            IntCount = 0;
            AppBIACtrl(BIACTRL_SHUTDOWN, 0);
            goto restart;
          }
        }
      }
    }

  • Hi,

    you may modify as below:

    void AD5940_Main(void)
    {
    uint32_t temp;
    uint32_t count;

    //restart:
    //count = 0;

    AD5940PlatformCfg();
    AD5940AMPStructInit(); /* Configure your parameters in this function */
    AppAMPInit(AppBuff, APPBUFF_SIZE); /* Initialize AMP application. Provide a buffer, which is used to store sequencer commands */
    AppAMPCtrl(AMPCTRL_START, 0); /* Control AMP measurement to start. Second parameter has no meaning with this command. */

    while(1)
    {
    /* Check if interrupt flag which will be set when interrupt occurred. */
    if(AD5940_GetMCUIntFlag())
    {
    AD5940_ClrMCUIntFlag(); /* Clear this flag */
    temp = APPBUFF_SIZE;
    AppAMPISR(AppBuff, &temp); /* Deal with it and provide a buffer to store data we got */
    AMPShowResult((float*)AppBuff, temp); /* Show the results to UART */
    count++;
    }
    if (count == 10) {
    AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);

    AppAMPCtrl(AMPCTRL_START, 0);
    //goto restart;
    }
    }
    }

    and 

    modify 

    static AD5940Err AppAMPSeqMeasureGen(void)
    {
    AD5940Err error = AD5940ERR_OK;
    uint32_t const *pSeqCmd;
    uint32_t SeqLen;

    uint32_t WaitClks;
    ClksCalInfo_Type clks_cal;

    AFERefCfg_Type aferef_cfg;

    LPLoopCfg_Type lp_loop;

    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);
    WaitClks += 15;
    AD5940_SEQGenCtrl(bTRUE);
    AD5940_SEQGpioCtrlS(AGPIO_Pin2);


    /*add code to reinitialize low power loop*/

    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);

    lp_loop.LpDacCfg.PowerEn = bTRUE;

    lp_loop.LpAmpCfg.LpPaPwrEn = bTRUE;
    lp_loop.LpAmpCfg.LpTiaPwrEn = bTRUE;

     AD5940_LPLoopCfgS(&lp_loop);

    /****************************************************************/
    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 */
    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;
    }

Reply
  • Hi,

    you may modify as below:

    void AD5940_Main(void)
    {
    uint32_t temp;
    uint32_t count;

    //restart:
    //count = 0;

    AD5940PlatformCfg();
    AD5940AMPStructInit(); /* Configure your parameters in this function */
    AppAMPInit(AppBuff, APPBUFF_SIZE); /* Initialize AMP application. Provide a buffer, which is used to store sequencer commands */
    AppAMPCtrl(AMPCTRL_START, 0); /* Control AMP measurement to start. Second parameter has no meaning with this command. */

    while(1)
    {
    /* Check if interrupt flag which will be set when interrupt occurred. */
    if(AD5940_GetMCUIntFlag())
    {
    AD5940_ClrMCUIntFlag(); /* Clear this flag */
    temp = APPBUFF_SIZE;
    AppAMPISR(AppBuff, &temp); /* Deal with it and provide a buffer to store data we got */
    AMPShowResult((float*)AppBuff, temp); /* Show the results to UART */
    count++;
    }
    if (count == 10) {
    AppAMPCtrl(AMPCTRL_SHUTDOWN, 0);

    AppAMPCtrl(AMPCTRL_START, 0);
    //goto restart;
    }
    }
    }

    and 

    modify 

    static AD5940Err AppAMPSeqMeasureGen(void)
    {
    AD5940Err error = AD5940ERR_OK;
    uint32_t const *pSeqCmd;
    uint32_t SeqLen;

    uint32_t WaitClks;
    ClksCalInfo_Type clks_cal;

    AFERefCfg_Type aferef_cfg;

    LPLoopCfg_Type lp_loop;

    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);
    WaitClks += 15;
    AD5940_SEQGenCtrl(bTRUE);
    AD5940_SEQGpioCtrlS(AGPIO_Pin2);


    /*add code to reinitialize low power loop*/

    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);

    lp_loop.LpDacCfg.PowerEn = bTRUE;

    lp_loop.LpAmpCfg.LpPaPwrEn = bTRUE;
    lp_loop.LpAmpCfg.LpTiaPwrEn = bTRUE;

     AD5940_LPLoopCfgS(&lp_loop);

    /****************************************************************/
    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 */
    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;
    }

Children
  • Hi Akila,

    I have been following this thread and am experiencing the same issue as montecarlo.

    After inserting this init code modification into the sequence measurement gen loop as you suggested, the voltage bias no longer is maintained at the expected value.

    More specifically, on the first call of AppAMPCtrl(AMPCTRL_START, 0); the voltage seems to pulse and return to 0V, and I measure a decaying current signal to 0. I have confirmed the interrupt still triggers and returns the measurement. Removing the reinitialization code from AppAMPSeqMeasureGen fixes this issue, though the shutdown/restart issue remains with and without the suggested change.

    Regarding the issue in the thread, when calling AMPCTRL_START a second time after AMPCTRL_SHUTDOWN, the voltage bias stays at 0V and the interrupt does not trigger. Trying to power-on the LP Amplifier makes sense, though it did not seem to work for me copying your suggestion.

    If this worked for your devkit or board please let me know. I have a custom PCB and am reading the data and packets through a phone, but I am using test code that is nearly identical to the example.

    If there are more suggestions, I am happy to try them so we can resolve this.

    Best,

    Jmstine

  • Hi Jmstine,

    See the line 24 of Amperometric.c in the AD5940_Amperometric example. The AppAMPCfg structure is only initialized at its declaration. I fixed this issue by implementing my own AMPCfg structue reset function and calling it at the beginning of AppAMPInit() function. The example code is not written to start/stop dynamically. Hope it helps.