Post Go back to editing

High Input bias detected while using analog pins to perform open circuit potentiometry

Category: Hardware
Product Number: AD5941

Hi ADI Team,

I have tried using the AD5941 AFE to read open circuit potential of certain solutions but I have discovered that the analog pins that I am using for said measurement are heavily biased in the range of mV(using DMM)  while the voltages I am trying to measure are in the range of microvolts, and hence the analog pins are biasing said solution and I am receiving erroneous readings.

I have the requirement to measure 5 different measurements wrt to a common reference so in total I need 6 pins and I have 3 AD5941 in my custom built PCB(heavily similar to the evaluation board)

Can I know why I am observing this behavior, will greatly appreciate your efforts to help me understand said issue.

Attached schematic to one of the AFE

The code I'm using is as follows

#include "ad5940.h"
#include <stdio.h>



uint32_t adc_pin[]={ADCMUXP_AIN1,ADCMUXP_AIN2,ADCMUXP_AIN3,ADCMUXP_AIN4, ADCMUXP_VAFE1};
uint32_t gain_val[]={10,20,50,100,200,500,1000};


#define ADCPGA_GAIN_SEL   ADCPGA_1P5

static void AD5940_PGA_Calibration(void){
  AD5940Err err;
  ADCPGACal_Type pgacal;
  pgacal.AdcClkFreq = 16e6;
  pgacal.ADCSinc2Osr = ADCSINC2OSR_178;
  pgacal.ADCSinc3Osr = ADCSINC3OSR_4;
  pgacal.SysClkFreq = 16e6;
  pgacal.TimeOut10us = 1000;
  pgacal.VRef1p11 = 1.11f;
  pgacal.VRef1p82 = 1.82f;
  pgacal.PGACalType = PGACALTYPE_OFFSETGAIN;
  pgacal.ADCPga = ADCPGA_GAIN_SEL;
  err = AD5940_ADCPGACal(&pgacal);
  if(err != AD5940ERR_OK){
    Serial.println("AD5940 PGA calibration failed.");
  }
}

float getVolt(uint8_t sz=10){
  uint64_t rd=0;
  float vlt=0;
  uint8_t frq =sz;
  while(frq>0){
    if(AD5940_INTCTestFlag(AFEINTC_1,AFEINTSRC_SINC2RDY)){
      AD5940_INTCClrFlag(AFEINTSRC_SINC2RDY);
      rd = rd + AD5940_ReadAfeResult(AFERESULT_SINC2);
      frq--;
    }
  }
  vlt = (AD5940_ADCCode2Volt(rd/sz, ADCPGA_GAIN_SEL, 1.82));
  return vlt;
}


void readVal(float *rd,float* t){
    rd[4]=getVolt();
    t[4] = (((float)millis())-t[5])/1000;
}

void print_float(float* a, long m=1){
  int i=0;
  while(i<5){
    Serial.print(a[i]*m);
    if(i==4&&m==1)
    Serial.println();
    else
    Serial.print(" ");
    i++;
  }
  return;
}

void reading(){
  //float rd[5];
  //float tim[6];
  float rd[]={0,0,0,0,0};
  float tim[]={0,0,0,0,0,0};
  delay(100);
  tim[5]=((float)millis())/1000;
  while(1){
  readVal(rd,tim);
  print_float(rd,1000000);
  print_float(tim);
  //print_float(tim);
  }
}

void AD5940_Main(void)
{
  ADCBaseCfg_Type adc_base;
  ADCFilterCfg_Type adc_filter;
 
  /* Use hardware reset */
  AD5940_HWReset();

  /* Firstly call this function after reset to initialize AFE registers. */
  AD5940_Initialize();
 
  AD5940_PGA_Calibration();
  /* Configure AFE power mode and bandwidth */
  AD5940_AFEPwrBW(AFEPWR_LP, AFEBW_250KHZ);
 
  /* Initialize ADC basic function */
  AD5940_AFECtrlS(AFECTRL_DACREFPWR|AFECTRL_HSDACPWR, bTRUE); //We are going to measure DAC 1.82V reference.
  adc_base.ADCMuxP = ADCMUXP_VREF1P8DAC;
  adc_base.ADCMuxN = ADCMUXN_VSET1P1;
  adc_base.ADCPga = ADCPGA_GAIN_SEL;
  AD5940_ADCBaseCfgS(&adc_base);
 
  /* Initialize ADC filters ADCRawData-->SINC3-->SINC2+NOTCH */
  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 = bFALSE;                /* We use SINC3 filter. */  
  adc_filter.Sinc2NotchEnable = bTRUE;        /* Enable the SINC2+Notch block. You can also use function AD5940_AFECtrlS */
  AD5940_ADCFilterCfgS(&adc_filter);
  //AD5940_ADCMuxCfgS(ADCMUXP_AIN0, ADCMUXN_VSET1P1);   /* Optionally, you can change ADC MUX with this function */

  /* Enable all interrupt at Interrupt Controller 1. So we can check the interrupt flag */
  AD5940_INTCCfg(AFEINTC_1, AFEINTSRC_ALLINT, bTRUE);

  //AD5940_AFECtrlS(AFECTRL_ADCPWR|AFECTRL_SINC2NOTCH, bTRUE);
  //AD5940_AFECtrlS(AFECTRL_ADCCNV, bTRUE);
  AD5940_ADCPowerCtrlS(bTRUE);
  AD5940_ADCConvtCtrlS(bTRUE);
  AD5940_ADCMuxCfgS(adc_pin[3], ADCMUXN_AIN0);
  reading();
  AD5940_ADCMuxCfgS(adc_pin[2], ADCMUXN_AIN0);
  while(1){
    //AD5940_ADCMuxCfgS(adc_pin[4], ADCMUXN_AIN0);
    Serial.println(getVolt()*1000000);
    //delay(500);
    //AD5940_ADCMuxCfgS(adc_pin[3], ADCMUXN_AIN0);
    //Serial.println(getVolt()*1000000);
    //delay(500);
  }
}

void setup() {
  Serial.begin(115200);
  AD5940_config();
  AD5940_Main();

}

void loop() {
  // put your main code here, to run repeatedly:

}