cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7: jumps in ADC transfer curve; both with Self-calibration, and FactoryLoad

lura
Visitor

Dear ST experts,

we're currently struggling with getting acceptable ADC performance with some of our samples of the STM32H753VIT ADC2. Our setup includes:

  • ADC2 works in Independent mode
  • using Scan Conversion Mode, 7 Channels (3, 5, 9, 10, 15, 18, 19)
  • 14-bit resolution, 16x oversamplig (each channel), 2 bit right-shift for oversampling
  • ADC2-Clock is 37,5 MHz, generated by PLL2P, before internal division by 2, Asynchronous clock mode divided by 1
  • Continuous Conversion Mode and Discontinuous Conversion Mode are both disabled
  • TIM15 triggers ADC2 every 100 µs to scan all channels
  • DMA Circular Mode
  • VRef = 3.0 Volt, external
  • We set up a minimal STM CubeIDE project to verify the described behaviour

While more than half of our parts work more or less as advertised, but with some parts we reproducibly fail to generate decent calibration values; regardless of whether we use the factory-load linear calibration values (by using

HAL_ADCEx_LinearCalibration_FactorLoad(&hadc2);

) or doing a self-calibration with

HAL_ADCEx_Calibration_Start(&hadc2, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED);

 

For testing, we use to apply a slow (1Hz) ramp signal to ADC2 channel3 while the ADC is running, buffer a large number of results in memory, stop the ADC when the buffer is filled, and finally read out the buffer via UART.

From the recorded ADC values, we cut out one ramp, and subtract the linear trend line. With the "bad" STM32H752 samples, we always get rather big jumps in the error curve, like this one:

stm32h7_selfcalib_bad_01.png

Notably, the jumps seem to occur at multiples of 0x2000. So, we concluded that the calibration for the bit weights does not work properly with these examples.

Our main application is to accurately sinusodial signals around 0x8000, which gets ugly whenever the amplitude is small (because we then work in a small interval around the main dicontoninuity at 0x8000)

 

When investigating the issue, we have read out both the factory calibration value, and the linear calibration values resulting from self-calibrating, and noticed that all 10-bit-parts of the 160-bit linearity calibration factor lay around 0x200 (+/- roughly 0x1B). We conjectured that 0x200 may be a "neutral" value, and manually set all 10-bit-parts to 0x200:

  uint32_t lincalbuf[ADC_LINEAR_CALIB_REG_COUNT] = {
		  0x20080200u,
		  0x20080200u,
		  0x20080200u,
		  0x20080200u,
		  0x20080200u,
		  0x00000200u,
  };
  HAL_ADCEx_LinearCalibration_SetValue(&hadc2, lincalbuf);

A bit surprisingly, this gave us much a more "continuous" error curve, with all our parts ("good" and "bad"), e.g.

stm32h7_manualcalib_better.png

Thus we have a few questions:

i) Can someone tell us what is exactly the meaning of the 10-bit parts of the linear calibration factor, preferably with some formulae? By experimenting, we concluded, that the lower eight 10-bit parts represent the bit weights of the upper 8 ADC bits. Is this correct?

ii) Did we miss something when calibrating the ADC, which may explain the bad behaviour with some parts?

iii) Are there some risks when we use our "manual" calibration values (16 times 0x200) that we may not be aware of?

 

Best Regards,
Lukas Rauber

 

1 REPLY 1
MasterT
Lead

Very unlikely internal whereabouts of adc ever be disclosed, proprietary /patented /etc.

I'm curios how exactly you drive adc inputs, mind to show circuits? Draft, hand sketched ?