Skip to main content
MKhak
Associate
January 9, 2020
Question

My problem: stm32h743 ADC does not convert small signals(about 1-5mv) correctly

  • January 9, 2020
  • 23 replies
  • 18248 views

I configure ADC1 and ADC2 in Dual mode, 16 bit resolution, differential-ended. I use CubeMx to initialize ADC. I want measure voltage and current. My project samples the signals and then sends them to the computer for plotting and logging by the WiFi module. When the amplitude of voltage and current are too small, the ADC does not convert the signals correctly. I have attached figures of a logged signal. In these figures the amplitude of voltage changes from 1mV to 9 mV. Figures show that, a part of the signal has not been converted correctly.

0690X00000BvlokQAB.png

This behaviour is seen in other channel that you can see in below figure.

0690X00000BvsGfQAJ.png

In my hardware, the signal first passes through a differential-ended amplifier (AD8132) and then enters the ADC. The common mode voltage at the amplifier outputs is Vref/2(There is some potential difference (about a few millivolts) between the amplifier outputs). Schematic of the amplifier is attached. 

0690X00000BvlopQAB.png

ADCs are initialized by below functions. Sampling frequency is 12KHz.

static void MX_ADC1_Init(void)

{

 ADC_MultiModeTypeDef multimode = {0};

 ADC_ChannelConfTypeDef sConfig = {0};

 hadc1.Instance = ADC1;

 hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV6;

 hadc1.Init.Resolution = ADC_RESOLUTION_16B;

 hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;

 hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;

 hadc1.Init.LowPowerAutoWait = DISABLE;

 hadc1.Init.ContinuousConvMode = DISABLE;

 hadc1.Init.NbrOfConversion = 3;

 hadc1.Init.DiscontinuousConvMode = DISABLE;

 hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T6_TRGO;

 hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_FALLING;

 hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;

 hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;

 hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;

 hadc1.Init.OversamplingMode = ENABLE;

 hadc1.Init.Oversampling.Ratio = 31;

 hadc1.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_5;

 hadc1.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;

 hadc1.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;

 if (HAL_ADC_Init(&hadc1) != HAL_OK)

 {

  Error_Handler();

 }

 multimode.Mode = ADC_DUALMODE_REGSIMULT_INJECSIMULT;

 multimode.DualModeData = ADC_DUALMODEDATAFORMAT_32_10_BITS;

 multimode.TwoSamplingDelay = ADC_TWOSAMPLINGDELAY_1CYCLE;

 if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)

 {

  Error_Handler();

 }

 sConfig.Channel = ADC_CHANNEL_2;

 sConfig.Rank = ADC_REGULAR_RANK_1;

 sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5;

 sConfig.SingleDiff = ADC_DIFFERENTIAL_ENDED;

 sConfig.OffsetNumber = ADC_OFFSET_NONE;

 sConfig.Offset = 0;

 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

 {

  Error_Handler();

 }

 sConfig.Channel = ADC_CHANNEL_3;

 sConfig.Rank = ADC_REGULAR_RANK_2;

 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

 {

  Error_Handler();

 }

 sConfig.Channel = ADC_CHANNEL_4;

 sConfig.Rank = ADC_REGULAR_RANK_3;

 if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)

 {

  Error_Handler();

 }

 HAL_ADCEx_Calibration_Start(&hadc1, LL_ADC_CALIB_LINEARITY, ADC_DIFFERENTIAL_ENDED); 

}

static void MX_ADC2_Init(void)

{

 ADC_ChannelConfTypeDef sConfig = {0};

 hadc2.Instance = ADC2;

 hadc2.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV6;

 hadc2.Init.Resolution = ADC_RESOLUTION_16B;

 hadc2.Init.ScanConvMode = ADC_SCAN_ENABLE;

 hadc2.Init.EOCSelection = ADC_EOC_SEQ_CONV;

 hadc2.Init.LowPowerAutoWait = DISABLE;

 hadc2.Init.ContinuousConvMode = DISABLE;

 hadc2.Init.NbrOfConversion = 3;

 hadc2.Init.DiscontinuousConvMode = DISABLE;

 hadc2.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;

 hadc2.Init.Overrun = ADC_OVR_DATA_PRESERVED;

 hadc2.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;

 hadc2.Init.OversamplingMode = ENABLE;

 hadc2.Init.Oversampling.Ratio = 31;

 hadc2.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_5;

 hadc2.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;

 hadc2.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE;

 if (HAL_ADC_Init(&hadc2) != HAL_OK)

 {

  Error_Handler();

 }

 sConfig.Channel = ADC_CHANNEL_18;

 sConfig.Rank = ADC_REGULAR_RANK_1;

 sConfig.SamplingTime = ADC_SAMPLETIME_8CYCLES_5;

 sConfig.SingleDiff = ADC_DIFFERENTIAL_ENDED;

 sConfig.OffsetNumber = ADC_OFFSET_NONE;

 sConfig.Offset = 0;

 if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)

 {

  Error_Handler();

 }

 sConfig.Channel = ADC_CHANNEL_5;

 sConfig.Rank = ADC_REGULAR_RANK_2;

 if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)

 {

  Error_Handler();

 }

 sConfig.Channel = ADC_CHANNEL_2;

 sConfig.Rank = ADC_REGULAR_RANK_3;

 if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)

 {

  Error_Handler();

 }

 HAL_ADCEx_Calibration_Start(&hadc2, LL_ADC_CALIB_LINEARITY, ADC_DIFFERENTIAL_ENDED);

}

