2022-12-22 10:57 PM
Hi,
i'm trying to read voltage through voltage divider circuit, o/p voltage is 3.2, but i could read only around 2.7, can some help whats wrong with the code
note: R1=6.8K ohm and R2=12K ohm.
im attaching circuit and code.
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
// get ADC value
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
raw=HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
data= (3.3*raw/4095);
uint8_t length= sprintf(msg, "%.3lf\r\n\0", data);
HAL_UART_Transmit(&huart1, msg, length, 100);
2022-12-22 11:26 PM
Real world hardly is ideal.
When ADC is used to read the divider, during the sample and hold time, it will be equivalent to a low pass RC filter, which values are usually in the electrical adc table in datasheet.
Run calibration and put a cap to ground, or max out the sampling time to get closer.
If the chip has vdda pin make sure it is supplied.
2022-12-22 11:46 PM
AND, ground the mcu with the same ground as R1
2022-12-23 12:11 AM
Got it.. thanku
2022-12-23 01:31 AM
what do you see if you remove the voltage divider and tie the ADC to 3v3?
2022-12-23 01:43 AM
What you are trying to display (incorrectly) is the voltage at ADC input, not at the input of voltage divider.
With 12k/6k8 voltage divider, the proper formula for voltage in mV in your case is:
Vin_mV = adcval * Vdd_mV * (120 + 68) / 68 / 4096;
where Vdd_mV should be measured by acquiring Vref channel but for start it may be assumed to be 3300. Note that no floating point math is needed if you stick to mV instead of Volts. 🙂
2023-01-07 05:53 PM
It's better to avoid the additional division and ensure the calculation is always done with 32-bit integers:
Vin_mV = (uint32_t)adcval * Vdd_mV * (120 + 68) / (68 * 4096);
And even better to do the same with a correct rounding:
#define DIVU_ROUND(n, d) ( ((n) + (d) / 2) / (d) )
Vin_mV = DIVU_ROUND((uint32_t)adcval * Vdd_mV * (120 + 68), 68 * 4096);