cancel
Showing results for 
Search instead for 
Did you mean: 

Stm32L562 Internal Temperature sensor reading is not right?

chsriniv
Associate II
 

 

 

float read_internal_temperature(void) { uint32_t adcValue; float temperature; // Configure ADC channel for temperature sensor ADC_ChannelConfTypeDef sConfig = {0}; sConfig.Channel = ADC_CHANNEL_TEMPSENSOR; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5; HAL_ADC_ConfigChannel(&hadc1, &sConfig); // Start conversion and wait for it to complete HAL_ADC_Start(&hadc1); HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); // Read ADC value adcValue = HAL_ADC_GetValue(&hadc1); // Retrieve calibration values from system memory uint16_t ts_cal1 = TS_CAL1; // Calibration value at 30°C uint16_t ts_cal2 = TS_CAL2; // Calibration value at 110°C // Calculate the slope between TS_CAL1 and TS_CAL2 float slope = (float)(ts_cal2 - ts_cal1) / (110.0f - 30.0f); // Calculate the temperature temperature = 30.0f + ((float)(adcValue - ts_cal1) / slope); // Stop ADC to save power HAL_ADC_Stop(&hadc1); return temperature; }
View more

 

 

The adcValue returns very low value although I am using a 12 bit resolutio

5 REPLIES 5
TDK
Super User

Do you calibrate the ADC on startup?

Does your VREF+ match what was used for TS_CALx? (in datasheet)

If you feel a post has answered your question, please click "Accept as Solution".

Isn't TS_CAL1 an address? You need to de-reference it first. Also I would invert the slope calculation so you only need to multiply instead of dividing.
If your VREF voltage is not the same you need to scale your voltage or the CAL values.

Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.
chsriniv
Associate II

Thanks all for your help!

I confirm my Vref match the CAL values in my data sheet.

Initial ADC calibration

static void MX_ADC1_Init(void) { /* USER CODE BEGIN ADC1_Init 0 */ /* USER CODE END ADC1_Init 0 */ ADC_MultiModeTypeDef multimode = {0}; ADC_ChannelConfTypeDef sConfig = {0}; /* USER CODE BEGIN ADC1_Init 1 */ /* USER CODE END ADC1_Init 1 */ /** Common config */ hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; hadc1.Init.Resolution = ADC_RESOLUTION_12B; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE; // Enable scan mode for multiple channels hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; hadc1.Init.LowPowerAutoWait = DISABLE; hadc1.Init.ContinuousConvMode = DISABLE; hadc1.Init.NbrOfConversion = 2; // Two conversions (Temp sensor and VREFINT) 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; hadc1.Init.DFSDMConfig = ADC_DFSDM_MODE_DISABLE; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } /** Configure the ADC multi-mode */ multimode.Mode = ADC_MODE_INDEPENDENT; if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK) { Error_Handler(); } /** Configure Regular Channel for Temperature Sensor (ADC_CHANNEL_TEMPSENSOR) */ sConfig.Channel = ADC_CHANNEL_TEMPSENSOR; 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; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } /** Configure Regular Channel for VREFINT (ADC_CHANNEL_VREFINT) */ sConfig.Channel = ADC_CHANNEL_VREFINT; sConfig.Rank = ADC_REGULAR_RANK_2; // Second conversion sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN ADC1_Init 2 */ /* USER CODE END ADC1_Init 2 */ }
View more

My temperature reading code

float read_internal_temperature(void) { uint32_t adc_vref_raw; uint32_t adc_temp_raw; // Start the ADC conversion HAL_ADC_Start(&hadc1); // Wait for conversion to complete for Temperature channel HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); adc_temp_raw = HAL_ADC_GetValue(&hadc1); // Temperature sensor value // Wait for conversion to complete for VREFINT channel HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); // Ensure the next channel is ready adc_vref_raw = HAL_ADC_GetValue(&hadc1); // VREFINT value // Retrieve calibration values for temperature sensor and VREFINT uint16_t ts_cal1 = (*TEMPSENSOR_CAL1_ADDR); // Calibration at 30°C uint16_t ts_cal2 = (*TEMPSENSOR_CAL2_ADDR); // Calibration at 110°C uint16_t vrefint_cal = (*VREFINT_CAL_ADDR); // VREFINT calibration // Calculate VDDA (the reference voltage) float vdda = (3.0 * vrefint_cal) / adc_vref_raw; // Calculate temperature based on calibration values float slope = (float)(ts_cal2 - ts_cal1) / (110.0f - 30.0f); float temperature = 30.0f + ((float)(adc_temp_raw - ts_cal1) / slope); // Stop the ADC conversion HAL_ADC_Stop(&hadc1); // You now have the calibrated temperature and VDDA (reference voltage) return temperature; }
View more

 Final Output:

adc_temp_raw = 901 -> again too low adc_vref_raw = 1443 ts_cal1 = 1040 ts_cal2 = 1384 vrefint_cal = 1657 vdda = 3.4V

 

You are not calibrating your ADC in MX_ADC1_Init(). A common mistake.
Use HAL_ADCEx_Calibration_Start() or LL_ADC_StartCalibration().
Also wait after calibration before starting: https://community.st.com/t5/stm32-mcus-products/adc-register-adrdy-never-sets-when-i-enable-the-adc-so-it-keeps/m-p/106159#M17007

Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.

> vdda = 3.4V

TS_CAL values are taken at 3.0 V per the datasheet.

TDK_0-1741966110921.png

So not the same.

Scale adc_temp_raw by 3.4 / 3.0 which gives 1021.

Put that in the calculation and you'll get a temp just under 30 C which is reasonable.

If you feel a post has answered your question, please click "Accept as Solution".