cancel
Showing results for 
Search instead for 
Did you mean: 

ADC converted value error: bit truncation when using DMA

wronskian
Associate II

Hello.
I encountered a truncation error issue while working on a grid-connected converter application with the STM32G474MET6 MCU. To manage multiple ADC channels, I opted for DMA to obtain 12-bit ADC converted values. However, I've noticed a bit truncation error in the converted values, where such LSB of the value remains unchanged even as the analog value varies. Here's an illustrative example:

When Vref = VDDA = 3.3V, and the analog value continuously shifts from 1.65V to 1.68V, the converted values exhibit a step-function behavior. The digital values transition from 2063 (0b 1000 0000 1111) to 2079 (0b 1000 0001 1111), with 'no intermediate values'. Even though the analog value changes, the four LSBs of the converted value persist as 0b1111. I also attached the waveform of bit truncation: the green one is real value and the others are ADC converted values(I apologize for slight difference of scale).

Discovering this error was quite embarrassing, prompting me to explore potential solutions. Initially, I attempted to adjust the ADC module parameters to address the issue. I observed that the truncation error correlates with the ADC's sampling cycle. Increasing the sampling cycle (e.g., from 2.5 cycles to 12.5 cycles) augmented the bit truncation (e.g., from 2 LSBs to 4 LSBs). I also experimented with oversampling to enhance resolution. While the oversampling reduced the bit truncation slightly, a few LSBs remained unchanged, indicating that this may not be a fundamental solution.

The ADC conversion code is currently implemented using HAL functions, as shown below. Additionally, my CUBEMX (.ioc) file can be downloaded at the drive link: https://drive.google.com/file/d/1DkIZht7omcr_Q17ae8uVIGorbue5hK6r/view?usp=sharing 

 

 

 

//////////////h file//////////////
#define ADC1CHANNEL 4 // Ia,Ib,Ic,Idc
#define ADC2CHANNEL 2 // N,NTC
#define ADC3CHANNEL 5 // Ea,Eb,Ec,Vdcp,Vdcn

uint16_t ADC1_Result[ADC1CHANNEL], ADC1_Offset[ADC1CHANNEL];
uint16_t ADC2_Result[ADC2CHANNEL], ADC2_Offset[ADC2CHANNEL];
uint16_t ADC3_Result[ADC3CHANNEL], ADC3_Offset[ADC3CHANNEL];


//////////////c file//////////////
void InitADC(void){
	// ADC gain calculation
	Gain_ACV = RES_DIV_AC*ISO_OP_GAIN*OPAMP_GAIN*ADC3GAIN;
	Gain_ACC = -CUR_SEN_GAIN*OPAMP_GAIN*ADC1GAIN;
	Gain_DCV = RES_DIV_DC*ISO_OP_GAIN*OPAMP_GAIN*ADC3GAIN;
	Gain_DCC = CUR_SEN_GAIN*OPAMP_GAIN*ADC1GAIN;

	Gain_PEV = ISO_OP_GAIN*OPAMP_GAIN*ADC4GAIN;
	Gain_PEC = LEAK_CUR_SEN_GAIN*LEAK_CUR_OPAMP_GAIN*ADC5GAIN;
	Gain_PEVrms = OPAMP_GAIN*ADC2GAIN;
	Gain_NTC = NTC_GAIN*ADC2GAIN;

	ADC_Enable(&hadc1);
	ADC_Enable(&hadc2);
	ADC_Enable(&hadc3);

	HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
	HAL_ADCEx_Calibration_Start(&hadc2, ADC_SINGLE_ENDED);
	HAL_ADCEx_Calibration_Start(&hadc3, ADC_SINGLE_ENDED);

	HAL_ADC_Start_DMA(&hadc1, (uint32_t *) ADC1_Result, ADC1CHANNEL);
	HAL_ADC_Start_DMA(&hadc2, (uint32_t *) ADC2_Result, ADC2CHANNEL);
	HAL_ADC_Start_DMA(&hadc3, (uint32_t *) ADC3_Result, ADC3CHANNEL);
}

