Skip to main content
emre ozdemir
Associate III
September 16, 2021
Question

STM32G0 internal temperature sensor

  • September 16, 2021
  • 9 replies
  • 10967 views

Hello All,

I need to read tempereture of mcu.

But I confused about formula given at referance manual.which is below.Because there no data TS_CAL_2 val

0693W00000DnKJwQAN.png 

0693W00000DnKKGQA3.png 

Thanks.

Regards.

EMRE

This topic has been closed for replies.

9 replies

ST Technical Moderator
September 16, 2021

Hello @emre ÖZDEMİR​ ,

There is a internal request to update the formula in the coming releases of the RM0454.

In the meantime, you can refer to the formula provided in RM0360:

0693W000001sk41QAA.png 

When your question is answered, please close this topic by choosing Select as Best. This will help other users find that answer faster.

Thanks

Imen

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
SMMB
Graduate II
January 4, 2023

Does V(SENSE) also need to be calibrated according to V(REFINT) (use a calibrated VDD value in the formula)?

emre ozdemir
Associate III
September 16, 2021

Hello,

I tried the formula given in RM0360,code example actually.I updated address and ADC data in the formula.But temperature value I get is not realistic.

/* Temperature sensor calibration value address */

#define TEMP30_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FFF75A8))

#define VDD_CALIB ((uint32_t) (3300))

#define VDD_APPLI ((uint32_t) (3000))

#define AVG_SLOPE ((uint32_t) (5336)) // AVG_SLOPE in ADC conversion step (@3.3V)/°C multiplied by 1000 for precision on the division

int32_t temperature; /* will contain the temperature in degrees Celsius */

temperature = ((uint32_t) *TEMP30_CAL_ADDR - ((uint32_t) ADC_TEMPERATURE * VDD_APPLI / VDD_CALIB)) * 1000;

temperature = (temperature / AVG_SLOPE) + 30;

Thanks.

EMRE

emre ozdemir
Associate III
September 20, 2021

Hello ,

It is an ergent stuation.

Is there any suggestion for me.

Thanks.

EMRE

waclawek.jan
Super User
September 20, 2021

Which STM32 exactly?

What hardware? Is this a "known good" board such as Nucleo or DIsco, or your own design? If the latter, how is VDDA/VREF+ connected?

> .But temperature value I get is not realistic.

Post numbers - the raw ADC readout, actual VREF/VDDA voltage, readout of the calibration value.

Do you observe the start time and the sampling time given for temperature sensor in the datasheet?

JW

emre ozdemir
Associate III
September 20, 2021

Hello,

This board is our custom design.

Here the values

Raw ADC data at

tempereture channel = 1005

Vref = 1540

*TEMP30_CAL_ADDR = 1042;

*VREFINT_CAL = 1659

adcData[2] stores temperature channel value

adcData[3] stores vref channel value

here is the code for temperature

void CalculateTemperature(void)

{

if(temperatureReadTime++ == 100)

{

temperatureReadTime = 0;

temperature = ((uint32_t) *TEMP30_CAL_ADDR - ((uint32_t) adcData[2] * VDD_APPLI / VDD_CALIB)) * 1000;

temperature = (temperature / AVG_SLOPE) + 30;

if(temperature > TEMPERATURE_THRESHOLD && MOTOR_ERROR == 0)

{

MOTOR_ERROR = 1;

MOTOR_STOP();

}

}

}

here is the code for vref (I get this formula from datasheet)But this also gives me (around 2.78V) from the calculation.

void CalculateVref(void)

{

if(VrefReadTime++ == 100)

{

VrefReadTime = 0;

Vref = 3.00 * ((double)adcData[3] / *VREFINT_CAL);

}

}

About sampling time when I check the datasheet

Here is the conversation time formula

0693W00000DnkJKQAZ.pngfor temperature minimum value is 5 ms

0693W00000DnkPMQAZ.png 

ADC clock speed is 16 mHz.

And ADC clock prescaler is 10

Sampling time 160.5

if I calculate the time (160.5+12.5)/(16MHZ/10) = 108 us.This should be suitable then.

There is not a info about a certain sampling time to read temperature.

Thanks.

EMRE

S.Ma
Principal
September 20, 2021

In case this snippet helps.

Make sure adc conversion is longest time, and channel for vref/vtemp are powered up

int32_t Interpolate_s32 (int32_t x0, int32_t x1, int32_t y0, int32_t y1, int32_t x) {
 
  int32_t dwQ;
 
  dwQ = ((y1-y0))*x+(x1*y0)-(x0*y1);       // overflow not checked yet
 
  dwQ = dwQ / (x1-x0);// we can also do roundings here
 
  return dwQ;
 
}
 
int32_t Deg30Lsb;
 
  int32_t Deg130Lsb;
 
  int32_t ADC_Num, ADC_Denum;
 
  int32_t DegC_x10;
 