This topic has been closed for replies.

23 replies

waclawek.jan
Super User
January 9, 2020

Did you perform the differential-mode calibration, as outlined in Calibration (ADCAL, ADCALDIF, ADCALLIN, ADC_CALFACT) subchapter of the ADC chapter in Reference Manual?

I don't use/understand Cube/HAL.

JW

MKhak
MKhakAuthor
Associate
January 10, 2020

Thank you for your attention to my problem. I perform the differential-mode calibration. This line does it.

 HAL_ADCEx_Calibration_Start(&hadc2, LL_ADC_CALIB_LINEARITY, ADC_DIFFERENTIAL_ENDED);

I test my Program with the differential-mode calibration and without it. In both cases there is a problem mentioned above.

Ozone
Principal
January 10, 2020

> I have attached images of a converted signal. In these figures the amplitude of voltage changes from 1mV to 9 mV.

> Figures show that, a part of the signal has not been converted correctly.

I don't understand how you got to that.

The converted signal would numerical values in memory or a register, not a scope-able voltage curve.

Re-converting it via DAC would introduce further artifacts.

MKhak
MKhakAuthor
Associate
January 10, 2020

Excuse me for the incomplete description. My project samples the voltage and current and sends sampled data to the computer using the WiFi module. In PC, a software plots data.

Chris1
Associate II
January 10, 2020

Are your results worse than the claimed performance in the datasheet? There's some significant error numbers shown there, for example +/-10 or +/-16 LSB total unadjusted error, +/-4 or +/-6 LSB linearity error, etc.

MKhak
MKhakAuthor
Associate
January 11, 2020

I don't think this problem is related to unadjusted error or linearity error. I added another figure to my description. for 1mV amplitude the result is good. when the amplitude of signal is increased, a distortion is occured in sampled data.

Uwe Bonnes
Chief
January 11, 2020

Did you have a look with the scope on the signals after the AD8132? Maybe the problems are before the STM32H7?

MKhak
MKhakAuthor
Associate
January 11, 2020

I looked with the scope on the signals at the input of ADC. Analog signal didn't have any problem

waclawek.jan
Super User
January 11, 2020

IMO this is an offset error - i.e. input of +-0mV is not converted to 0x0000 but to some small offset, e.g. +-0x0010 - compounded with an offset in center of the sinus, whether its source is internal or external.

This is IMO specific to the differential mode; so you maybe might want to convert the singal to single-ended by the external circuitry and convert it as such; and then remove the DC component by some suitable method in software.

JW

MKhak
MKhakAuthor
Associate
January 11, 2020

a

waclawek.jan
Super User
January 11, 2020

Which revision of the chip are you using?

JW

MKhak
MKhakAuthor
Associate
January 11, 2020

I think, it is RevY.

0690X00000BvsXgQAJ.jpg

January 11, 2020
MKhak
MKhakAuthor
Associate
January 11, 2020

Thank you for introducing this link.

Base on this link,There is a problem in stm32h743 RevY and I have to migrate to stm32h743 RevV.

Unfortunately, stm32h743 RevV is not available to me and I can't test it.

Does anyone have any opinion about stm32h743 RevV?

January 11, 2020

Did you check if both of the differential inputs are above 0 relative to AGND?

Also, do you still see this problem without oversampling?

MKhak
MKhakAuthor
Associate
January 13, 2020

I've tested program without oversampling before, but there was above problem.

csing.1
Visitor II
September 12, 2020

I have exactly the same problem. Did you solve it? In my case , the single ended input is provided around 1.65V. But it still works like your fig

MKhak
MKhakAuthor
Associate
September 15, 2020

I can't solve my problem

Dvorak.Peter
Associate II
September 12, 2020

> stm32h743 ADC does not convert small signals(about 1-5mv) correctly

https://www.eevblog.com/forum/microcontrollers/stm32h7-adc-performance-ya-gotta-read-the-fine-print!/