3

I want to convert ADC Values to float numbers. This is my code:

uint32_t ADCValue;
char str[15];

          ADCValue = HAL_ADC_GetValue(&hadc1);
          ADCValue=ADCValue*3.3/4095;
          sprintf(str, "%d", Voltage);
          HAL_UART_Transmit(&huart2, (uint8_t*)(&str), 6, 100);
          HAL_UART_Transmit(&huart2, (uint8_t*) "\n\r", 2, 100);
          HAL_Delay(500);

I am reading value of 4095 at 3.3V but I am transmitting 3 to buffer. I want to transmit exact value of voltage.

coollime
  • 147
  • 1
  • 3
  • 11

4 Answers4

6

There is no apparent reason why you need to use float numbers here in the first place. They are needlessly slow. Simply do this:

uint32_t millivolts = ADCValue*3300/4095.

For an input of 4095, you get the result 3299mV. This is possibly more accurate than what you would get through float numbers, because of floating-point inaccuracy.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • While I agree that floats are not necessary here, there is no reason why they would be less accurate here. Unless you back it up with something, this answer would be better of without such remark. – user694733 Jan 13 '17 at 10:44
  • In case of using CMSIS DSP float functions we have to convert ADC output to float. This is bad and make ADC DMA useless, What if hardware could output float directly. – mohammadsdtmnd May 25 '22 at 05:04
5

You probably want this:

ADCValue = HAL_ADC_GetValue(&hadc1);
float fADCValue = (float)ADCValue*3.3 / 4095.0;
int txlength = sprintf(str, "%.2f", fADCValue);
HAL_UART_Transmit(&huart2, (uint8_t*)(&str), txlength, 100);
HAL_UART_Transmit(&huart2, (uint8_t*) "\n\r", 2, 100);
HAL_Delay(500);

Caution: this only works if the float type is available on your platform.

If floating point is not available you can use this:

ADCValue = HAL_ADC_GetValue(&hadc1);
ADCValue = ADCValue * 330 / 4095;
int len = sprintf(str, "%d.%02d", ADCValue / 100, ADCValue % 100);
HAL_UART_Transmit(&huart2, (uint8_t*)(&str), leb, 100);
HAL_UART_Transmit(&huart2, (uint8_t*) "\n\r", 2, 100);

This is a quick hack and there is certainly room for improvement.

Demonstration here.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
0

This should do the trick

float Adcvalue_f;
uint32_t ADCValue;
char str[15];
....
ADCValue = HAL_ADC_GetValue(&hadc1); 
ADCValue_f =ADCValue*3.3/4095;
sprintf(str, "%2.2f", AdcValue_f);   //Adjust the .2 as per required precision
HAL_UART_Transmit(&huart2, (uint8_t*)(&str), 6, 100);
HAL_UART_Transmit(&huart2, (uint8_t*) "\n\r", 2, 100);
Rishikesh Raje
  • 8,556
  • 2
  • 16
  • 31
0

In addition to other fine answers, consider:

Integer division truncates the factional part of the mathematical quotient.

Instead, perform a rounded integer division. With unsigned integer math, add half the divisor before the division.

// ADCValue=ADCValue*3.3/4095;

unsigned Voltage = // millivolts
Voltage = (ADCValue*3300 + 4095/2)/4095.
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256