This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADS1130 Values getting stuck

Other Parts Discussed in Thread: ADS1130, MSP430F2011

Hi 

I am having the following configuration for ADS1130. All VDD pins connected to +3.2V all analog and digital ground pins grounded. REFP = 3.2V REFN = 0(GND).

SPEED = 3.2V. PDWN = 1.

the problem.

The adc output is kind of stuck to 0x00233F95. Even if I vary the load from full scale to 0 the output doesn't change. I am using msp2011 mcu.

Below is the code for reference.

Thanks in advance

============================================================================================================================

//=========================================================================
#include  <msp430f2011.h>
#define  LOAD_CELL_ENABLE       0x10;
#define  ADC_ENABLE             0x80;
#define  DELAY_20_MS            40000;
#define  DATA_READY             (0x01) //p1.0    
#define  SCLK                   (0x08) // p1.3
//=========================================================================
// used to count number of samples taken
//static unsigned int SampleValue = 0;

// Indicates max number of samples
//static unsigned int SampleNum = 512;

// Used to store current ADCValue
long int CurrentADCValue, ADCValue;

//static unsigned int ADCOffset;

// Used to store previous ADC value
//..static unsigned long int LastADCValue;
//static unsigned int VoltageSettleCtr;
//static unsigned int int_val_adc = 0;
//static unsigned int ReadTemperature;

// Used along with the delay set this to the desired delay
static unsigned long int DelayVal;

//=========================================================================
// function prototypes
//=========================================================================
void InitializeDevice(void) ;
void delay (void);
void GetNewValues(void);
void ReadADCData(void);
//=========================================================================
//                M A I N  P R O G R A M
//=========================================================================
void main(void) {
  // Device initialisation   
  InitializeDevice();
while (1) {   
  GetNewValues();
}
  // GO to low power mode
 // _BIS_SR(LPM0_bits + GIE);
 //
 }
//==========================================================================
// This function polls for the new conversion values avaliable. And reads the
// values into the variables
//==========================================================================
void GetNewValues(void) {
  unsigned int adcDataCnt = 0;
  // Enable the load Cells
  P1OUT |= LOAD_CELL_ENABLE;

  // Enable the ADC
 // P2OUT |= ADC_ENABLE;

  // Wait for the voltage to get settled
  DelayVal = DELAY_20_MS;
  delay();

  ADCValue = 0;
  for (adcDataCnt = 0; adcDataCnt <100; adcDataCnt++) {
  // Enable the ADC
  P2OUT |= ADC_ENABLE;
  //DelayVal = 100;
  //delay();
    ReadADCData();
    //CurrentADCValue = 10;
    ADCValue = ADCValue + CurrentADCValue;
  }
  ADCValue = ADCValue/(1000);
  // Disable the load cells and ADC
  //P1OUT &= LOAD_CELL_ENABLE;
  _NOP();
  // Disable the ADC
  //P2OUT &= ADC_ENABLE;
}
//==========================================================================
//ReadADCData
//==========================================================================
void ReadADCData(void) {
  unsigned int temp_adc_val = 0;
  unsigned int clk_count = 0;   
  // Wait for data Ready
  CurrentADCValue = 0;
  P1OUT &= ~SCLK;
  while (P1IN & DATA_READY) {
    _NOP();     
  }
  // Toggle clock and get the ADC value in CurrentADCValue;
 
  for (clk_count = 0; clk_count <23; clk_count++) {
    P1OUT ^= SCLK;
    _NOP();

   
    // Valid ADC bits are only 18 rest clocks are applied to force the drdy high
    if (clk_count < 18) {
      temp_adc_val = (P1IN & DATA_READY);
      //temp_adc_val = (temp_adc_val/8);
     
      // Move the data right once
      CurrentADCValue =  CurrentADCValue << 1;
      CurrentADCValue |= temp_adc_val;
    } 
    P1OUT ^= SCLK;
    _NOP();
  }
  P1OUT |= SCLK;
  while ((P1IN & DATA_READY) == 0) {
      temp_adc_val++;
     
    _NOP();     
  }
  _NOP(); 
}
//===========================================================================
// This function configurations
// PORT
// WDT
// clock  selection
// Initialise local variables
//
//
//===========================================================================
void InitializeDevice(void) {
//===========================================================================
// Program port directions
//===========================================================================
// o = Input 1 = output
//
  P2SEL = 0;
  P1SEL = 0;
  P1DIR = 0xB8;
  P2DIR = 0xC0;
  P1OUT = 0;
  P2OUT = 0;
 
//disable the WDT + enable nmi
  WDTCTL = WDTPW + WDTHOLD + WDTNMI + WDTNMIES;
// Select VLO as clock source for ACLK
  BCSCTL3 |= LFXT1S_2;
 
  // reference voltage work around
  asm(" MOV.B # 0x61, & 0xbf");     
// Initialize variables
//  SampleValue = 0;
  //ADCOffset = 000;
  //SampleNum = 512;
  //LastADCValue = 0;
  //VoltageSettleCtr = 0;
  ADCValue = 0;
  //ReadTemperature = 1;
  P2OUT &= ADC_ENABLE;
}
//================================================================================
//================================================================================
void delay (void)
//===========================================================================
{
  volatile unsigned long int tmp_delay;
  tmp_delay = DelayVal;
  while (tmp_delay > 0) {
      tmp_delay --;
     ;
  }
}
=========================================================================================================================

  • Suchitra,

    The first thing I noticed is the value of code you are getting back is greater than 18 bits.  The number you gave is 24 bits, so we have a problem with that right away.  It appears that you are trying to take a series of readings and then average them.  Your code shows 100 reading taken, and divided by 1000.  So, that's one problem.

    Another problem is the data coming from the ADS1130 is signed, and you do use signed values, or account for them in any way.

    You are not polling DRDY, so there is no clear way for you to know if the data is valid when you try to measure it.

    I'm assuming that you are actually using a load cell.  How do you have it connected?  Does the output fall within the common mode range of the the ADC input?  The common mode input range is between  AVSS+1.5V and AVDD-1.5V.  That means the voltage at the ADC inputs must be between 1.5 and 1.7V, and with the PGA of 64 the full scale range is +/-0.5*VREF/64 = 25mV.  In other words, the maximum voltage swing of the load cell can only be 25mV and AINN must be greater than 1.5 volts and AINP must be less than 1.7V.

    So, first verify that you have the correct range and voltages at the input of the ADC.  Once you have verified the analog portion, run your program and connect the communications lines to an oscilloscope to verify that DRDY is working, and you are getting out the correct clocks.  You should see the DOUT shift as you change the load cell.  Once that is working correctly, search for and fix any remaining code issues.  You can verify the codes in software with reading from the scope.

    Best regards,

    Bob B

  • Hi Bob

    Please read my answers inline and give your valuable feedback.

    Kind Regards

    Suchitra

    Bob Benjamin said:

    Suchitra,

    The first thing I noticed is the value of code you are getting back is greater than 18 bits.  The number you gave is 24 bits, so we have a problem with that right away.  It appears that you are trying to take a series of readings and then average them.  Your code shows 100 reading taken, and divided by 1000.  So, that's one problem.

    Another problem is the data coming from the ADS1130 is signed, and you do use signed values, or account for them in any way.

    You are not polling DRDY, so there is no clear way for you to know if the data is valid when you try to measure it.

    [ssb] => I am checking for DRDY line to go low

    while (P1IN & DATA_READY) {
        _NOP();     
      }

    The above code in ReadADC polls for DRDY to go low. and againthe following code in same function polls for DRDY to go high.

    while ((P1IN & DATA_READY) == 0) {
          temp_adc_val++;
         
        _NOP();     
      }

    I expect the piece of code to behave in the following way please comment if there is any thing wrong.

    When clock is held high for Tstandby stand by mode should be activated and DRDY should go high. And when sclk is held low standby mode should be exited and DRDY should go low indicating the avaliability of new data.

    The ReadADC() works on this understanding. Just when I enter the function. I assign sclk == 0 and wait for DRDY to go low indicating data to be ready. Now I clock in 18 clocks and get the data in the  CurrentADCValue. for clocks 18 to 24 I don't read the DRDY pin. After that I assign sclk == 1 which should take the adc in standby mode.

    Do you think there's a problem in this scheme.

     

    I'm assuming that you are actually using a load cell.  How do you have it connected?  Does the output fall within the common mode range of the the ADC input?  The common mode input range is between  AVSS+1.5V and AVDD-1.5V.  That means the voltage at the ADC inputs must be between 1.5 and 1.7V, and with the PGA of 64 the full scale range is +/-0.5*VREF/64 = 25mV.  In other words, the maximum voltage swing of the load cell can only be 25mV and AINN must be greater than 1.5 volts and AINP must be less than 1.7V.

    I am using a load cell with exication vtg of 3.3V. Which means in balanced state or no load the AINP and AINN will be at 1.65 V. Now the rating of my load cell is 1.6 mv/v so for 3.2 volt the maximum output it will give is 5.28 mv. So my inputs should be well within the range.

    So, first verify that you have the correct range and voltages at the input of the ADC.  Once you have verified the analog portion, run your program and connect the communications lines to an oscilloscope to verify that DRDY is working, and you are getting out the correct clocks.  You should see the DOUT shift as you change the load cell.  Once that is working correctly, search for and fix any remaining code issues.  You can verify the codes in software with reading from the scope.


    I have one more question.

    I want to understand if its really possible to measure a load with an accuracy of 300 gms with the above load cells and ads1130. Secondly I have configured 4 three wired load cells in bridge configuration will their output be 1.6 mv/v or 1.6 * 4 mv/v since I am using one load cell each in the bridge arm. (Please pardon me for asking such a basic quesion)

    Best regards,

    Bob B

     

     

     

  • Hi Bob

    Please read my answers inline and give your valuable feedback.

    Kind Regards

    Suchitra

    Bob Benjamin said:

    Suchitra,

    The first thing I noticed is the value of code you are getting back is greater than 18 bits.  The number you gave is 24 bits, so we have a problem with that right away.  It appears that you are trying to take a series of readings and then average them.  Your code shows 100 reading taken, and divided by 1000.  So, that's one problem.

    Another problem is the data coming from the ADS1130 is signed, and you do use signed values, or account for them in any way.

    You are not polling DRDY, so there is no clear way for you to know if the data is valid when you try to measure it.

    [ssb] => I am polling for DRDY line to go low

    while (P1IN & DATA_READY) {
        _NOP();     
      }

    The above code in ReadADC polls for DRDY to go low. and againthe following code in same function polls for DRDY to go high.

    while ((P1IN & DATA_READY) == 0) {
          temp_adc_val++;
         
        _NOP();     
      }

    I expect the piece of code to behave in the following way please comment if there is any thing wrong.

    When clock is held high for Tstandby stand-by mode should be activated and DRDY should go high. And when sclk is held low standby mode should be exited and DRDY should go low indicating the Availability of new data.

     

    The ReadADC() works on this understanding. Just when I enter the function. I assign sclk == 0 and wait for DRDY to go low indicating data to be ready. Now I clock in 18 clocks and get the data in the  CurrentADCValue. for clocks 18 to 24 I don't read the DRDY pin. After that I assign sclk == 1 which should take the adc in standby mode.

    Do you think there's a problem in this scheme.

     

    I'm assuming that you are actually using a load cell.  How do you have it connected?  Does the output fall within the common mode range of the the ADC input?  The common mode input range is between  AVSS+1.5V and AVDD-1.5V.  That means the voltage at the ADC inputs must be between 1.5 and 1.7V, and with the PGA of 64 the full scale range is +/-0.5*VREF/64 = 25mV.  In other words, the maximum voltage swing of the load cell can only be 25mV and AINN must be greater than 1.5 volts and AINP must be less than 1.7V.

    I am using a load cell with excitation vtg of 3.3V. Which means in balanced state or no load the AINP and AINN will be at 1.65 V. Now the rating of my load cell is 1.6 mv/v so for 3.2 volt the maximum output it will give is 5.28 mv. So my inputs should be well within the range.

    So, first verify that you have the correct range and voltages at the input of the ADC.  Once you have verified the analog portion, run your program and connect the communications lines to an oscilloscope to verify that DRDY is working, and you are getting out the correct clocks.  You should see the DOUT shift as you change the load cell.  Once that is working correctly, search for and fix any remaining code issues.  You can verify the codes in software with reading from the scope.


    I have one more question.

    I want to understand if its really possible to measure a load with an accuracy of 300 gms with the above load cells and ads1130.

    Secondly I have configured 4 three wired load cells in bridge configuration will their output be 1.6 mv/v or 1.6 * 4 mv/v since I am using one load cell each in the bridge arm. (Please pardon me for asking such a basic quesion)

    Best regards,

    Bob B

     

     

     

  • Suchitra,

    Sorry that I missed the section of code polling DRDY, however I do question why you are polling for DRDY to go high as any clocks after 18 SCLKs forces DRDY high, but I guess redundancy is ok.  Conceptually I think you are ok with the code, you just need to verify that things are happening as you would expect, and that SCLK is at the frequency you expect.  You really need to look at this with a scope and see what code is being output and compare this to what you would expect.  Maybe you should take just one reading instead of 100 to make the comparison.  As a reminder, you need to fix your code so that it is a signed number, and it is signed correctly.  You also need to fix your number in GetNewValues so that the ADCValue is divided by the number of measurements collected.

    You have not provided enough information on the load cell to know what the maximum weight the load cell can handle.  This value is needed to calculate the resolution.  As far as your configuration, I'm not entirely sure what you expect the results to be, so a schematic would help.  If you have connected the system as I think you have, I'm not sure how you would know which load cell has a weight(s).

    So I can be of more help by you sending me a schematic and some pictures of your data as it appears on a scope.  Also, measure with a meter each analog input to ground, and also differentially.

    You also might try to hook just one load cell as described in this document. http://www.vishay.com/docs/11092/tt612.pdf   Then measure the results and see what you get.

    Best regards,

    Bob B

     

  • Hi Bob,

    Well don't know why but the DRDY pin doesn't go high untill I pull the sclk high and put the device in idle state.

    The problem was with the device itself. On changing the device things work ok. Meaning I am getting the readings now.

    The max weight spec of the load cell is 75 kg and the output is 1.6 mv/V.  The system is such that all the load cells will have weight. Actually I am trying to weight a fixed mass in a box. Whenever the mass goes below a point I have to generate a trigger. Since this is online application the readings have to be stable over temperature.

    The minimum resolution of accuracy I  require is @ 250 to 300 gms. What I am noticing is the readings of the adc are changing by about 16 counts. The load cell are temperature compensated.

    I doubt that the offset voltage of the ADC changes with temperature due to which the readings are varying.

    Please suggest me if getting the above desired accuracy is possible ?

    I am trying to upload the schematic but some how its not working. Hence I am sharing the link from google docs

    https://docs.google.com/fileview?id=0B7zsk9wkphteMWViM2UxZDgtZWY2MC00YjNjLWIzYWYtZWE0NzZkZjYwMmVi&hl=en&authkey=CJzhqtwO

     

    Kind Regards

    Suchitra

     

  • Suchitra,

    You should be able to achieve the type of resolution that you are looking for with the load cells you are using.  If you are seeing 16 counts of variation, you most likely have noise in your system.  The ADS1130 will generate about 2 to 3 counts of noise.  This is a best case scenario with a good and stable reference.  You can measure this if you short the inputs together at the ADC and bias the shorted inputs up to half of AVDD.  The measured values is the best possible noise performance of your system.

    You can then work backwards through your system following the same shorted input scenario to see which parts are adding the noise.  Possiblilities are the op amp, or biasing resistor/pot.

    Best regards,

    Bob B