2018-06-19 05:13 AM
Hello everyone,
I'm currently trying to get as accurate ADC values as possible from a STM32F072. I'm using the NUCLEO-F072RB and wanted to use the internal stored reference voltage value for calibration. But I'm already off when I use this to calculate my actual VDDA for further ADC measurement. I double checked all my voltages with a calibrated multimeter and oscilloscope directly on the pins and with smalles possible ground loops. There are no spikes/drops in the voltage due to the ADC measurement and the ripple and noise is at around 5 mVpp. I also added 2x 10 nF and 1x 10 uF to C30 (100 nF) on AVDD on the nucleo. I tried all sampling times for the ADC without any change in the results and of course use 12-Bit. I do not want to read the value of the internal Vref-Voltage as it is not accurate (min 1.2V, typ 1.23V, max 1.25V).
So even after taking care of any possible error sources I'm getting a wrong value for my calculated AVDD voltage. I measured this with two multimeters to be 3.310V at 25�C. The calculated value from the STM32 is ~3.296 V, which is 14 mV off. This might be too much for measurements of voltages after a voltage divider, even when considering the 1% tolerance of the resistors. I read about a accuracy of ~1 mV (without voltage divider), so I'm curious how to achieve this when the reference value is not accurate.
This are parts of the code from the used test program:
// ADC self calibration, has to be done before any ADC Start/Enable
while(HAL_ADCEx_Calibration_Start(&hadc) != HAL_OK);// values for calculation of actually VDDA-supply and reference voltagevolatile uint32_t VREFINT_CAL, VREF_3V3 = 330000;const uint16_t *p = (uint16_t *)0x1FFFF7BA; // 2 Byte at this address is VRefInt @3.3V/30�CVREFINT_CAL = *p; // read the value at pointer address// Start ADC with DMA supportvolatile uint16_t adc_value[4] = {0, 0, 0, 0};HAL_ADC_Start_DMA(&hadc, (uint32_t*)adc_value, 4); while (1){ //toggle LED HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); HAL_Delay(50); // calculate 3.3 V supply voltage with the factory stored VREFINT_CAL value // adc_value[2] contains the raw ADC_IN17 value of the internal voltage reference (~1530) VREF_3V3 = (330000 * VREFINT_CAL) / adc_value[2]; // VREFINT_CAL = 1529 // adc_value[2] = 1530 // VREF_3V3 = ~329568 (~3.29568 V calculated)}#accuracy #nucleo-f072rb #adc #calibration #stm32f0 #internal-voltage-reference2018-06-20 07:12 AM
USB powered Nucleo
and the two pins OSB_DM, DP are at 5V levels ? or 3V ? can you see on the scope ?
can you remove the USB connector and still see the readings ?
2018-06-20 08:13 AM
The USB data lines are a kind of a differential signal and do not have a specific level to GND. Scope shows minimum levels of -500 mV and +3.5 V in referece to GND. But this USB signal is not connected to the microcontroller I'm trying to get the ADC working. On the Nucleo boards, there is a STM32F103 that is connected via USB and works as STLink. It than is connected via UART (3.3V) to the STM32F072
Why do you think that the +5V are causing such problems? Can you provide a source for that?
2018-06-20 08:42 AM
Some threads were discussing 5V tolerant pins pulling internally on the ADC rail, thereby affecting the readings substantially
just a thought.
2018-06-21 06:52 AM
Set up an application-level calibration that converts the voltage back into whatever engineering unit is actually being measured.
Did you check the data sheet to see what the specified accuracy of the ADC is? Running the numbers shows the measurement is off by 0.4% of reading. I regard that as excellent.
For another implementation angle, I run the ADC of STM32 processors using DMA and very fast. Then do an Infinite Impulse Response filter in binary logic in the interrupt. Super fast and super stable. The read voltage is converted to whatever is needed (Voltage, currrent, temperature, etc...) in the application code along with a final calibration stage that uses different techniques to address end-to-end the non-linearities and inaccuracies of the signal.
2019-01-09 01:06 PM
It sounds like I'm having a similar problem on my STM32F070CB. I put 0.6V into AN1 CH9 and it reads 679 Counts (which translates to 0.54V). At 0.6V I should be reading 740 counts. VDDA is 3.319V. I have confirmed my voltage in with 2x multimeters and an O-Scope. DId you ever find a solution?
2019-01-28 06:40 PM
I also have the same issue, exactly the same, down to the 14 mV (from the original poster). It could be related to DMA usage, the DMA automatic conversion sequence might be the issue here. I haven't had time to check yet.
2019-01-28 10:17 PM
2019-01-29 06:29 AM
Check the data sheet for your parts against the specs the system needs. If the design needs the ADC to be accurate to 1 bit, it's not going to make spec. Checking the M4F I'm using, it'll be 3-4 LSB at best and on top of Vref errors and noise.
Four suggestions:
Use a precision supply on Vref
Apply the cal from Vrefin_cal
Calibrate each unit in production
Add a better external ADC
2019-01-30 06:04 AM
Figured out the solution to this, you need to calibrate the ADC anytime you restart the MCU. Use this command if you are using the HAL libraries: HAL_ADCEx_Calibration_Start(&hadc);
2019-01-31 10:56 PM
I am doing that :(
I'm using a different library, I've compared the source of the HAL library to what I'm using and its equivilent. The ADC is off before ADCAL is set as it should be.