cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F205 temperature sensor problems

tfk
Associate II
Posted on June 24, 2011 at 15:06

Hi everybody,

I'm having some trouble with the STM32F205 temperature sensor. 

I'm using the algorithm from section 10.10 in the reference manual. {(V25 � VSENSE) / Avg_Slope} + 25

I'm using the following algorithm to convert the ADC value to a voltage value from the temperature sensor ADC channel (ch 16):

ADCConvertedValue*3.3/4096;

When I'm heating up the chip the ADCConvertedValue increases resulting in a greater voltage value, that results in lower temperature as a higher VSENSE value will subtract more from V25. 

Does anyone have the same problem ? 

Best Regards

Tord

#not-that-complicated #vsense-temperature-sensor #adc-dma #stm32f205-temperature
20 REPLIES 20
ColdWeather
Senior
Posted on June 25, 2011 at 12:36

Hello, Tord!

I have STM32F103RC (not 205) running here and tested the temperature sensor. I think, the unit in 205 is not quite different from 103

The equation is correct. The board shows now +27^C and rises a bit if I hold a finger on the CPU. Well, indeed the room temperature now is about +21^C, but ST says, the embedded sensor is just for estimation purposes only and quite unprecise.

raptorhal2
Lead
Posted on June 25, 2011 at 17:20

If you are using the 4.3 Avg_Slope from the datasheet, it is in millivolts, so your conversion to voltage should be ADCConvertedValue*3300/4096. And you will have to allow for integer overflow in this equation by using u32 type.

If that is not your problem, post the code so we can see what is going on.

Cheers, Hal

tfk
Associate II
Posted on June 26, 2011 at 15:30

Here's the code:

/* Includes ------------------------------------------------------------------*/

#include ''stm32f2xx.h''

/** @addtogroup STM32F2xx_StdPeriph_Examples

  * @{

  */

/** @addtogroup ADC_ADC1_DMA

  * @{

  */ 

/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/

#define ADC1_DR_ADDRESS    ((uint32_t)0x4001204C)

/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/

__IO uint16_t ADCConvertedValue = 0;

__IO uint16_t TempSTM32 = 0;

ADC_InitTypeDef       ADC_InitStructure;

ADC_CommonInitTypeDef ADC_CommonInitStructure;

DMA_InitTypeDef       DMA_InitStructure;

GPIO_InitTypeDef      GPIO_InitStructure;

/* Private function prototypes -----------------------------------------------*/

/* Private functions ---------------------------------------------------------*/

/**

  * @brief  Main program

  * @param  None

  * @retval None

  */

int main(void)

{

  /*!< At this stage the microcontroller clock setting is already configured, 

       this is done through SystemInit() function which is called from startup

       file (startup_stm32f2xx.s) before to branch to application main.

       To reconfigure the default setting of SystemInit() function, refer to

       system_stm32f2xx.c file

     */     

       

  /* Enable peripheral clocks *************************************************/

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

  /* DMA2_Stream0 channel0 configuration **************************************/

  DMA_DeInit(DMA2_Stream0);

  DMA_InitStructure.DMA_Channel = DMA_Channel_0;  

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS;

  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCConvertedValue;

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

  DMA_InitStructure.DMA_BufferSize = 1;

  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;

  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

  DMA_InitStructure.DMA_Priority = DMA_Priority_High;

  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         

  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

  DMA_Init(DMA2_Stream0, &DMA_InitStructure);

  /* DMA2_Stream0 enable */

  DMA_Cmd(DMA2_Stream0, ENABLE);

  /* ADC1 configuration ------------------------------------------------------*/

  /* Configure ADC Channel12 pin as analog input */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

  /* ADCs DeInit (for debug purpose) */  

  ADC_DeInit();

  /* ADC Common Init */

  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;

  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;

  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;

  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; 

  ADC_CommonInit(&ADC_CommonInitStructure);

  

  /* ADC1 Init */

  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

  ADC_InitStructure.ADC_ScanConvMode = DISABLE;

  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//ENABLE;

  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;   

  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

  ADC_InitStructure.ADC_NbrOfConversion = 1;

  ADC_Init(ADC1, &ADC_InitStructure);

  /* ADC1 regular channel12 configuration */ 

  ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_480Cycles);

  /* Enable DMA request after last transfer (Single-ADC mode) */

 // ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);

  /* Enable ADC1 DMA */

  //ADC_DMACmd(ADC1, ENABLE); 

    ADC_TempSensorVrefintCmd(ENABLE);

    ADC_EOCOnEachRegularChannelCmd(ADC1, ENABLE);

  /* Enable ADC1 */

  ADC_Cmd(ADC1, ENABLE);

    

  /* Start ADC1 Software Conversion */ 

  ADC_SoftwareStartConv(ADC1);

  float adcVolt = 0;

  float diffVolt = 0;

  float temp1 = 0;

  float temp2 = 0;

  while (1)

  {

    ADC_SoftwareStartConv(ADC1);

    while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)== RESET);

   ADCConvertedValue = ADC_GetConversionValue(ADC1);

   adcVolt  = ADCConvertedValue*3.3/4096;

   diffVolt =   adcVolt - 0.76 ;

   temp1  = diffVolt / (2.5/1000);//0.00025;

   temp2 = temp1 +25;   

  }

}

