2025-04-22 11:02 PM
I have a +30V -30V input to be fed to STM32H7 ADC 16-bit
I tried using a 2 resistor potential divider using 33K 3.3K ; 1K 100E, 1M 100K, resistor combinations but the output is not correctly read by the ADC. (For 3V input, ADC reads from 2.2V to 3.2V randomly fluctuating) Not constant
But if I bypass the divider circuit and feed an input less than 3.3V to the ADC pin directly, it reads perfectly (For 3V input, it reads 2.9999).
Should sampling time affect the resistor values?
2025-04-22 11:29 PM - edited 2025-04-23 1:37 AM
Random fluctuations should not happen. Check if the power supply of the MCU and the ADC (VDDA) and the reference voltage are stable. What did you measure?
What happens if you supply a stable voltage from a low impedance source? Such as a 1.2V battery or a bench power supply? Same fluctuations?
Did you read the datasheet of the MCU? The ADC is not designed for high impedance sources since its sample and hold circuit loads the signal. At least decouple the output of the voltage divider with a capacitor. But preferably use a buffer.
Did you calibrate the ADC?
2025-04-23 1:06 AM
I tried with an input from GPIO pin of a Nucleo board. Direct input to ADC pin works fine but if checked after the divider it starts getting erratic.
Made an opamp buffer after divider circuit using general purpose LM358, but still fluctuating. Will try with a precision opamp.
How about this divider circuit? Will also try a buffer after this.
2025-04-23 1:36 AM - edited 2025-04-23 5:34 AM
The divider circuit is not the problem. If the voltage is stable its equivalent circuit is an ideal voltage source with a series resistance. It will be loaded by the ADC so the reading won't be correct, but it should not fluctuate. You already tried a buffer with a unity gain stable OPAMP and that didn't change the result.
Could you please answer my other questions?
2025-04-23 5:35 AM
The ADC will never read a constant value, you will always have some noise, at 16 bits at least. But 1 V of noise is excessive.
You can see general tips on improving accuracy here:
How to optimize the ADC accuracy in the STM32 MCUs - Application note
> Direct input to ADC pin works fine but if checked after the divider it starts getting erratic.
Suggests something else at play here.
How is this set up? On a breadboard with questionable connections? Pictures would help.
2025-04-24 12:25 AM - edited 2025-04-27 9:43 PM
An existing PCB is used with wires taken out from those ADC pins and connected to the circuit on a stripboard.
VIN_A = 10V from a calibrator source.
This is the read ADC output count with voltage. This trend remains almost the same with or without the buffer.
Count | Voltage |
43172 | 2.1739161 |
43172 | 2.1739161 |
42967 | 2.16359329 |
42967 | 2.16359329 |
43194 | 2.17502403 |
43194 | 2.17502403 |
43053 | 2.16792393 |
43053 | 2.16792393 |
42881 | 2.1592629 |
42881 | 2.1592629 |
43195 | 2.17507434 |
43195 | 2.17507434 |
43082 | 2.16938424 |
43082 | 2.16938424 |
43101 | 2.17034101 |
43101 | 2.17034101 |
43201 | 2.17537642 |
43201 | 2.17537642 |
43118 | 2.17119694 |
43118 | 2.17119694 |
43077 | 2.16913247 |
43077 | 2.16913247 |
43110 | 2.17079425 |
43110 | 2.17079425 |
43112 | 2.17089486 |
43112 | 2.17089486 |
43199 | 2.1752758 |
43199 | 2.1752758 |
43214 | 2.17603111 |
43214 | 2.17603111 |
43083 | 2.16943455 |
43083 | 2.16943455 |
43033 | 2.16691685 |
43033 | 2.16691685 |
43046 | 2.16757154 |
43046 | 2.16757154 |
43038 | 2.16716862 |
43038 | 2.16716862 |
43188 | 2.17472172 |
43188 | 2.17472172 |
43145 | 2.17255664 |
43145 | 2.17255664 |
43172 | 2.1739161 |
43172 | 2.1739161 |
43085 | 2.1695354 |
43085 | 2.1695354 |
43008 | 2.165658 |
43008 | 2.165658 |
43167 | 2.17366433 |
43167 | 2.17366433 |
42969 | 2.16369414 |
42969 | 2.16369414 |
43129 | 2.17175102 |
43129 | 2.17175102 |
42978 | 2.16414738 |
42978 | 2.16414738 |
42971 | 2.16379476 |
42971 | 2.16379476 |
43145 | 2.17255664 |
43145 | 2.17255664 |
43231 | 2.17688704 |
43231 | 2.17688704 |
43007 | 2.16560769 |
43007 | 2.16560769 |
43097 | 2.17013955 |
43097 | 2.17013955 |
43097 | 2.17013955 |
43097 | 2.17013955 |
43123 | 2.17144871 |
43123 | 2.17144871 |
43200 | 2.17532611 |
43200 | 2.17532611 |
43119 | 2.17124748 |
43119 | 2.17124748 |
43142 | 2.17240548 |
43142 | 2.17240548 |
43034 | 2.16696739 |
43034 | 2.16696739 |
43014 | 2.16596031 |
43014 | 2.16596031 |
43121 | 2.17134809 |
43121 | 2.17134809 |
43026 | 2.16656446 |
43026 | 2.16656446 |
43161 | 2.17336226 |
43161 | 2.17336226 |
43123 | 2.17144871 |
43123 | 2.17144871 |
43123 | 2.17144871 |
43123 | 2.17144871 |
42975 | 2.16399622 |
42975 | 2.16399622 |
43109 | 2.17074394 |
43109 | 2.17074394 |
43070 | 2.16878009 |
43070 | 2.16878009 |
43166 | 2.17361403 |
43166 | 2.17361403 |
43085 | 2.1695354 |
2025-04-24 1:17 AM
@Jonah9Veh wrote:But if I bypass the divider circuit and feed an input less than 3.3V to the ADC pin directly, it reads perfectly (For 3V input, it reads 2.9999).
ADC can output stable results only if its saturated...
Internal ADC are always noisy, especially when Reference voltage has no Vref- differential part.
Just do oversampling & averaging
2025-04-24 1:38 AM - edited 2025-04-24 2:08 AM
I noticed a few things.
First off all I see a lot of duplicate values. Are you sure each data point is one sample or are you saving the values faster then they are sampled?
plot of counts
The histogram (bin size 16 counts) doesn't look particularly like Gaussian (noise).
histogram of counts (bin size 16 counts)
Perhaps there aren't enough samples to conclude this. But in my experience you should see noise levels of 1 or maybe 2 counts. This spread of 350 counts is way too large!
FFT doesn't show any particular frequency stand out, but there are not enough samples to be sure of this.
@Jonah9Veh wrote:
- No calibration done. Can it be done before the ADC reads something stable? How to calibrate it? Please help with that.
If you use LL you need to call LL_ADC_StartCalibration().
Example:
LL_ADC_Disable(ADC1);
LL_ADC_SetChannelPreSelection(ADC1, LL_ADC_CHANNEL_16);
LL_ADC_StartCalibration(ADC1, LL_ADC_CALIB_OFFSET_LINEARITY, LL_ADC_SINGLE_ENDED);
/* Wait for calibration completion */
while (LL_ADC_IsCalibrationOnGoing(ADC1) != 0UL)
{
;
}
LL_ADC_Enable(ADC1);
while ((ADC1->ISR & ADC_ISR_ADRDY) != ADC_ISR_ADRDY);// On this STM32 series, after ADC enable, a delay for ADC internal analog stabilization is required before performing a ADC conversion start.
LL_ADC_REG_StartConversion(ADC1);
For HAL you need to call HAL_ADCEx_Calibration_Start().
@Jonah9Veh wrote:An existing PCB is used with wires taken out from those ADC pins and connected to the circuit on a stripboard.
How long are the wires?
@Jonah9Veh wrote:
- Multimeter reads a constant 2.172V output after the divider and buffer. Input to ADC is 2.172V.
A multimeter on voltage mode reads a DC voltage. It doesn't measure noise or ripple. You need an oscilloscope for that.
2025-04-24 1:45 AM
@MasterT wrote:
@Jonah9Veh wrote:But if I bypass the divider circuit and feed an input less than 3.3V to the ADC pin directly, it reads perfectly (For 3V input, it reads 2.9999).
ADC can output stable results only if its saturated...
Exactly.
@MasterT wrote:Internal ADC are always noisy, especially when Reference voltage has no Vref- differential part.
Just do oversampling & averaging
Not that noisy! 350 counts between max and min. That's a lot.
I disagree with averaging something that noisy. The source of the noise needs to be fixed first. Then the remaining noise (1-2 counts) can be averaged to reduce noise and optionally increase resolution.
2025-04-24 1:46 AM
@TDK wrote:
You can see general tips on improving accuracy here:
How to optimize the ADC accuracy in the STM32 MCUs - Application note.
+ AN5354 " Getting started with the STM32H7 Series MCU 16-bit ADC"