Differential pulse voltammetry on AD5941

Hello forum,

I'm working on a simple potentiostat utilizing the AD5941 chip. I have searched and used the official github repository with code examples for this chip. Im using the Nucleo-F411RE board so it was not a problem. It was very helpful to test the capabilities of this chip. As a hardware engineer I'm not that good in C programming but I was able to migrate the source code to STM32CubeIDE and then modify the source code to print the potential (Voltage) according the ADC generated by the RampDacRegUpdate() function in the Ramp (Cyclic voltammetry) example. Happy with this result I moved to the squarewave voltammetry. This example is also working fine with my hardware however my ultimate goal is to modify it to differential pulse voltammetry.

In my understanding the difference in squarewave voltammetry and differential pulse voltammetry is basically the same, and the difference is in the option of changing the duty cycle of the squarewave and calculating the difference between measured current points. However, I quickly found out that using the sequencer in order to change the voltage values of the DAC and also placing the measurement points accordingly cannot be done. Because the squarewave is not 50/50 duty, the delay value for the DAC sample measure cannot be the same. It has to change also according the duty cycle.

Because the sequencer has 4 sequences available and one is always used as the ending sequence, we can only use 3 sequences for the DAC and ADC update. Two for DAC update and one for ADC however the wakeup timer is also bound to the same 4 sequences. So two wakeup timers for DAC update and only one for ADC. Hence I cannot move the time of sampling of the two points in the waveform period independently. They are always equally positioned after the change of the potential. 

I'm still hoping it can be done and I'm seeking help on this forum. Because the AD5941 and ADuCM355 share the same AFE and the ADuCM355 is known to support the differential pulse voltammetry I'm positive it can be done. I just need a hint....


Im adding an image to show what ima aiming for.

Thank you.

imag size
[edited by: RobertSz at 1:51 PM (GMT -4) on 5 Oct 2021]
  • Hi,

    By modifying the lines in AppSWVCtrl() in SquareWaveVoltammetry.c as below:

    wupt_cfg.SeqxWakeupTime[SEQID_0] = (uint32_t)(AppSWVCfg.LFOSCClkFreq*((1/AppSWVCfg.Frequency*800) - AppSWVCfg.SampleDelay)/1000.0f) - 4;
    wupt_cfg.SeqxSleepTime[SEQID_1] = wupt_cfg.SeqxSleepTime[SEQID_0];
    wupt_cfg.SeqxWakeupTime[SEQID_1] = (uint32_t)(AppSWVCfg.LFOSCClkFreq*((1/AppSWVCfg.Frequency*200) - AppSWVCfg.SampleDelay)/1000.0f) - 4;//wupt_cfg.SeqxWakeupTime[SEQID_0];

    Duty cycle of the square wave can be changed:

  • Hi Akila,

    thank you for the reply. However, I already know how to change the duty cycle of the generated signal. The problem is how to manage the ADC to sample the signal correctly. Right now the sampling is made at a constant time interval after each change of the voltage. But because I now have a signal which has different duty cycle I need to sample the waveform according the duty cycle. Lets say I have a signal with 10ms period and 0.8 (or 80%) duty. Therefore, I have to sample the signal firstly after 7 (1ms before change) and secondly sample after 1ms (again 1 ms before change). And that is the problem I need to figure out. I need to change AppSWVCfg.SampleDelay in

    wupt_cfg.SeqxWakeupTime[SEQID_2] = (uint32_t)(AppSWVCfg.LFOSCClkFreq*AppSWVCfg.SampleDelay/1000.0f)- 4 -2;

    according to the duty cycle for each half-period of the signal. Can it be even done ? Or I need to make a solution without using the sequencer ? 

    Thank you very much !!

  • Hi,

    You may

    1) add a line in AppSWVSeqADCCtrlGen() function as below:

    AD5940_SEQGenFetchSeq(NULL, &AppSWVCfg.SeqWaitAddr[0]); /* Record the start address of the next command. */
    AD5940_SEQGenInsert(SEQ_WAIT(16*100)); /* wait 250us for reference power up */
    AD5940_AFECtrlS(AFECTRL_ADCCNV, bTRUE); /* Start ADC convert and DFT */

    2) change AppSWVRegModify() function as:

    static int32_t AppSWVRegModify(int32_t * const pData, uint32_t *pDataCount)

    uint8_t Duty = 4;                              //Duty =4 for 4:1 duty cycle ratio
    uint32_t SeqCmdBuff[32];
    uint32_t SRAMAddr = 0;
    static BoolFlag seqflag = bTRUE;

    if(AppSWVCfg.StopRequired == bTRUE)
    return AD5940ERR_OK;

    if(seqflag == bFALSE)
    SRAMAddr = AppSWVCfg.ADCSeqInfo.SeqRamAddr + AppSWVCfg.SeqWaitAddr[0];
    SeqCmdBuff[0] =SEQ_WAIT(16*100);
    AD5940_SEQCmdWrite(SRAMAddr, SeqCmdBuff, 1);
    SRAMAddr = AppSWVCfg.ADCSeqInfo.SeqRamAddr + AppSWVCfg.SeqWaitAddr[0];
    SeqCmdBuff[0] =SEQ_WAIT(16*100*Duty);                      
    AD5940_SEQCmdWrite(SRAMAddr, SeqCmdBuff, 1);

    seqflag = seqflag?bFALSE:bTRUE;
    return AD5940ERR_OK;

    3) and add in AppSWVCfg_Type definition in SquareWaveVoltammetry.h:

    uint32_t SeqWaitAddr[2]; 

  • Hi Akila,

    Thank you for the reply. However, the function AppSWVRegModify is only called after the FIFO treshhold is reached in AppSWVISR. I dont see how it can resolve the issue. I have done the modifications and the issue remains. 

  • AppSWVRegModify() function is accessed after each measuremnt.

    In addition, you may increase the sample delay and check.

    May I know how you are verifying?