#ifdef  USE_FULL_ASSERT

/**

  * @brief  Reports the name of the source file and the source line number

  *         where the assert_param error has occurred.

  * @param  file: pointer to the source file name

  * @param  line: assert_param error line source number

  * @retval None

  */

void assert_failed(uint8_t* file, uint32_t line)

  /* User can add his own implementation to report the file name and line number,

     ex: printf(''Wrong parameters value: file %s on line %d\r\n'', file, line) */

  /* Infinite loop */

  while (1)

  {

  }

}

#endif

/**

  * @}

  */ 

/**

  * @}

  */ 

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

raptorhal2
Lead
Posted on June 26, 2011 at 16:49

You made one simple error (probably a typo). The ADC1 address boundary starts at 0x40012400. The DR address offset is 0x4C, so the ADC1_DR_Address should be 0x4001244C.

If that doesn't fix the problem, I will give your code a more intensive review.

Cheers, Hal

tfk
Associate II
Posted on June 27, 2011 at 09:28

Thanks for the code review, nice catch, however the ADC address boundary starts at a address on the 2xx series, than the 1xx series. The code doesn't activate DMA on the ADC device so it is manually driven. I probably should have removed the unutilized  DMA code snippets to avoid confusion. 

Heres the code a bit more tidy: 

Cheers 

Tord

#include ''stm32f2xx.h''

__IO uint16_t ADCConvertedValue = 0;

__IO uint16_t TempSTM32 = 0;

ADC_InitTypeDef       ADC_InitStructure;

ADC_CommonInitTypeDef ADC_CommonInitStructure;

GPIO_InitTypeDef      GPIO_InitStructure;

int main(void)

{

       

  /* Enable peripheral clocks *************************************************/

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);

  /* ADC1 configuration ------------------------------------------------------*/

  /* Configure ADC Channel12 pin as analog input */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

  GPIO_Init(GPIOC, &GPIO_InitStructure);

  ADC_DeInit();

  /* ADC Common Init */

  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;

  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;

  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;

  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; 

  ADC_CommonInit(&ADC_CommonInitStructure);

  

  /* ADC1 Init */

  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;

  ADC_InitStructure.ADC_ScanConvMode = DISABLE;

  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//ENABLE;

  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;   

  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

  ADC_InitStructure.ADC_NbrOfConversion = 1;

  ADC_Init(ADC1, &ADC_InitStructure);

  /* ADC1 regular channel16 configuration */ 

  ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 1, ADC_SampleTime_480Cycles);

    ADC_TempSensorVrefintCmd(ENABLE);

    ADC_EOCOnEachRegularChannelCmd(ADC1, ENABLE);

  /* Enable ADC1 */

  ADC_Cmd(ADC1, ENABLE);

    

  /* Start ADC1 Software Conversion */ 

  ADC_SoftwareStartConv(ADC1);

  float adcVolt = 0;

  float diffVolt = 0;

  float temp1 = 0;

  float temp2 = 0;

  while (1)

  {

    ADC_SoftwareStartConv(ADC1);

    while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)== RESET);

   ADCConvertedValue = ADC_GetConversionValue(ADC1);

   adcVolt  = ADCConvertedValue*3.3/4096;

   diffVolt =   adcVolt - 0.76 ;

   temp1  = diffVolt / (2.5/1000);//0.00025;

   temp2 = temp1 +25;   

  }

}

raptorhal2
Lead
Posted on June 28, 2011 at 20:35

Try calibrating the ADC one time before the conversion loop. You also have two start conversions the first time through. Eliminate the first one.

The data sheet says the slope is positive, but the formula indicates otherwise. Try assuming the formula should be Vsense - V25.

There is a more efficient way to perform the calculation than using floating variables, based on ADC values of 943 for V25 and 3.1 for slope.

    Temperature = 25 + BiasCorrection + (((s16) ADCConvValue-943)*10)/31;

Your CPU will be smoke and ash before you exceed 16 bit integer range.

Cheers, Hal

cristian2399
Associate II
Posted on June 27, 2012 at 15:02

Hi Tord,

I have the same problem, with the same uC. Did you solved the problem?

Thanks

Posted on June 27, 2012 at 18:07

It's been a year since Tord posted, suggest you submit YOUR code and no doubt some of the members can critic it. Hal is still active here, and has a good handle on the ADC stuff.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jpeacock2399
Associate II
Posted on June 27, 2012 at 23:53

Be sure the sample time for the temperature sensor is > 10usec, otherwise you get unreliable readings.  For an STM32F407, 168MHz, ADCCLK scaled to 21MHz, I have to use the 480 cycle setting for sample time of about 23usec.

  Jack Peacock