void ADC(void){
	while(adc1wait || adc2wait || adc3wait)
		;

	Ia = (float)(ADC1_Result[0] - ADC1_Offset[0]) * Gain_ACC;
	Ib = (float)(ADC1_Result[1] - ADC1_Offset[1]) * Gain_ACC;
	Ic = (float)(ADC1_Result[2] - ADC1_Offset[2]) * Gain_ACC;
	Idc = (float)(ADC1_Result[3] - ADC1_Offset[3]) * Gain_DCC;

	Ea = (float)(ADC3_Result[0] - ADC3_Offset[0]) * Gain_ACV;
	Eb = (float)(ADC3_Result[1] - ADC3_Offset[1]) * Gain_ACV;
	Ec = (float)(ADC3_Result[2] - ADC3_Offset[2]) * Gain_ACV;
	Vdcp = (float)(ADC3_Result[3] - ADC3_Offset[3]) * Gain_DCV;
	Vdcn = (float)(ADC3_Result[4] - ADC3_Offset[4]) * Gain_DCV;

	adc1wait = 1; adc2wait = 1; adc3wait = 1; adc4wait = 1; adc5wait = 1;
}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {
	if (hadc == &hadc1) {
		if (adc1wait) adc1wait = 0;
	}
	else if (hadc == &hadc2) {
		if (adc2wait) adc2wait = 0;
	}
	else if (hadc == &hadc3) {
		if (adc3wait) adc3wait = 0;
	}
	else if (hadc == &hadc4) {
		if (adc4wait) adc4wait = 0;
	}
	else if (hadc == &hadc5) {
		if (adc5wait) adc5wait = 0;
	}
	else ;
}

 

 

 

I would greatly appreciate any guidance or suggestions to help resolve the truncation problem.

Best Regards,

Paul

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

This has come up in the past a few times. If I recall correctly, the issue was always on custom hardware where VDDA or VREF+ wasn't stable. Do you have a capacitor on this line? Can you share the schematic?

 

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

5 REPLIES 5
SGree.2
Associate II

Hey Paul - what's actually driving the ADCs here? It's a long shot, but if it's from a high impedance source (i.e. voltage divider, unbuffered DAC output, anything with a resistor in the chain, etc), then your ADC sampling is much much too fast. For a 2.5 cycle sample on a fast ADC channel, you're limited to 100 ohm max input resistance for 12-bit resolution - so your loss of resolution may be caused by that. What happens if you max out the sampling, at 640.5 cycles

Also - your ADC1/2/3_Result buffers aren't marked as volatile - this can/will cause issues down the line.

MasterT
Lead

Where is definition of 

Gain_ACC

?

TDK
Guru

This has come up in the past a few times. If I recall correctly, the issue was always on custom hardware where VDDA or VREF+ wasn't stable. Do you have a capacitor on this line? Can you share the schematic?

 

If you feel a post has answered your question, please click "Accept as Solution".

I appreciate your helpful response.

I discovered that the voltage at the VDDA pin was unstable. Upon investigation, I determined that the 3.3V regulator IC had insufficient output power for the demands of the VDDA pin. When I switched to a regulator IC with a higher output capacity, the truncation error vanished. It's truly remarkable! I believe the error occurred because there wasn't enough power available for the ADC conversion, which explains why the truncation error worsened as I increased the ADC sampling cycle.

I'm immensely grateful for your assistance.

Paul.

I appreciate your helpful response.

I observed that increasing the sampling cycle deteriorates the truncation error. However, the issue has been successfully resolved. The root cause was insufficient power supply to the VDDA pin. Once I addressed this power supply issue, I was able to increase the sampling cycle as per your advice.

I'm immensely thankful for your help.

Paul.