Post Go back to editing

Getting wrong data occasionally with AD7780

Hi,

For reading from AD7780 I'm waiting for DOUT/~RDY pin to go low and after about 100us reading 32-bit. Then by checking eight status bit if equals 0x0D (according to filter and gain that is set) (which indicated that there is no error with communication and the conversion is completed), using 24-bit output for my application.

By this method everything is ok and the result is correct but two things occur that sometimes make the output wrong:

1)  In some reading, the status bit is correct but the data output is 0xFFFFFF or 0x000000. This occurs once in "about" every 10 conversions.

2)  Worse than first, In some reading the data output  is wrong (far from what it should be). This occurs occasionally and too late after about every thousand conversions.

I can ignore the first one by filtering the 0x0 or 0xFFFFFF data because my input never is zero or full-scale (may be a bad practice because this assumption seems to be not absolutely true) but the second problem is unacceptable.

STM32F1xx is used for reading from adc. First I used SPI peripheral of STM3F1 for reading data from adc. But after that I use a basic and simple code for reading data to ensure there is no problem in my communication with ADC. This simple code makes the condition better and the wrong data is occurred at a lower frequency. Nevertheless the problem with wrong data is remained and is not solved completely.

Edge detection of DOUT/~RDY pin for getting low and reading operation all is done in a 100us-period timer.

This is my code:

/*check if timer 1 interrupt(100us) is occured or not*/
if(htim->Instance == TIM1)
{
   /*check if RDYLow flag is set*/
if(RDYLow == 1)
{
  /*toggle SCLK pin 64 times (for 32-bit reading)*/
  /*clock cylce is 200us*/
if(bitNum < 64)
{
    HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
   /*read pin in rising edge of sclk*/
   if(bitNum % 2 != 0)
   {
      readPin = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6);
      a = bitNum/2;
      adc8 [a] = readPin ;
    }
   bitNum++;
}
else
{
        /*32-bit reading complete*/
      bitNum = 0;
      adcCnt++;
     /*check status byte to be 0x0D*/
    if(adc8[31] == 1 && adc8[30] == 0 && adc8[29] == 1 && adc8[28] == 1) /*0x00001101*/
    {
       adc32 = 0;
      /*shift the seperated 24-bit data into a 32-bit integer*/
      for(b = 0;b < 24;b++)
      adc32 += (uint32_t)( adc8[b] << (23-b));
     /*check if data is not 0xFFFFFF or 0x0*/
    if(adc32 != 0xFFFFFF && adc32 != 0)
    {
      temp32 = adc32 & 0x7FFFFF;
      adcValidBit = (temp32 >> 9);
      /*convert adc value to real pressure*/
      adcVinput = (5.0f * adcValidBit)/powf(2,14);
    if((adc32 >> 23) == 1)
      pressTemp = adcVinput * (100.0f/(4.07f-0.792f)) - 24.16f;/*hardware: .792v --> 0bar,4.07v--> 100bar*/
    else
      pressTemp = -1.0f * adcVinput * (100.0f/(4.07f-0.792f)) - 24.16f;/*hardware: .792v --> 0bar,4.07v--> 100bar*/;
   /*calibration*/
     pressTempCal = pressGain * pressTemp + pressOff;
     pressure = pressTempCal - pressZero;
}
}
    RDYLow = 0;
    adc8[31] = 0;
    adc8[30] = 0;
    adc8[29] = 0;
    adc8[28] = 0;
}
}
one_ms_counter3++;
/*RDY pin edge detection*/
if(HAL_GPIO_ReadPin(adcStart_GPIO_Port,adcStart_Pin) == 0)
{
    if(adcStatus == 1)
    {
     adcStatus = 0;
      adcIntCnt++;
      one_ms_counter3 = 0;
     }
}
else
{
    if(adcStatus == 0)
      adcStatus = 1;
}
/* if RDY level is low set RDYLow flag for reading*/
if(adcStatus == 0)
{
    one_ms_counter2 = 0;
     RDYLow = 1;
}

}

ADC input and reference voltage is stable in my test and I don't think the problem is due to hardware design (good hardware design according to considerations).

Please help me with this problem. 

Thanks.

Parents
  • Hi, 

    May I know what is your selected ODR? And are you using an actual sensor during the test? or you are just using a stable source? Might be good if you can just try to perform a noise test for example just short the inputs and try to perform measurements. Is ther also an instance that it still go full scale even if the inputs are just shorted? 

    I know you might be pretty sure that the hardware is fine but can you share the schematic so I can have a full picture of the setup? 

    Can you clarify again the interrupt for? for example you have mentioned that you are monitoring first the RDY and when it goes low you have 100us to read all the data register is that correct? From the code I think you have a timer condition before checking the RDY. So are you polling the RDY every 100us? or is it continuously monitoring? I’m not a coder but I am trying to understand how this interrupt works in the above code.

    Thanks,

    Jellenie

  • Hi,

    Thanks for your reply. 

    The selected ODR is 16.7Hz. In real application a pressure sensor with 4-20 mA  output is used. But for testing a 4-20mA current source (with acceptable stability) is used. I performed a noise test after your recommendation. I shorted circuit the inputs but all I mentioned about my problems remained. Sometimes (about every ten conversions) the adc output goes (negative or positive) full scale(problem 1)  and at a lower speed the output goes far from zero(problem 2)!! (not full-scale a value somewhere between zero and full-scale).

    Yes, I use a  timer interrupt (with 100us period) for monitoring the RDY state. Whenever RDY goes low, after  100us ( in next timer interrupt) I generate the clock by toggling the SCLK every 100us. So after 64 interrupt ( 32 clock with 200us period), 32-bit register is read form adc as data output. So timer interrupt is used both for RDY state monitoring and for SCLK generation for 32-bit adc reading.

    Here is the schematic link for more information about hardware design.

    https://drive.google.com/file/d/19eJ9bF2Iu4pFGrQn41GmAEY5ruh5m0x7/view?usp=sharing

    I hope I was able to precisely answer your questions.

    Thanks again for your help.

  • Hi, 

    I was actually thinking if the interrupt causes the issue. Instead of having an interrupt for example. Can you explore just try a simple read mechanism without adding any interrupt. For example just monitor the DRDY and when it goes low just read the data register by applying correct number of SCLKs. You can just repeat it continuously and see if there is also an issue. 

    My thinking is to try a simple code for writing and reading the registers and when everything works fine with that then you can just add other code feature such as interrupt. 

    Thanks,

    Jellenie

Reply
  • Hi, 

    I was actually thinking if the interrupt causes the issue. Instead of having an interrupt for example. Can you explore just try a simple read mechanism without adding any interrupt. For example just monitor the DRDY and when it goes low just read the data register by applying correct number of SCLKs. You can just repeat it continuously and see if there is also an issue. 

    My thinking is to try a simple code for writing and reading the registers and when everything works fine with that then you can just add other code feature such as interrupt. 

    Thanks,

    Jellenie

Children
No Data