cancel
Showing results for 
Search instead for 
Did you mean: 

Measuring temperature - voltage is off by factor of 2ish

c_shearer_cooper
Associate III

I'm running a STM32G474RET6 on a Nucleo G474RE board, and trying to read the internal temperature.

I set up ADC1 with 2 ranks (the temperature and the vrefint) like so (not including the error checking and comments for better readability):

 

hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; hadc1.Init.Resolution = ADC_RESOLUTION_12B; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.GainCompensation = 0; hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; hadc1.Init.LowPowerAutoWait = DISABLE; hadc1.Init.ContinuousConvMode = DISABLE; hadc1.Init.NbrOfConversion = 2; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.DMAContinuousRequests = DISABLE; hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED; hadc1.Init.OversamplingMode = DISABLE; multimode.Mode = ADC_MODE_INDEPENDENT; HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode); sConfig.Channel = ADC_CHANNEL_TEMPSENSOR_ADC1; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5; sConfig.SingleDiff = ADC_SINGLE_ENDED; sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.Offset = 0; HAL_ADC_ConfigChannel(&hadc1, &sConfig); sConfig.Channel = ADC_CHANNEL_VREFINT; sConfig.Rank = ADC_REGULAR_RANK_2; HAL_ADC_ConfigChannel(&hadc1, &sConfig); TemperatureData.StoredVolt = *((uint16_t *) 0x1FFF75AA); HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
View more

 

 

I then read the 2 ADC values:

 

FirstADC = true; HAL_ADC_Start_IT(hadc1); void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) { BaseType_t xHigherPriorityTaskWoke = pdFALSE; if (FirstADC) { TemperatureData.TempSensorRaw = HAL_ADC_GetValue(hadc); FirstADC = false; } else { TemperatureData.VoltRefRaw = HAL_ADC_GetValue(hadc); HAL_ADC_Stop_IT(hadc); TemperatureData.VoltRef = __HAL_ADC_CALC_VREFANALOG_VOLTAGE(TemperatureData.VoltRefRaw, hadc->Init.Resolution); TemperatureData.Temperature = __HAL_ADC_CALC_TEMPERATURE(TemperatureData.VoltRef, TemperatureData.TempSensorRaw, hadc->Init.Resolution); TemperatureData.State = hadc->State; TemperatureData.ErrorCode = hadc->ErrorCode; TemperatureData.Success = true; } portYIELD_FROM_ISR( xHigherPriorityTaskWoke ); }

 

 

What I get back doesn't look bad, TemperatureData.StoredVolt is 1654 which is a little higher than it

should be but it's in the ballpark. What's strange is that TemperatureData.VoltRef is 3275 which is

about double what it should be.

 

What am I doing wrong?

 

1 ACCEPTED SOLUTION

Accepted Solutions

Kholdoun -

Thank you for your response, it took me a while to filter through it but the simple answer is:

"__HAL_ADC_CALC_VREFANALOG_VOLTAGE does not return VREFINT, it returns VREF+"

Chris

 

View solution in original post

3 REPLIES 3
c_shearer_cooper
Associate III

Any ideas?

nouirakh
ST Employee

Hello @c_shearer_cooper

The value calculated by the internal temperature sensor of the micro-controller is not supposed to be equivalent to the analog reference voltage VREF+. The analog reference voltage (VREF+) is used as the reference for ADC measurements, It's used to figure out what the highest numerical value that ADC can measure, while the internal temperature sensor value is a separate measurement that represents the internal temperature of the micro-controller using a specific formula that takes into account the reference voltage.

Otherwise, The code will be structured as follows:

#include "stm32g4xx_hal.h" // Assuming 'hadc' is the ADC handle and the ADC has been properly initialized // Start the ADC calibration HAL_ADCEx_Calibration_Start(&hadc, ADC_SINGLE_ENDED); // Configure the ADC to read the internal temperature sensor and VREFINT // ... // Start the ADC HAL_ADC_Start(&hadc); // Wait for the temperature sensor conversion to be finished HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY); // Get the raw value from the temperature sensor uint32_t temp_sensor_raw = HAL_ADC_GetValue(&hadc); // Start the ADC again for VREFINT conversion HAL_ADC_Start(&hadc); // Wait for the VREFINT conversion to be finished HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY); // Get the raw value from the VREFINT channel uint32_t vrefint_raw = HAL_ADC_GetValue(&hadc); // Stop the ADC HAL_ADC_Stop(&hadc); // Calculate the VREF+ voltage using the calibration value and the raw VREFINT value uint32_t vref_plus = __HAL_ADC_CALC_VREFANALOG_VOLTAGE(vrefint_raw, ADC_RESOLUTION_12B); // Calculate the temperature using the VREF+ voltage, the raw temperature sensor value, and the ADC resolution float temperature = __HAL_ADC_CALC_TEMPERATURE(vref_plus, temp_sensor_raw, ADC_RESOLUTION_12B); // Now 'vref_plus' contains the VREF+ voltage in millivolts, and 'temperature' contains the temperature in degrees Celsius
View more

 
With Regards,
Kholdoun

Kholdoun -

Thank you for your response, it took me a while to filter through it but the simple answer is:

"__HAL_ADC_CALC_VREFANALOG_VOLTAGE does not return VREFINT, it returns VREF+"

Chris