ADC calibration results vary ?!

cancel
Showing results for 
Search instead for 
Did you mean: 

ADC calibration results vary ?!

1,320 Views
bitsplitter
Contributor I

Hello all,

 

I'm using Freescale KL3x MCU.  Embedded 16-bit A/D converter is capable of performing its own calibration to eliminate offset and linearity problems.

However, I've experienced some problems with this feature.

 

It seems that two successive A/D calibrations result in slightly different calibration data. In my application, high resolution measurement is required, so I'm running

A/D converter in 16-bit mode. First thing after reset is to init A/D converter and perform A/D calibration. Afterward, measurement is done in an endless loop and results are being sent to LCD.

I have noticed that if I reset MCU several times in a row least significant digit on the LCD is changing ± 2 although the input value being measured is fixed (comes from very precise source).

This implies that ADC readings vary. Therefore, I've suspected on the A/D calibration procedure.

 

To investigate this further, I have created simple program that does only A/D convertor init and calibration ... then waits 1 second and does everything again in an infinitive loop.

Calibration results are sent to PC via UART. I've logged this data into txt file (see attachment).

Inside this file, you'll see that every time data is slightly different although the MCU environment (in example: temperature) didn't change.

 

 

Here are calibration results from two successive calibrations:

 

0 --> ADC0_OFS

47 --> ADC0_CLP0

92 --> ADC0_CLP1

187 --> ADC0_CLP2

372 --> ADC0_CLP3

740 --> ADC0_CLP4

48 --> ADC0_CLPS

33511 --> ADC0_PG

49 --> ADC0_CLM0

97 --> ADC0_CLM1

192 --> ADC0_CLM2

382 --> ADC0_CLM3

755 --> ADC0_CLM4

48 --> ADC0_CLMS

33529 --> ADC0_MG

 

 

65535 --> ADC0_OFS

49 --> ADC0_CLP0

96 --> ADC0_CLP1

193 --> ADC0_CLP2

385 --> ADC0_CLP3

767 --> ADC0_CLP4

49 --> ADC0_CLPS

33537 --> ADC0_PG

50 --> ADC0_CLM0

100 --> ADC0_CLM1

198 --> ADC0_CLM2

392 --> ADC0_CLM3

776 --> ADC0_CLM4

49 --> ADC0_CLMS

33550 --> ADC0_MG

 

 

I have read that calibration results can be affected by the clock source, frequency, power and conversion speed settings, voltage reference, hardware average function, the

sample time and to a much lesser extent, environment. I've followed all the instructions from the datasheet. Here is the relevant code snippet:

 

uint8_t Init_ADC(void)

{

unsigned short nCal;

uint8_t autocal_result;

 

  // Turn on the ADC0 clock

  SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK;

 

  // Select TPM2 as ADC 0 trigger source

  SIM_SOPT7 = SIM_SOPT7_ADC0ALTTRGEN_MASK | SIM_SOPT7_ADC0TRGSEL(10);

 

  //Normal power configuration

  //Input Clock is (Bus Clock)/2

  //The divide ratio is 1 and the clock rate is input clock

  //ADC clock = 24M/2/4 = 3MHz

  //Long sample time

  //16-bit conversion

  ADC0_CFG1 = 0x5D;

 

  //ADxxa channels are selected

  //Asynchronous clock output disabled; Asynchronous clock is enabled only if selected by ADICLK

  //and a conversion is active.

  //High-speed conversion sequence selected with 2 additional ADCK cycles to total conversion time.

  //Default longest sample time; 20 extra ADCK cycles; 24 ADCK cycles total.

  ADC0_CFG2 = 0x4;

 

  //Hardware trigger selected

  //Compare function disabled

  //DMA disabled

  //Default voltage reference pin pair, that is, external pins VREFH and VREFL

  ADC0_SC2 = ADC_SC2_ADTRG_MASK;

 

  //Hardware average function enabled

  //32 samples averaged

  ADC0_SC3 = 0x7;

 

  //Conversion complete interrupt enabled

  //Single-ended conversions

  //AD4 is selected as input

  ADC0_SC1A = ADC_SC1_AIEN_MASK | 0x4;

 

 

/* ADC calibration */

 

  //The input channel, conversion mode continuous function, compare function, resolution

  //mode, and differential/single-ended mode are all ignored during the calibration function.

  //In 16-bit single-ended mode, there is no field in the OFS

  //corresponding to the least significant result D[0], so odd values, such as -1 or +1, cannot

  //be subtracted from the result.

 

  ADC0_SC1A &= ~ADC_SC1_AIEN_MASK;

 

  ADC0_SC2 = 0x1; //Enable Software Conversion Trigger for Calibration Process; Alternate reference pair (Vrefh = VDDA).

 

  ADC0_SC3 |= ADC_SC3_CAL_MASK; //Start calibration

 

  while(!(ADC0_SC1A & ADC_SC1_COCO_MASK));

 

  if (ADC0_SC3 & ADC_SC3_CALF_MASK)

  {

      // Calibration failed

      autocal_result = 0;

  }else{

          // Calculate plus-side calibration

            nCal = 0x00;

            nCal =  ADC0_CLP0;

            nCal += ADC0_CLP1;

            nCal += ADC0_CLP2;

            nCal += ADC0_CLP3;

            nCal += ADC0_CLP4;

            nCal += ADC0_CLPS;

 

            nCal = nCal >> 1;

            nCal |= 0x8000;

            ADC0_PG = ADC_PG_PG(nCal);

 

            // Calculate minus-side calibration

            nCal = 0x00;

            nCal =  ADC0_CLM0;

            nCal += ADC0_CLM1;

            nCal += ADC0_CLM2;

            nCal += ADC0_CLM3;

            nCal += ADC0_CLM4;

            nCal += ADC0_CLMS;

 

            nCal    = nCal >> 1;

            nCal    |= 0x8000;

            ADC0_MG = ADC_MG_MG(nCal);

   

            autocal_result = 1;

    }

 

  ADC0_SC3 &= ~ADC_SC3_CAL_MASK;

 

//Restore original settings

 

  ADC0_SC1A = ADC_SC1_AIEN_MASK | 0x4;

  ADC0_SC2 = ADC_SC2_ADTRG_MASK;

 

 

/*End - ADC calibration */

 

  //Configure interrupts

  //Set Priority 2

  // NVIC_IPR3: PRI_1=0x80

  NVIC_IPR3 = (uint32_t)((NVIC_IPR3 & (uint32_t)~(uint32_t)(NVIC_IP_PRI_15(0x3F))) | (uint32_t)(NVIC_IP_PRI_15(0x80)));

  NVIC_ICPR |= 0x00008000; //Clear any pending interrupts

  NVIC_ISER |= NVIC_ISER_SETENA(0x00008000); //Enable ADC0 interrupts

 

  return autocal_result;

}

     

 

