Skip to main content
meghasb
Associate III
December 23, 2022
Question

wrong voltage reading

  • December 23, 2022
  • 6 replies
  • 2719 views

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);

0693W00000Y6maFQAR.png

This topic has been closed for replies.

6 replies

S.Ma
Principal
December 23, 2022

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.

Javier1
Principal
December 23, 2022

AND, ground the mcu with the same ground as R1

hit me up in https://www.linkedin.com/in/javiermuñoz/
meghasb
meghasbAuthor
Associate III
December 23, 2022

Got it.. thanku

Javier1
Principal
December 23, 2022

what do you see if you remove the voltage divider and tie the ADC to 3v3?

hit me up in https://www.linkedin.com/in/javiermuñoz/
gbm
Super User
December 23, 2022

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. :)

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
Piranha
Principal III
January 8, 2023

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);