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.

Problem in ADS1230 weighing scale program

Other Parts Discussed in Thread: ADS1230, ADS1232

Hi,

I wrote program in C & using Keil compiler, the header file & schematis are attached for your reference. The program is working fine with some load cells but for some load cells it is giving high value of counts i.e. more than 500K at no load conditions, now if I put some load then counts increases & becomes 0 & increases while increasing load. I hope the method of offset calibration used is not correct. Please review the header file & let me know the right method or send me the sample code for offset calibration. I saw the different behaviour for different load cell when starts the weighing machine, some times there is a reading before zero comes, some time fast fluctuations in counts & that is not readable.

Please suggest the solution..

Regards,

Navin Rana

5684.ADC.H

3660.ADC1230.pdf 

 

  • Hi Navin,

    Can you provide any details on the load cells you are using with the ADS1230?  For the ones that 'work fine' versus those that do not, what is the difference between these cells?

  • Dear Tom,

    Thanks for reply!

    What all details you want? I have some queries pls reply

    Could you please check our .h file whether it is correct or not ?

    We have offset calibration function in .h file, Is it that correct & where we have to call this in our C program?

    Can you pls provide me sample code in C for ADS1230?

    Regards,

    Navin Rana

  • Navin,

    26 clocks is what you need for offset calibration, but the extra clocks should come following a data read.  What we have in our ADS1230REF code is a flag that is set prior to the interrupt routine used for reading out the data.  The flag  is checked in the 'if' statement in the routine following the data read, and if set sends the extra clocks.  In this way we don't accidentally call the offset at the wrong time.  This call is in the ADS1232.c in the interrupt routine at the bottom of the file found on the ftp server:

    ftp://ftp.ti.com/pub/data_acquisition/ADS123xREF/ADS123x_CDROM/Firmware/Firmware_Source_Code/

    A couple of other things to consider is there is some latency for accurate readings following step changes, so generally you discard the first few readings after any weight is applied to the load cell.

    Another thing is you have a resistor (R18) that is pulling up AINP.  This resistor will cause a lot of issues to include offsets and linearity errors.  This resistor is unbalancing the bridge.  If you have a poor connection to the load cell, the problem will get worse.  I would double check my connections to the load cell and remove R18.

    Best regards,

    Bob B

  • Dear Bob,

    Thanks for your suggesstions, let me apply these & get back to you with result, also should I remove R18 & keep the ends open?

    Regards,

    Navin Rana

  • Navin,

    If the load cell is connected, then the 'ends' are connected.  Maybe I'm not understanding what you are asking, but R18 should be removed.  Part of the problem with R18 is lifting the input outside of the common mode input range.

    Best regards,

    Bob B

  • Dear Bob,

    We tried the same as per your suggestions, removed R18 & discard some initial data but may be we are not doing correctly. Pls find attached the c file for your review comments. We are facing problem of hang of application i.e. display 0000 weight & no change even put weight on load cell. This is not happenning every time. It happens only when we on/off the machine frequently (some time it comes in 5-6 on/off, some times in 10-12 on/off).

    Pls suggest the solution where we are making mistake in getting data from ADC or it is due to some other factor.

    Regards,

    Navin Rana

    /*------------------------------------------------------------------------------
    weighing machine
    ------------------------------------------------------------------------------*/
    #include <reg52.H> 
    #include "ADC.H"
    #include "EEPROM.H"
    #define max_avg 4
    
    #define ad_cal_count   0x01	//EEPROM address for weight caliberation -upper byte
    //Capecity
    #define ad_cap1 0x09	//EEPROM address for capacity 1 - upper byte
    #define ad_cap1_fd	0x0D		//EEPROM address for Capacity 1 fd parameter
    #define ad_cap2 0x0E	//EEPROM address for capacity 2 - upper byte
    #define ad_cap2_fd	0x12		//EEPROM address for Capacity 2 fd parameter
    #define ad_232 	0x13
    
    //Accuracy
    #define ad_acc1 0x18	//EEPROM address for accuracy 1 - upper byte
    #define ad_acc1_fd 0x1A	//EEPROM address for Accuracy1 feed paramener
    #define ad_acc2 0x1B	//EEPROM address for accuracy 2 - upper byte
    #define ad_acc2_fd 0x1D	//EEPROM address for Accuracy1 feed paramener
    #define ad_dp1 	  0x29	//EEPROM address for decimal point 1
    #define ad_dp2 	  0x2A	//EEPROM address for decimal point 2
    
    sbit key1 = P1^4;			   
    sbit key2 = P1^5;
    sbit key3 = P1^6;
    sbit key4 = P1^7;
    
    //Functions Prototype Declarations
    void wait(void) { ; }  //for delay
    void delay(unsigned int); 
    void caliberation();
    
    unsigned char bdata flg;
    sbit sign=flg^0;
    sbit TrFlg=flg^2;
    sbit cnt_mode=flg^4;
    	 
    idata unsigned char digit[6];
    unsigned char acc,acc1,acc2,dp,dp1,dp2;
    idata long litd, value, tare_val, temp, value1, cal_val=2000;
    idata long disp_value;
    idata long avg[max_avg];
    idata unsigned char avg_cnt=0;
    idata unsigned long cap1, cap2;//,tmpDisp_Val=0;
    unsigned char val_1, val_2, val_3, val_4;
    idata unsigned char tp1,tp2;
    idata long cal_count;
    
    void main (void) 
    {
    	SCK = 0;
    	PDN = 1;
    	SDO = 1;
    
    	TrFlg=1;
    	sign=0;	
    
    	delay(10000);
    
    	 displayBlank();
        offset_calibation();
    	
    	if(!key1 && !key4)                                
        {
              cnt_mode=1;
        }	
    	
    	delay(25000);
    	
    	for(val_1=0;val_1<max_avg;val_1++)
    	{
    		avg[val_1] = Read_Adc();
    		 	
    	}
    	  
    	while(1)
    	{ 
    label1:
    			value = Read_Adc();
    			avg[avg_cnt++] = value;
    			value = 0;
    			for(val_1=0;val_1<max_avg;val_1++)
    				value = value + avg[val_1];
    			value = value/max_avg;
    			if(avg_cnt >= max_avg)
    				avg_cnt = 0;
    			
    		if(!key1)
    		{
    			delay(5000);
    			TrFlg=1;
    		}
    
    		if(!key3)
    		{
    			delay(5000);
    			caliberation();
    		}
    			if(cnt_mode==1)//count mode
    	    	{
    				disp_value=value;
    				goto cnt_mode;
    			}	  
    			if(TrFlg==1)
        		{
        				TrFlg =  0;  
           	 			tare_val=value;
    			}
    	
    				if(tare_val > value)
    				{
    					value=tare_val-value;
    					sign = 1;
    		    	}
    		        else
    				{
    			        value=value-tare_val;
    		        	sign = 0;
    		    	} 
    			
    			disp_value = (value*10000)/cal_count;
    			
    cnt_mode:
    		  display(disp_value);
    	}//end of while(1)
    }//end of void main
    
    
    void caliberation()
    {
    	unsigned long enter_val=0, value1=0;
    	while(1)
    	{
    		if(!key3)
    		{	 
    			digit[0]++;
    		
    			if(digit[0] > 9)
    			{
    				
    				digit[0] = 0;
    			}
    			delay(5000);
    		}
    				    
    		if(!key2)
    		{
    			digit[0]=0;
    			delay(5000); 
    		}
    		//stable();			
    		if(!key1)	                                  
    		{	                                   
    		    delay(25000);
    				enter_val = 0;
    				for(val_1=5;val_1>0;val_1--)
    				{
    						enter_val = enter_val*10 + 0;
    				}
    
    				value = Read_Adc();
    				
    				value = value - tare_val;
    				cal_count = ((float)value/enter_val)*10000;
    				
    				write_val(ad_cal_count, cal_count);
    				
    				return;
    				
    			
    		}
    	}
    }
    
    void delay(unsigned int dx)
    {
    	unsigned int i;
        for (i=0;i<dx;i++)
    	{
        	wait();
        }
    } 
    
    	

     

  • Navin,

    We are on holiday today in the USA, so I will look at your code further tomorrow.  One thing that most likely is happening is a power reset issue.  When you switch on and off the power you must make sure that the power has completely gone to zero. Caps will hold the power above ground for a period of time. There is no brown out circuitry detection with the ADS1230, and it is quite possible that the part is not fully re-initializing following a power cycle.

    Best regards,

    Bob B

  • Dear Bob,

    Thanks for reply on holiday!

    How do we ensure that the caps are discharged, is there any way to discharge before initialize the circuit. We are getting complaint of this problem from our customer so it is becoming critical for us. Pls suggest if we can do it in our code ..

    Regards,

    Navin Rana

  • Navin,

    Holding the PWRDN pin low either with your micro or by using a supervisor should do what you desire.  PWRDN will reset the ADS1230 to a known state.

    Best regards,

    Bob B

  • Dear Bob,

    We are doing it..

    In main() we have PWRDN = 0, then we do PWRDN = 1 just before reading ADS1230. I will try to making PWRDN = 0 for some more time by using delay after that..

    Thanks agaian for suggestions..

    Regards,

    Navin Rana

  • Dear Bob,

    I tried the same & felt that the frequency of the same problem is reduced but it is not removed, pls check the updated c file attached in which PDN is done 0,1, also I tried several permutation & combinations for PDN = 0 & PDN = 1. Pls suggest how to resolve it..

    Also I noticed that when this problem occurs then the counts displayed are 262144 (4 0000H)..

    Regards,

    Navin Rana

    /*------------------------------------------------------------------------------
    weighing machine
    ------------------------------------------------------------------------------*/
    #include <reg52.H> 
    #include "ADC.H"
    #include "EEPROM.H"
    #define max_avg 4
    
    #define ad_cal_count   0x01	//EEPROM address for weight caliberation -upper byte
    //Capecity
    #define ad_cap1 0x09	//EEPROM address for capacity 1 - upper byte
    #define ad_cap1_fd	0x0D		//EEPROM address for Capacity 1 fd parameter
    #define ad_cap2 0x0E	//EEPROM address for capacity 2 - upper byte
    #define ad_cap2_fd	0x12		//EEPROM address for Capacity 2 fd parameter
    #define ad_232 	0x13
    
    //Accuracy
    #define ad_acc1 0x18	//EEPROM address for accuracy 1 - upper byte
    #define ad_acc1_fd 0x1A	//EEPROM address for Accuracy1 feed paramener
    #define ad_acc2 0x1B	//EEPROM address for accuracy 2 - upper byte
    #define ad_acc2_fd 0x1D	//EEPROM address for Accuracy1 feed paramener
    #define ad_dp1 	  0x29	//EEPROM address for decimal point 1
    #define ad_dp2 	  0x2A	//EEPROM address for decimal point 2
    
    sbit key1 = P1^5;			   
    sbit key2 = P1^4;
    sbit key3 = P1^7;
    sbit key4 = P1^6;
    
    //Functions Prototype Declarations
    void wait(void) { ; }  //for delay
    void delay(unsigned int); 
    void caliberation();
    
    unsigned char bdata flg;
    sbit sign=flg^0;
    sbit TrFlg=flg^2;
    sbit cnt_mode=flg^4;
    	 
    idata unsigned char digit[6];
    unsigned char acc,acc1,acc2,dp,dp1,dp2;
    idata long litd, value, tare_val, temp, value1, cal_val=2000;
    idata long disp_value;
    idata long avg[max_avg];
    idata unsigned char avg_cnt=0;
    idata unsigned long cap1, cap2;
    unsigned char val_1, val_2, val_3, val_4;
    idata unsigned char tp1,tp2;
    idata long cal_count;
    
    void main (void) 
    {
    	SCK = 0;
    	//PDN = 1;	
    	SDO = 1;
    
    	TrFlg=1;
    	sign=0;	
    
    	delay(10000);
    
    	 displayBlank();
         offset_calibation();
    	
    		PDN = 1;	// set powerup to display hello as this pin is connected to reset of MCU
    	  	
    		  display(Hello);
    		 
    		PDN = 0;	// set powerdown to get time to discharge the capacitor
    		delay(25000);
    		PDN = 1;	// again powerup & down  
    		PDN = 0;
    		delay(25000);
    
    	if(!key1 && !key4)                                
        {
              cnt_mode=1;
        }	
    	
    	PDN = 1;	// powerup to fill up the buffer for getting data from ADC 
    	delay(200);
    	for(temp_char=0;temp_char<10;temp_char++)	// fill up the buffer for 10 readings from ADC & then discarded
    		avg[val_1] = Read_Adc();
    	value = 0;
    	for(val_1=0;val_1<max_avg;val_1++)		// fill up the buffer for actual calculations
    	{
    		avg[val_1] = Read_Adc();
    		value = value + avg[val_1]; 	
    	}
    	tare_val=value/max_avg;
    	  
    	while(1)
    	{ 
    label1:
    			value = Read_Adc();
    			avg[avg_cnt++] = value;
    			value = 0;
    			for(val_1=0;val_1<max_avg;val_1++)
    				value = value + avg[val_1];
    			value = value/max_avg;
    			if(avg_cnt >= max_avg)
    				avg_cnt = 0;
    			
    		if(!key1)
    		{
    			delay(5000);
    			TrFlg=1;
    		}
    
    		if(!key3)
    		{
    			delay(5000);
    			caliberation();
    		}
    			if(cnt_mode==1)//count mode
    	    	{
    				disp_value=value;
    				goto cnt_mode;
    			}	  
    			if(TrFlg==1)
        		{
        				TrFlg =  0;  
           	 			tare_val=value;
    			}
    	
    				if(tare_val > value)
    				{
    					value=tare_val-value;
    					sign = 1;
    		    	}
    		        else
    				{
    			        value=value-tare_val;
    		        	sign = 0;
    		    	} 
    			
    			disp_value = (value*10000)/cal_count;
    			
    cnt_mode:
    		  display(disp_value);
    	}//end of while(1)
    }//end of void main
    
    
    void caliberation()
    {
    	unsigned long enter_val=0, value1=0;
    	while(1)
    	{
    		if(!key3)
    		{	 
    			digit[0]++;
    		
    			}
    				    
    		if(!key2)
    		{
    			digit[0]=0;
    			delay(5000); 
    		}
    		//stable();			
    		if(!key1)	                                  
    		{	                                   
    		    delay(25000);
    				enter_val = 0;
    				for(val_1=8;val_1>0;val_1--)
    				{
    						enter_val = enter_val*10 + 0;
    				}
    
    				value = Read_Adc();
    				
    				value = value - tare_val;
    				cal_count = ((float)value/enter_val)*100;
    				
    				write_val(ad_cal_count, cal_count);
    				
    				return;
    				
    			
    		}
    	}
    }
    
    void delay(unsigned int dx)
    {
    	unsigned int i;
        for (i=0;i<dx;i++)
    	{
        	wait();
        }
    } 
    
    	

  • Navin,

    In your current code you are losing your offset calibration, and I don't think that it is necessary to keep toggling PDN.  As per datasheet Power-Up Sequence on page 19 it states that the PDWN pin must remain low for at least 10us after AVDD and DVDD have completely power up.  I would suggest that you have a pull-down resistor (47k perhaps) to ground on the PWDN pin.  This will make sure the pin is grounded when the micro starts (which I believe initializes in tri-state.)  Then hold the PWDN pin low until at least 10us after all supplies are stable at the rated voltage.  That should be sufficient.

    Best regards,

    Bob B

  • Dear Bob,

    Thanks for reply!

    Could you pls check the header file I sent regarding offset calibration, is it correct function definition or need some modification, if you think it is not correct then pls tell me what modification needed & when it is to be revoked in our c file..

    Regards,

    Navin Rana

  • Navin,

    I believe the header file is ok, but I don't see that PDN is set to 0.  What micro are you using?  Does the port pin default to output low?  Can you send me some scope shots of the supply ramp, PWDN pin, and the communication pins?  Oscilloscope plots of the startup would be helpful to verify the timing.

    Best regards,

    Bob B

  • Dear Bob,

    Thanks for your guidance!

    We are using 8051 MCU, the port PIn was high & now we made it low, it seems the issue is resolved but I will confirm tomorrow after testing with different load cells. I am working at home because in India it is 1:20 AM so not able to test with other load cells, I have only one at home but I saw different excitation voltage for different load cells & some of them are having little bit in minus side & for that I used some substraction in header file. I do not have CRO but will try to get the plot to check timing if face any issue tomorrow. I have some issues in power save mode & will ask you once I am sure that this critical problem is resolved..

    Regards,

    Navin Rana

  • Hi,

    i am very much new to the programming field. i am trying to interface ADS 1230 with MCU 89C52.. but i am unable to make the proper code,, would be thankful if any body could provide me a sample C code for accessing the 20 digital data bits from ADC, 

  • Hi Gopali,

    Welcome to the forum!  If you read through this post you will find Navin's code.  The ReadADC code is in the header file.  The approach is to use bit-bang SPI, where you set up GPIO pins with SCLK as the output and you toggle the pin high and low.  Another GPIO is an input and read at the appropriate time of the SCLK transition as is shown in the datasheet for the ADS1230.

    Best regards,

    Bob B

  • thank you so much sir,

    the code was a great help.. have started working on it. hope soon i reach a conclusion. thanks a lot.

  • the 20 bit digital data has been saved in a variable "temp" with data type long.

    now to display the weight on 7 segments, do we have to convert this 20 bit binary data to 7 segment using a binary to seven segment decoder? I have 6  seven segments connected to port 0 for data and port 2.1 to pin 2.6 via transistors. 

    (temp/1000000)
    (temp/1000000)%10)
    (temp/100000)%10)
    (temp/10000)%10)
    (temp/1000)%10)
    (temp/100)%10)
    (temp/10)%10)
    (temp%10)

    this way i could separate the digits but i don't know what to do next.. please suggest me how to display this data on 6 seven segments. or should i use decimal to 7 segment converter and convert this each value of temp and display it.

  • Gopali,

    There are a number of different ways to convert numbers and display them.  We use starburst LCD displays.  It sounds like you are using a LED display.  You could create a look-up table function of values 0 through 9.  Each digit would represent a value to be displayed with the required segments that need to be lit.  You could then turn on the required segments based on the look-up table.

    Best regards,

    Bob B

  • You know, i am also interested in program writing, and i found lots of useful information here- http://www.moris.lt/lt/bendra-iranga/svarstykles.html , i think that you will also find what you need, especially here. Maybe you already found smth? Share it with me