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?

  • Hi, 

    We will contact the product apps to help you on this. We'll get back to you as soon as we can. 

    Thanks,

    Jellenie

  • Jellenie, when do you estimate we can hear back from the AD apps team? I am blocked on this issue. Thanks

  • Hi,

        AppAMPCtrl(AMPCTRL_SHUTDOWN)

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

  • Thanks for your response Akila. What's the best way to enter into the Sleep state and run another measurement upon a user input (i.e. button press)? In my code snippet above, I do jump (see "goto restart" line) to the beginning of the main function and I thought it would reset and re-init all the necessary hardware subsystems and registers.

  • Akila,

    I am not asking about how to do button interrupt. Sorry, if it was not clear. The issue is what's stated in the title of this question. Let me rephrase it here.

    - How do I take multiple measurements, with AD5940 sleeping between each measurement to save battery life?

    The issue is that, as you said, if SHUTDOWN shuts off everything, shouldn't jumping to the beginning of the main function after the SHUTDOWN reset AD5940 and make AMP measurement work with valid interrupts? From my experiment, that does not work (see my code snippet)

    - Why does it not work?

    - How can I get subsequent measurement to work following the first successful measurement, without power cycling the entire system?

  • Akila - I'm having this same problem. Is it possible to answer montecarlo's question?

  • 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;
    }

  • 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