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.

how to solved zero_count drift in ADS1230?

Other Parts Discussed in Thread: ADS1230

 

I am facing following issue.

 

Let’s say I am calibrating grocery weigh scale with 5kg weight .

 

At zero weight I am getting 1000 count from ADS1230 and @5kg I am getting 6000 count from ADC.

 

Hence,

 

Display weight = ((ADC Count – Zero count)* Calibration weight)/(Span Count – Zero count)

 

For example lest say I am getting 6002 count from ADC, so as per above formula,

 

Display weight = ((6002-1000) * 5000)/(6000-1000) = 5002 gm, and weight put is also same.

 

Now over the time,

 

I am getting, 1002 count for zero weight.

 

Display weight = ((1002-1000) * 5000)/(6000-1000) = 2 gm, and weight put is zero, and

 

lest say I am getting , 998 count for zero weight.

 

Display weight = ((998-1000) * 5000)/(6000-1000) = -2 gm, and weight put is zero.

 

This is issue of zero count shift. With it span count also shifts,but I have to know new zero so that it can be taken care automaticallu.

 

People use auto zero for this. I used that method but still this issue persist. I have attached code part of that function.

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Function to read ADC
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void read_ADS1230(void)
{
	adc_data=serial_read(21);	
	adc_data>>=3;					// Convert to 18 bit

    adc_sample[mov_sample_counter++] = adc_data;
	mov_average();			 		// block average + moving avaerage(with fast update) (use variable 'weight' as a stable data)

	if(run_mode)
	{
		update_display=1;
		main_disp=weight;
		if(hold_flag)
			main_disp=hold_weight;
	}
	else if(set_mode)
	{
		if(index==27)
		{
			tare_count=0;
			zero_count=adc_final;
			update_display=1;
		}
		else if(index==31)
		{
			span_count=adc_final;
			update_display=1;
		}
	}
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Routine to read 21 bit data from ADS1230
// Read data when clock is low
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
long serial_read(unsigned char bits)
{
	long data1=0; 

	for(i=0;i<bits;i++)
	{ 
		data1<<=1;
		ADS_SCLK=1;     
		_nop_();
		_nop_();
		ADS_SCLK=0;

		if(ADS_SDO)
			data1 |= 0x00000001;  
	}
	return(data1);
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Moving Average Method
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void mov_average(void)
{
	long templ1,templ2;
    if(mov_sample_counter>=MOVE_SAMPLE)
    {   
      	mov_sample_counter=0; 
      	templ1=0;      
     	
		for(i=0;i<MOVE_SAMPLE;i++)
        	templ1+=adc_sample[i];

      	adc_final=templ1>>3; 				  // Divide by 8	  
      
//      if(adc_final > zero_count)            // Auto zeroing
//        	templ2=(adc_final - zero_count);
//      else
//        	templ2=(zero_count - adc_final);   
       
		if(start_mode)
		{
			if(++start_time>STRT_DLY)
			{
				start_mode=0;
				run_mode=1;
				run_zero = adc_final;
			}
			start_update=1;
		}

//	  	templ1=set_auto0;
//		auto_zr=(templ1*CNT_GRM)+OFST_GRM;	
//		if((weight >= -templ1) && (weight <= templ1) && (templ2 < auto_zr))
//		{
//	      	if(adc_final > run_zero)            
//    	    	templ2=(adc_final - run_zero);
//	      	else
//    	    	templ2=(run_zero - adc_final);  
//			run_zero = adc_final;
//			if(tare_count!=0)
//			{
//          	if(tare_count>0)
//					tare_count=tare_count-templ2;
//				else if(tare_count<0)
//					tare_count=tare_count+templ2;	
//			}
//		}
    }        
    else
    {
      	templ1=0;
      	for(i=0;i<MOVE_SAMPLE;i++)
        	templ1 += adc_sample[i];
		templ1=templ1>>3;
		templ2=templ1-adc_final;
		if(templ2>3)
		{
			buzzer_on();
		}
      	adc_final = templ1;
    }   
	if(run_mode)
		calculation();
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Weight Calculation
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void calculation(void)
{
	long templ1,templ2;

	sign_flag=1;

	templ2 = (span_count - zero_count); 

	if(set_auto0==0)
		templ1 = adc_final - zero_count;
	else	
		templ1 = adc_final - run_zero;  

	if(!gross_flag)
		templ1 = templ1 - tare_count;

	weight = ((float)templ1 * cal_weight ) / templ2;
	
	if(weight < 0)
		weight *= (-1);
	else 
		sign_flag = 0;

	decide_capacity();

	if(liter_mode)
	{
		weight = (weight * 977 );
		weight = (weight/1000);
	}
}

 

Commented portion  is one method I have adopted but still facing problem.

 

  • Khodidas,

    Precision scales, like a grocery scale, usually have a TARE button.  When the TARE button is pressed, an new zero point is added/subtracted from the original calibration values.  The TARE is useful and should be added to grocery scales so that the consumer pays for the weight of the product and not the container.  So the formula should include this value.

    Display weight = ((ADC Count – Zero count - Tare count)* Calibration weight)/(Span Count – Zero count)

    The 'Tare count' is the difference in count from the Zero count (Tare-Zero).  So in your example you would get:

    Display weight = (((1002-1000-(1002-1000))*5000)/(6000-1000) = 0

    For the auto zero section in your code it appears that the values for the tare are included in parts of the formula, but 'tare_count' never gets moved from the 0 value (even if you uncomment that part of the code).  That is why the auto zero gives the same results.  Of course that assumes that there is not another function that sets the tare_count value.

    So, verify that your code is actually following the above formula and you should see the results you expect.

    Best regards,

    Bob B

  • Bob,

     

    Thanks for your reply.

    I have already provide TARE in my code.

    At power on, tare_count=0;

     

    and it gets updated as per below formula when some one press the TARE key,

    void tare_key_func(void)
    {
        if(run_mode)
       {
            if(set_auto0==0)
                 tare_count = (adc_final - zero_count);
           else 
                 tare_count = (adc_final - run_zero);

            update_display=1;
        }
    }

    What I understand from your reply, is that I need not to apply auto zero. Drift in count from calibration count will be taken care by TARE.

     i.e. TARE will act as autozero. Means when no load is kept on cell and cell don't show zero vale apply tare to make it zero.

     

    Is my understanding right?

     

    khodidas

     

     

     

  • Khodidas,

    You are correct about the usage.  However TARE doesn't auto zero, but allows for an offset of the calibrated zero point.  So make sure you understand that you have to have a calibrated zero count with no load applied, and a calibrated weight count for a specific weight.  So when you adjust the count values within the software code you need to make sure you adjust appropriately and know hot to get back to the calibrated values.

    With the formula you initially gave me TARE was not taken into account, and I couldn't see where it was set in the code.  With the additional code you have now sent, your code formula appears to include the TARE so that it actually looks similar to the formula I gave you.

    TARE will help you if small atmospheric changes affect the load cell, or if there is a small offset due to drift of the converter.  It will not help you if something causes the load cell calibration to change (like if the load cell gets damaged or if you accidentally change the calibration values.)  Gain drift of the converter is another error that cannot be solved by adding or subtracting counts.

    So whether you use TARE, or auto zero, or a combination of both, you must be certain of the math involved so that you don't accidently change the calibrated zero count itself, but rather adjust to the zero by adding or subrtracting as necessary to get a display count of zero.

    So when you take a measurement the display should always be at zero when you start.  Are you always starting with  zero display reading before the weight is applied to the scale?

    Best regards,

    Bob B