2019-06-16 02:59 AM
Hi all,
I need to measure the internal CPU temperature sensor from the STM32H743. I activated the ADC3 using STM32CUBEMX (V. 5.0.1) and selected Temperature Channel.
However the calculated temperatures are far too high. When switching on the cooled system at 22° Temperature, the delivered value is 55 °C. This is definitely by far too high!
Can anybody tell what might be wrong with my init code?
ADC input clock is set to 32 MHz
Clock Prescaler = devided by 1
Resolution 16 Bit
Continuous Mode Enabled
In Rank 1:
Sampling Time set to 810.5 Cycles
Generated initialisation code is as follows:
//////////////////////////////////////////////////////////////////
void MX_ADC3_Init(void)
{
ADC_ChannelConfTypeDef sConfig = {0};
/**Common config
*/
hadc3.Instance = ADC3;
hadc3.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;
hadc3.Init.Resolution = ADC_RESOLUTION_16B;
hadc3.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc3.Init.LowPowerAutoWait = DISABLE;
hadc3.Init.ContinuousConvMode = ENABLE;
hadc3.Init.NbrOfConversion = 1;
hadc3.Init.DiscontinuousConvMode = DISABLE;
hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR;
hadc3.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
hadc3.Init.BoostMode = DISABLE;
hadc3.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc3) != HAL_OK)
{
Error_Handler();
}
/**Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_810CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
{
Error_Handler();
}
}
////////////////////////////////////////////////////////////////////
// Reading Temperature in Interrupt mode:
// started after power on in continuous mode:
// HAL_ADC_Start_IT(&hadc3);
#define TEMP110_CAL_ADDR ((uint16_t*)((uint32_t)0x1FF1E840))
#define TEMP30_CAL_ADDR ((uint16_t*)((uint32_t)0x1FF1E820))
double adc_ReadInternalTemp(void)
{
double dTemp;
uint32_t adcConVal;
uint32_t T1_30;
uint32_t T2_110;
adcConVal = HAL_ADC_GetValue(&hadc3);
// Temp = 80 / (TS_CAL2 - TS_CAL1) * (ValTS - TS_CAL1) + 30
// TS_CAL1 = T1_30 = at 30 Degrees
// TS_CAL2 = T2_110 = at 110 Degrees
T1_30 = (int32_t)* TEMP30_CAL_ADDR; // Reads 0x3073
T2_110 = (int32_t)* TEMP110_CAL_ADDR; // Reads 0x3F63
dTemp = (double)(110 - 30) / (double)(T2_110 - T1_30);
dTemp *= (double)(adcConVal - T1_30);
dTemp += 30;
return dTemp; // 55-59 °C at startup, 80°C after warming up
}
Any help is very much appreciated!
2019-06-16 03:03 AM
The H7 dissipates a lot of power and so heats up the chip even even when the ambiant is cooled. I think 55 degrees is normal. Do some calculation with the dissipated power and the thermal resitstance chip to ambient!
2019-06-16 03:13 AM
I'm seeing 43degC on a NUcleo H743Zi with a daughter board tight over the Nucleo and 22degC ambient. I'm using oversampling on the measurement hence the right shift in the equation
temp = ((double)(80.0)) / ((double)(*TS_CAL2-*TS_CAL1)) * (((double)(HAL_ADC_GetValue(&hadc3)>>4))-((double)*TS_CAL1)) + ((double)30.0) ;
2019-06-16 03:18 AM
Thank you for your input. I agree that 55 degrees would be normal after heating up the chip. But this temperature already os seen immediately after startup. We get values of 70 degrees when the system is heated up for appx. 10 minutes.
We are wondering however, which temperatures will be considered as "normal" ? And the system is not yet built into a housing, which will increase heating additionally. And for which ambient temperatures will the system then be able to work...
The chip is defined for working temperatures of appx. 85 degrees. So only 15 degrees would be left for increased ambient temperatures...
The system will be used in a sports car vehicle, so 35° could be reached very easily.
2019-06-16 03:20 AM
Thank you for your information.
Could you please send me your initialisation code so I can compare it to mine? Maybe I did set a wrong sampling rate or so...
2019-06-16 05:00 AM
Cut and paste from a large program so variables not defined
hadc3.Instance = ADC3;
hadc3.Init.Resolution = ADC_RESOLUTION_16B;
hadc3.Init.Oversampling.Ratio = 256; /* Oversampling ratio */
hadc3.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_4; /* Right shift of the oversampled summation */
hadc3.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; /* Synchronous clock mode, input ADC clock divided by 4*/
hadc3.Init.ScanConvMode = DISABLE; /* Sequencer disabled (ADC conversion on only 1 channel: channel set on rank 1) */
hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV; /* EOC flag picked-up to indicate conversion end */
hadc3.Init.LowPowerAutoWait = DISABLE; /* Auto-delayed conversion feature disabled */
hadc3.Init.ContinuousConvMode = DISABLE; /* Continuous mode enabled (automatic conversion restart after each conversion) */
hadc3.Init.NbrOfConversion = 1; /* Parameter discarded because sequencer is disabled */
hadc3.Init.DiscontinuousConvMode = DISABLE; /* Parameter discarded because sequencer is disabled */
hadc3.Init.NbrOfDiscConversion = 1; /* Parameter discarded because sequencer is disabled */
hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START; /* Software start to trig the 1st conversion manually, without external event */
hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; /* Parameter discarded because software trigger chosen */
hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; /* DR mode selected */
hadc3.Init.BoostMode = ENABLE; /* Enable Boost mode as ADC clock frequency is bigger than 20 MHz */
hadc3.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN; /* DR register is overwritten with the last conversion result in case of overrun */
hadc3.Init.OversamplingMode = ENABLE; /* Oversampling enabled */
hadc3.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER ; /* Specifies whether or not a trigger is needed for each sample */
hadc3.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_CONTINUED_MODE ; /* Specifies whether or not the oversampling buffer is maintained during injection sequence */
if (HAL_ADC_Init(&hadc3) != HAL_OK)
{
/* ADC initialization Error */
error("HAL_ADC_Init");
}
/* Run the ADC calibration in single-ended mode */
if (HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED) != HAL_OK)
{
/* Calibration Error */
error("HAL_ADCEx_Calibration_Start");
}
}
uint16_t *TS_CAL1=(uint16_t *)0x1FF1E820;
uint16_t *TS_CAL2=(uint16_t *)0x1FF1E840;
sConfig.Channel = ADC_CHANNEL_TEMPSENSOR; /* Sampled channel number */
sConfig.Rank = ADC_REGULAR_RANK_1; /* Rank of sampled channel number ADCx_CHANNEL */
sConfig.SamplingTime = ADC_SAMPLETIME_387CYCLES_5; /* Sampling time (number of clock cycles unit) */
sConfig.SingleDiff = ADC_SINGLE_ENDED; /* Single-ended input channel */
sConfig.OffsetNumber = ADC_OFFSET_NONE; /* No offset subtraction */
sConfig.Offset = 0; /* Parameter discarded because offset correction is disabled */
if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
{
/* Channel Configuration Error */
error("HAL_ADC_ConfigChannel");
}
if (HAL_ADC_Start(&hadc3) != HAL_OK)
{
/* Start Conversation Error */
error("HAL_ADC_Start");
}
/*##-4- Wait for the end of conversion #####################################*/
/* For simplicity reasons, this example is just waiting till the end of the
conversion, but application may perform other tasks while conversion
operation is ongoing. */
if (HAL_ADC_PollForConversion(&hadc3, 10) != HAL_OK)
{
/* End Of Conversion flag not set on time */
error("HAL_ADC_PollForConversion");
}
else
{
/* ADC conversion completed */
/*##-5- Get the converted value of regular channel ########################*/
temp = ((double)(80.0)) / ((double)(*TS_CAL2-*TS_CAL1)) * (((double)(HAL_ADC_GetValue(&hadc3)>>4))-((double)*TS_CAL1)) + ((double)30.0) ;
}
2019-06-16 05:27 AM
Ok folks, now I got reasonable results of 50-55 degrees C when the system is heated up.
I forgot to call the calibration before starting the ADC:
HAL_ADCEx_Calibration_Start(&hadc3, ADC_CALIB_OFFSET, ADC_SINGLE_ENDED);
2019-06-16 05:58 AM
Hi Peter,
thank you for sending me your init code. Looks similar to mine except of the oversampling setup.
As I now got reasonable values I keep it as it is. Thank you anyway!
2019-06-16 06:33 AM
One more thing, check the datasheet for what is Vdd for the calibrated values.
If the cal values are 3.0V but running on 3.3V, you'll be off much.
So while the example is not provided (no need?), first measure ADC Vdd through Vref measurements, then read the ADC Temp value, and compensate for the 3.0V difference. You don't need to go to double format for this. float will be more than enough when the desired accuracy won't reach more than 1 degree (most temp sensors aren't acurate anyway)
2019-06-16 06:36 AM
ok, thank you for the hints!
Yes, I agree: float would be sufficient. Will change that ;)