int32_t ADC_Convert_mV_to_DegC_x10(ADC_t* A, uint32_t Lsb) {
 
  Deg30Lsb = (int32_t)(*((uint16_t*) 0x1FFF75A8));  // 3.0V +/- 10mV
 
  Deg130Lsb = (int32_t)(*((uint16_t*) 0x1FFF75CA)); // 3.0V +/- 10mV
 
  // we first convert the LSB calibrated Flash values to mV (let's remove the sign issue between normal and injected channels)
 
  // convert ADC value to 3.0 Vdd vs measured value
 
  Lsb = (Lsb*A->MeasuredVdd_mV)/3000; // scale the LSB to 3.0V
 
  DegC_x10 = Interpolate_s32 (Deg30Lsb, Deg130Lsb, 300U, 1300U, (int32_t)(int16_t)Lsb);
 
  A->Temp_degC_x10 = DegC_x10; // capture the value for debugging or reference
 
  return DegC_x10;
}
 
 
 
int32_t ADC_Convert_VRefByLsb(ADC_t* A, uint32_t Lsb) {   // Vref = 1.212V
 
  int32_t VRefLsb3p3V_Lsb = (int32_t)(*((uint16_t*) 0x1FFF75AA)); // this contains the ADC 12 bit right aligned raw data for Vref LSB at 30C and 3.0V
 
  uint32_t Vdd_mV = (3000*VRefLsb3p3V_Lsb)/Lsb;
 
  A->MeasuredVdd_mV = Vdd_mV;
 
  return 0;
}

emre ozdemir
Associate III
September 21, 2021

Hello,

stm32g030 does not have a 130°C calibration value.

So I could not implement this script into my code.

Thanks.

EMRE

waclawek.jan
Super User
September 21, 2021

Which STM32, exactly?

> here is the code for vref (I get this formula from datasheet)But this also gives me (around 2.78V) from the calculation.

>[...]

> Vref = 3.00 * ((double)adcData[3] / *VREFINT_CAL);

No, it's the other way round, Vref = 3.00V * (*VREFINT_CAL) / adcData. That gives Vref = 3.23V.

What is the actually measured voltage at VREF+ pin?

From this, voltage at your temperature sensor is Vref*1005/4096=3.23V*1005/4096=0.793V

The calibrated 30deg. voltage is 3.00V*1042/4096=0.763V, so your voltage is 30mV higher. Given average slope 2.5mV/deg, this is equivalent to 30mV/2.5mV/deg.C=12deg.C, i.e. internal die temperature 30deg+12deg=42deg. IMO entirely plausible.

JW

S.Ma
Principal
September 21, 2021

Sharpen your problem solving skills, if you have only one reference point and a slope in lsb per degree, you can calculate 130 degree point as 100 degtee shift and keep the code almost the same as with stm32 with 2 points. Say 341 lsb more at 130 degree vs 30 degree....

Deg130Lsb = Deg30Lsb + 341; // read your stm32 spec and tune.

Philippe Cherbonnel
ST Employee
October 18, 2021

Hello @emre ÖZDEMİR​ ,

STM32 series value line does have only one calibration point. Other ones have two calibration points.

In LL driver, there are 2 macro available to help you to compute temperature from ADC raw conversion data.

- __LL_ADC_CALC_TEMPERATURE(): requires 2 calibration points, most accurate since specific to each sample.

- __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(): uses typical parameters from datasheet, generic to all samples.

Here is a proposal to use this macro:

#define VDDA_APPLI ((uint32_t) 3300) /* Value of analog reference voltage (Vref+), connected to analog voltage supply Vdda (unit: mV) */
#define TEMPSENSOR_TYP_CAL1_V (( int32_t) 760) /* Internal temperature sensor, parameter V30 (unit: mV). Refer to device datasheet for min/typ/max values. */
#define TEMPSENSOR_TYP_AVGSLOPE (( int32_t) 2500) /* Internal temperature sensor, parameter Avg_Slope (unit: uV/DegCelsius). Refer to device datasheet for min/typ/max values. */
#define TEMPSENSOR_CAL_VREF ((uint32_t) 3000) /* Vdda value with which temperature sensor has been calibrated in production (+-10 mV). */
 
temperature_degC = __LL_ADC_CALC_TEMPERATURE_TYP_PARAMS(TEMPSENSOR_TYP_AVGSLOPE,
 TEMPSENSOR_TYP_CAL1_V,
 TEMPSENSOR_CAL1_TEMP,
 VDDA_APPLI,
 temperature_raw_data,
 LL_ADC_RESOLUTION_12B);

You can optimize accuracy by using offset calibrated data instead of generic value (literal TEMPSENSOR_TYP_CAL1_V above).

Best regards

Philippe