I would appreciate your opinion on this matter. Have I overseen something or have I reached the limits of A/D converter?

Thanks in advance!

Original Attachment has been moved to: adc_calibration.txt.zip

Labels (1)
Tags (2)
0 Kudos
5 Replies

165 Views
jeremyzhou
NXP TechSupport
NXP TechSupport

Hi ,

Thank you very much for your focus on Freescale Kinetis product. I'm glad to provide support for you.

First I don't think the ADC calibration results vary cause ADC sample result display on LCD change ± 2.

In my opinion, configure ADC work in 16 bit mode is the mainly reason that cause this phenomenon, you will find the particular ENOB wthen ADC work in 16 bit single-ended mode and it can't access to 16.

So it's reasonable that it exsit a little difference between several ADC results when ADC sample an same input signal.

Hope my support help.
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

1.jpg

0 Kudos

165 Views
bitsplitter
Contributor I

Hello Jeremy,

thanks for your interest in my problem.

I'm running ADC in 16-bit mode. However, I have managed to achieve ENOB ~14 bits after a lot of averaging and that is OK for my application.

I'm not outputting ADC readings on the LCD but values (calculated) based on ADC readings.

Let me explain my application in more details.

I'm constructing a voltage measurement device. When I power it up, it first does the ADC init and the ADC calibration... etc. Then it starts measuring applied voltage and displays it on the LCD in an endless loop. Without restarting the measuring device I can do a voltage measurement calibration using a very precise voltage source and then store the calibration data into eeprom. Afterward the device works perfectly accurate.

However, next time I power up the device it performs the ADC init and ADC calibration again and uses the previously stored eeprom calibration data. However, LCD showings are now slightly different (± 2 least significant digits) although the same voltage is applied to the measuring device (again coming from the very precise voltage source).

Therefore, I've concluded that ADC calibration results in varying calibration data and it affects my application badly because of its high resolution measurement (~14bits) requirement.

Just notice this plus side gain difference coming from two successive ADC calibrations:

33511 --> ADC0_PG

33537 --> ADC0_PG

Can I make this these two values not differ so much or this is just the way it is?

Thanks!

0 Kudos

165 Views
jeremyzhou
NXP TechSupport
NXP TechSupport

Hi ,

Thanks for reply and your explaination.

I'm afraid that you can't use previous calibration result any more after you reset the device. As mentioned in RM,

Calibration must be run, or valid calibration values written, after any reset and before a conversion is initiated.

Regarding to the difference between successive ADC calibration, I'd like to suggest that you'd better let it go and once ADC calibration is ok before ADC work.
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

164 Views
bitsplitter
Contributor I

Hello Jeremy,

I'm not storing ADC auto-calibration data into eeprom but the voltage measurement calibration data as it should be done once in the production phase.

Best regards

0 Kudos

164 Views
jeremyzhou
NXP TechSupport
NXP TechSupport

Hi Slavisa Zlatanovic,

Thanks for your reply.

I think you may misunderstand my opinion. I mean you should not use previous ADC calibration data for current ADC sample operation.

And calibration must be run after any reset or any configuration of ADC change, however one time is enough.

Hope my support could help.
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos