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.

Compiler/ads1232: ads1232 output stabilisation

Part Number: ADS1232

Tool/software: TI C/C++ Compiler

actually i m using ads1232 with gain=128

speed =10sps

when i m reading the output of adc there is fluctuations in its lower byte while the mid byte and higher byte is okk .

so is  this possible to that anyhow i can stabilize the output of adc completely . at the analog input i have connected a variable pot of 10k

and interfaced it with stm8s003k3 microcontroller.

waiting for reply.

sonu 

  • Hi Sonu,

    Welcome to the forum!  Unfortunately you will not be able to have all bits stable as there is noise inherent to the conversion process.  There will also be noise associated with the pot and also from your supply source.  You may see some benefit to averaging.

    On page 5 of the ADS1232 datasheet you will see some tables.  This is the best possible noise performance for the various scenarios.  Table 1 using 5V for AVDD shows noise-free bits of 18.4 which are the stable bits for a gain of 128.  This means for a 24-bit converter that the lower 5 to 6 bits will be toggling.

    One other thing I should mention is the input voltage you are providing using a pot cannot be measured as a single-ended input (where AINN is connected to AGND) using a gain of 128.  There is an input restriction for gains of 64 and 128 given on page 3 of the datasheet where the absolute input voltage must be within the common-mode input range of the ADS1232.  This voltage must be greater than AGND +1.5V and less than AVDD-1.5V.  Using a gain of 1 or 2 allows for single-ended measurements.

    Best regards,

    Bob B

  • ///////----------------------STM8 ADC ROUTINE-----------------------///////
    /*
    CONTROLLER USED : STM8S003K3 32PIN PACKAGE
    ADC USED : ADS1232 24 BIT ADC (TEXAS INSTRUMENTS)
    SUPPLY USED : 5V SUPPLY
    LCD USED : STANDARD 16X2 
    ANALOG DEVICE CONNECTED : VAR POT
    CHANNEL USED : 1
    
    // connection  definition
    // adc out put format postive scale  0-   0x07fffff
    //                    negative scale 0 to 0x8000000 twos complement 
    
    ///    #define DOUT    GPIOC,GPIO_PIN_3       // DATA bit declaring at port c BIT no. 3
    ////   #define SCLK    GPIOC,GPIO_PIN_2       // SCLK bit declaring at port c BIT no. 2
    ////   #define PWDN    GPIOC,GPIO_PIN_4       // powerdown BIT declaring at port c bit no 4
    ////   #define CHAN    GPIOC,GPIO_PIN_5       // A0 BIT declaring at port c bit no 5
    
    
    */
    //////////////////-------------------------------------------------//////////
    
    #include "stm8s.h"
    #include "stdbool.h"
    #include "math.h"
    
    //---------------------- routine--------------------------------- 
    
    
    #define DOUT    GPIOC,GPIO_PIN_3       // DATA bit declaring at port c BIT no. 3
    #define SCLK    GPIOC,GPIO_PIN_2       // SCLK bit declaring at port c BIT no. 2
    #define PWDN    GPIOC,GPIO_PIN_4       // powerdown BIT declaring at port c bit no 4
    #define CHAN    GPIOC,GPIO_PIN_5       // A0 BIT declaring at port c bit no 5
    
    #define LCD_port GPIOB	            // declaring Lcd port at port B
                                        // pin no. 4,5,6,7
    
    #define RS   GPIOD,GPIO_PIN_2       // RS bit declaring at port D BIT no. 2
    #define E    GPIOD,GPIO_PIN_3       // E  bit declaring at port D BIT no. 3
    
      unsigned char y[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
      unsigned char arr1[8];
      char h,adc_sign,i;
      long adc_val_0,adc_val_1,number,new_value=0,diff;
      float average=0;
      extern char flag;
      unsigned char high_byte,mid_byte,low_byte;
      unsigned char arr[8];
       uint8_t LOOP_time;
       uint8_t TOTAL_digit;
       uint32_t POSITION_data;
      ///-------------------delay functions-----------///
    void delay_ms(unsigned long delay)
    {
        while(delay--);
    }
    
    // *** LCD Command function *** //
    void  LCD_command(unsigned char com)
    {
      GPIO_WriteLow(RS);			    // rs=0 for sending command on lcd
      //HEX_data = com&0XF0;	                    //send higher bit
      GPIO_Write(LCD_port, (com&0XF0));
      GPIO_WriteHigh(E);		            // enable  lcd for taking command from micro-controller
      delay_ms(40);
      GPIO_WriteLow(E);		            // disable lcd for taking command from micro-controller
      delay_ms(40);
      //HEX_data = (com<<4)&0xF0;	            //send lower bit
      GPIO_Write(LCD_port, ((com<<4)&0xF0));
      GPIO_WriteHigh(E);			    // enable  lcd for taking command from micro-controller
      delay_ms(40);
      GPIO_WriteLow(E);		            // disable lcd for taking command from micro-controller
      delay_ms(40);
    }
    // *** LCD Initialization function *** //
    void LCD_init(void)
    {
      LCD_command(0X01); // clear display command
      delay_ms(1000);
      LCD_command(0X01); // clear display command
      delay_ms(1000);
      LCD_command(0X01); // clear display command
      delay_ms(1000);
      LCD_command(0X28); // function set command for lcd
      delay_ms(1000);
      LCD_command(0X28); // function set command for lcd
      delay_ms(1000);
      LCD_command(0X02); // cursor at home position
      delay_ms(1000);
      LCD_command(0X02); // cursor at home position
      delay_ms(1000);
      LCD_command(0X02); // cursor at home position 
      delay_ms(1000);
    //  delay_ms(400);
      LCD_command(0X06); // entry mode set command
      delay_ms(400);
      LCD_command(0X0C); // control display on & off  and cursor blink 
      delay_ms(400);
      LCD_command(0X01); // clear display command
    }
    
    // *** LCD data function *** //
    void  LCD_data(unsigned char value)
    {
      GPIO_WriteHigh(RS);			    // rs=1 for sending data on lcd
     // HEX_data = value&0XF0;	            //send higher bit
      GPIO_Write(LCD_port, (value&0XF0));
      GPIO_WriteHigh(E);			    // enable  lcd for taking data from micro-controller
      delay_ms(35);
      GPIO_WriteLow(E);			    // disable lcd for taking data from micro-controller
      delay_ms(35);
     // HEX_data = (value<<4)&0xF0;	            //send lower bit
      GPIO_Write(LCD_port, ((value<<4)&0xF0));
      GPIO_WriteHigh(E);			    // enable  lcd for taking data from micro-controller
      delay_ms(35);	    
      GPIO_WriteLow(E);		            // disable lcd for taking data from micro-controller
      delay_ms(35);		
    } 
    // *** LCD ROW & COL SELECT function *** //
    void LCD_row_col(unsigned char row,unsigned char col)
    {
      switch(row)
      {
        case 1: col=col+0x7F;     // for row 1 & col 1-16
        break;
        case 2: col=col+0xBF;     // for row 2 & col 1-16
        break;
      }
      LCD_command(col);
    }
    
    // *** LCD print function *** //
    
    void LCD_PRINT_string(unsigned char * str)
    {
      char i=0; 
      while(str[i]!='\0')
      {
        LCD_data(str[i]);
        i++;
      }
    }
    
    //*** LCD clear function ***//
    
    void LCD_clear(void)
    {
      LCD_command(0x01);
    }
      
    void delay(unsigned int val)
         {
            while(val!=0)
              val--;
         }
    
    /////////************ADC ROUTINE**************///////////
    
    unsigned long adc_read()
    {
         char m;         
          
    
         if(GPIO_ReadInputPin(DOUT)==0)              // cheack data ready
             { 
                 high_byte=0;
                 mid_byte=0;
                 low_byte=0;
                 if(GPIO_ReadInputPin(DOUT)==0)      // check sign
                   adc_sign=1; 
                 else 
                   adc_sign=-1;
    
                        for(m=0;m<8;m++)        
                        {
                            GPIO_WriteLow(SCLK); delay(1);
                            GPIO_WriteHigh(SCLK); delay(1);
                            GPIO_WriteLow(SCLK); delay(1); 
        
                            if(GPIO_ReadInputPin(DOUT)==0)
                            {
                              high_byte=high_byte | y[m];
                            }
                        };
                        
                        for(m=0;m<8;m++)        
                        {
                            GPIO_WriteLow(SCLK); delay(1);
                            GPIO_WriteHigh(SCLK); delay(1);
                            GPIO_WriteLow(SCLK); delay(1);
                            
                          if(GPIO_ReadInputPin(DOUT)==0)
                            mid_byte=mid_byte | y[m];
                         };
                                           
                         for(m=0;m<8;m++)
                         {    
                            GPIO_WriteLow(SCLK); delay(1);
                            GPIO_WriteHigh(SCLK); delay(1);
                            GPIO_WriteLow(SCLK); delay(1);
                            
                           if(GPIO_ReadInputPin(DOUT)==0)
                             low_byte=low_byte | y[m];
                           
                         };
                         
                            GPIO_WriteLow(SCLK); delay(1); // 25th clock
                            GPIO_WriteHigh(SCLK); delay(1);
                            GPIO_WriteLow(SCLK); delay(1);
                            number=0;
                            number=number|high_byte;
                            number=number<<8|mid_byte;
                            number=number<<8|low_byte;
                            number = number*adc_sign/2 ;
               
             }
         return (number);
       
    }
    
    
    void adc_calib()
    {
                     char j;          
                    while (GPIO_ReadInputPin(DOUT))
                           { 
                             GPIO_WriteLow(SCLK);
                             GPIO_WriteHigh(SCLK);
                             delay(1);
                             GPIO_WriteLow(SCLK);
                           }
    
                       for (j=1;j<=4;j++) 
                           {
                             delay_ms(100);
                             adc_read();
                           }
                          
                       while (GPIO_ReadInputPin(DOUT)); 
                         for(j=0;j<=25;j++)
                             {
                               GPIO_WriteLow(SCLK);
                               GPIO_WriteHigh(SCLK);
                               delay(1);
                               GPIO_WriteLow(SCLK);
                             }
                              delay_ms(1000);
    }
    
    void adc_reset()
    {
              GPIO_WriteLow(PWDN);
             delay_ms(3);
              GPIO_WriteLow(PWDN);
             delay_ms(2);
              GPIO_WriteHigh(PWDN);       
             delay_ms(1000);     
    }
    
    /*void lcd_disp(char data)
        {
          char arr[8],i,comp=0x80;
          for(i=0;i<8;i++)
            {
               arr[i]=(data&comp);
               comp=comp>>1;
            }
         
        }
    */
    void LCD_32BIT_ADJUSTABLE_data(unsigned long data , unsigned char row , unsigned char col)
    {
      // first check  size of variable //
      
      if(data>=100000 && data<=999999)
        TOTAL_digit=6;
      else if(data>=10000 && data<=99999)
        TOTAL_digit=5;
      else if(data>=1000 && data<=9999)
        TOTAL_digit=4;
      else if(data>=100 && data<=999)
        TOTAL_digit=3;
      else if(data>=10 && data<=99)
        TOTAL_digit=2;
      else
        TOTAL_digit=1;
      
      // now loop for print the digits //
      LOOP_time=6;
      while(LOOP_time--)
      {
        LCD_row_col( row , col-- );
        if(TOTAL_digit>=1)
        {
          TOTAL_digit--;
          POSITION_data = data%10;
          data    = data/10;
          LCD_data('0'+POSITION_data);
        }
        else
        {
          LCD_data(' ');
        }
      }
      LOOP_time=6;         // again set the loop time 
    }
    
    void main()
          {
                            CLK_HSIPrescalerConfig( CLK_PRESCALER_HSIDIV1);         //CLK AT 16 MHZ
                            GPIO_Init(GPIOB, GPIO_PIN_ALL, GPIO_MODE_OUT_PP_LOW_SLOW);  // PORT USED FOR DATA PORT OF LCD
                            GPIO_Init(GPIOD, GPIO_PIN_2, GPIO_MODE_OUT_PP_LOW_SLOW);    //RS  PIN OF ADC
                            GPIO_Init(GPIOD, GPIO_PIN_3, GPIO_MODE_OUT_PP_LOW_SLOW);  ///EN PIN OF LCD
                            delay_ms(1000);
                            delay_ms(1000);     
                            LCD_init();
                            LCD_command(0x80);
                            LCD_PRINT_string("   WELCOME TO   ");
                            LCD_command(0xc0);
                            LCD_PRINT_string("  Design Innova ");
                            GPIO_Init(GPIOC,GPIO_PIN_2,GPIO_MODE_OUT_PP_LOW_FAST);   //sclk 
                            GPIO_Init(GPIOC,GPIO_PIN_3,GPIO_MODE_IN_FL_NO_IT);        //Pin 3 selected as INput push-pull, low level, 10MHz
                            GPIO_Init(GPIOC,GPIO_PIN_4,GPIO_MODE_OUT_PP_LOW_FAST);   //pwdn
                            GPIO_Init(GPIOC,GPIO_PIN_5,GPIO_MODE_OUT_PP_LOW_FAST);    // chan
                            GPIO_WriteLow(CHAN);  
                            adc_reset();
                            delay_ms(1);
                     //        adc_calib();
                            LCD_command(0x01);
                            while(1)
                            {
                              new_value=adc_read();
                              diff= abs(new_value-average);
                              
                              if(diff>16777216)
                              {
                                average=new_value;
                              }
                              else if(diff>128)
                              {
                                average=(average*0.875)+(new_value*0.125);
                              }
                              else
                              {
                                average=(average*0.984375)+(new_value*0.015625);
                              }
                              
                      //        LCD_32BIT_ADJUSTABLE_data( number, 1 ,(8>>1));
                            }
          }
    
      #ifdef USE_FULL_ASSERT
    
    /**
      * @brief  Reports the name of the source file and the source line number
      *   where the assert_param error has occurred.
      * @param file: pointer to the source file name
      * @param line: assert_param error line source number
      * @retval : None
      */
    void assert_failed(u8* file, u32 line)
          { 
              /* User can add his own implementation to report the file name and line number,
                 ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    
              /* Infinite loop */
              while (1)
                {
                }
          }
    #endif
    
    thanks for the reply but one more thing that i would like like to ask is that can u plz send me a sample code where i can get the linear and stabilised output of ads1232

  • Hi Sonu,

    The ADS1232 outputs the conversion result in binary 2's complement.  The data is already formatted for negative values for 24-bit, so you just need to properly sign-extend the value to a 32-bit signed value (long).

    The function adc_read() returns an unsigned value.  This should be a long as opposed to unsigned long.  Also, you cannot determine the sign until the first SCLK clock transitions high.  It would also appear that the you are setting the bit high for the value when the input is low an example is shown below:

    if(GPIO_ReadInputPin(DOUT)==0)
    {
        high_byte=high_byte | y[m];
    }

    For the adc_read function remove the check sign code, change the above sections to read ==1 instead of 0, and properly sign-extend.  One method is shown below:

    number=0;
    number=number|high_byte;
    number=number<<8|mid_byte;
    number=number<<8|low_byte;
    number=number<<8;  // force the MSB with sign into the MSB of long
    number=number>>8;  // shift the value back to the proper value with sign

    In your main function you continually equate new_value from adc_read(), but you have no way of knowing if this is new data or not.  Either you need to poll DOUT/DRDY in the main function or in adc_read to wait unitl new data is available.  As an example:

    while(GPIO_ReadInputPin(DOUT) !=0);

    If you use a scope or logic analyzer you can check all the timing.  First you need to check and make sure the SCLK timing is valid.  Second, you should see DOUT/DRDY go from high to low at the specified data rate you have chosen.  Next you should see the data captured on the scope and compare to the data in your program.  This should all be working prior to working on the averaging algorithm.

    Best regards,

    Bob B

  • can u just help me by providing a sample code so that i can be able to check and compare both .
  • Hi Sonu,

    The only example code we have for the ADS1232 is in the location shown below.  As this code uses a different processor, a real-time operating system and complicated code I thought it would be easier to fix the few small issues in your code instead of getting confused by the example code.

    ftp://ftp.ti.com/pub/data_acquisition/ADS123xREF/ADS123x_CDROM/Firmware/Firmware_Source_Code/Source_for_123XREF_firmware-1.1.0d.zip

    Good luck,

    Bob B

  • so is it possible that u get my code edited where it needs to be and send me a copy of that.
  • Hi Sonu,

    Sorry for the delayed response.  I do not have time to go through your code line by line but for the ADC section the code should look more like the following:

    signed long adc_read()
    {
         char m;         
         char adc_sign=0; 
    
         if(GPIO_ReadInputPin(DOUT)==0)              // cheack data ready
             { 
                 high_byte=0;
                 mid_byte=0;
                 low_byte=0;
                
                        for(m=0;m<8;m++)        
                        {
                            GPIO_WriteLow(SCLK); delay(1);
                            GPIO_WriteHigh(SCLK); delay(1);
                            GPIO_WriteLow(SCLK); delay(1); 
        
                            if(GPIO_ReadInputPin(DOUT)!=0)
                            {
                              high_byte=high_byte | y[m];
    						  if(m==0) adc_sign=1;
                            }
                        };
                        
                        for(m=0;m<8;m++)        
                        {
                            GPIO_WriteLow(SCLK); delay(1);
                            GPIO_WriteHigh(SCLK); delay(1);
                            GPIO_WriteLow(SCLK); delay(1);
                            
                          if(GPIO_ReadInputPin(DOUT)!=0)
                            mid_byte=mid_byte | y[m];
                         };
                                           
                         for(m=0;m<8;m++)
                         {    
                            GPIO_WriteLow(SCLK); delay(1);
                            GPIO_WriteHigh(SCLK); delay(1);
                            GPIO_WriteLow(SCLK); delay(1);
                            
                           if(GPIO_ReadInputPin(DOUT)!=0)
                             low_byte=low_byte | y[m];
                           
                         };
                         
                            GPIO_WriteLow(SCLK); delay(1); // 25th clock
                            GPIO_WriteHigh(SCLK); delay(1);
                            GPIO_WriteLow(SCLK); delay(1);
                            number=0;
                            number=number|high_byte;
                            number=number<<8|mid_byte;
                            number=number<<8|low_byte;
    						if(adc_sign) number=number|0xFF000000; //value is negative
                                       
             }
         return (number);
       
    }

    You should also verify your communication on a scope or logic analyzer.  This would also include the SCLK timing to make sure that the clock follows the correct high/low time requirements.  I question the time of 'delay(1)' as being correct for the ADS1232.

    Best regards,

    Bob B

  • this was good but there is problem in linearity and stability of the the adc output
  • Hi Sonu,

    We have come back to the beginning of this thread.  You do not show a schematic or state how the Gain pins of the ADS1232 are connected.  If you are applying a voltage using a pot, you can only use a gain of 1 or 2.  If the voltage source has noise, or if noise is picked up in the connections of the pot you will see noise in the output codes.  If the reference is noisy, this will result in noisy codes.  If you are using a pot with gains of 64 or 128 you will see linearity issues as the input will be outside the common-mode input range for the ADS1232.

    The output codes will never be completely stable.  Tables 1 through 4 on page show the noise performance of the ADS1232 in various operating conditions.  In particular pay attention to the noise-free bits.

    When I look back at your code, I don't understand your averaging algorithm.  For example, 'diff' is the difference between the value just read and the average calculated value. You use an if statement that can never take place:

    if(diff>1677721)

    The maximum positive code from the ADS1232 is 0x7FFFFF (8388607 decimal).  Codes 0xFFFFFF to 0x800000 are negative codes (-1 to -8388608).  Also I do not understand your 2 different averaging methods.  When combining you will see different values depending on the comparison which will lead to error and may appear as linearity error.  I would not use an averaging algorithm until you know your data is valid.  Noise is to be expected, but reducing all external sources of noise should be accomplished first.

    Best regards,

    Bob B

  • the above is the schematic and at AINP1 i have connected a 10 k pot to give the input to the adc
  • also i m providing the power to adc via discovery board programmer voltage source of 5v
    gain =128
    speed =10 sps
  • Hi Sonu,

    The ADS1232 makes a differential measurement between AINP and AINN.  The input requirement for the analog inputs at a gain of 128 is AINN and AINP must be less than AVDD-1.5V and AGND+1.5V.  You cannot connect AINN to AGND and expect a good reading when the gain is 64 or 128.

    If you want to use a pot for the input you actually need to use 2 of them ( or at least one of them for one input and a voltage divider on the other) as both inputs must be within the correct common-mode for device operation.  The linearity error you are seeing is most likely related to your input voltage.  Also remember that difference voltage (between AINP and AINN) must be limited to +/- 19.5mV for a 5V reference.

    Best regards,

    Bob B

  • its a request to you
    if you can just send or edit my code to give me a stable output
    i will be much thankful to you and too send me a schematic which is much compatible.