Life.augmented
Skip to main content
Go Search
  

STM32

Modify settings and columns
STM32 - ARM Cortex-M 32-Bit MCU
Share Discussion
  
View: 
Post
Started: 6/24/2011 3:06 PM
fauskanger.tord
  Posts : 3
STM32F205 temperature sensor problems
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

Tags: STM32F205 temperature
Edited: 6/25/2011 1:21 PM
ColdWeather
  Posts : 99
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.
Posted: 6/25/2011 5:20 PM
baird.hal.001
  Posts : 411
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

Edited: 6/26/2011 3:31 PM
fauskanger.tord
  Posts : 3
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****/


From: baird.hal.001
Posted: Saturday, June 25, 2011 5:20 PM
Subject: STM32F205 temperature sensor problems

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



From: fauskanger.tord
Posted: Friday, June 24, 2011 3:06 PM
Subject: STM32F205 temperature sensor problems

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
Posted: 6/26/2011 4:49 PM
baird.hal.001
  Posts : 411
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
Posted: 6/27/2011 9:28 AM
fauskanger.tord
  Posts : 3
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;   
  }
}


Posted: 6/28/2011 8:35 PM
baird.hal.001
  Posts : 411
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
Posted: 6/27/2012 3:02 PM
pop.cristi
  Posts : 4

Hi Tord,
I have the same problem, with the same uC. Did you solved the problem?
Thanks
Posted: 6/27/2012 6:07 PM
clive1
  Posts : 8753
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.
Posted: 6/27/2012 11:53 PM
Jack Peacock
  Posts : 202
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


Tags: Vsense Temperature Sensor
Posted: 6/29/2012 3:37 PM
pop.cristi
  Posts : 4
Hi this is mai code:


#define STM32_TEMPSENS_ADC_DEVICE                ADC1
#define STM32_TEMPSENS_ADC_IRQHANDLER            ADC_IRQHandler
#define STM32_TEMPSENS_ADC_IRQCHANNEL            ADC_IRQn
#define STM32_TEMPSENS_ADC_PERIPH_CLK            RCC_APB2Periph_ADC1
#define STM32_TEMPSENS_ADC_PERIPH_CLK_FREQ_HZ    (PROJECT_SYSCLK_HZ / 2)
#define STM32_TEMPSENS_ADC_PRESCALER            8

#define STM32_TEMPSENS_ADC_RESOL_BITS            12
#define STM32_TEMPSENS_ADC_SAMPLETIME_CYCLES    56
#define STM32_TEMPSENS_ADC_V_REF_4DD            33000 /* typical */
#define STM32_TEMPSENS_AVG_SLOPE_MV_DEGC_1DD    25    /* typical */
#define STM32_TEMPSENS_V_25DEGC_4DD                7600  /* typical */
#define STM32_TEMPSENS_T_S_US                    10    /* typical */
#define STM32_TEMPSENS_ADC_RESOL_STEPS    (1 << STM32_TEMPSENS_ADC_RESOL_BITS)

static volatile uint16_t tempsens_rawval;
static volatile uint8_t conv_running;

static int
_init(const struct w2h_dev_t *self, const void *cfg)
{
    ADC_InitTypeDef ADC_InitStructure;
    ADC_CommonInitTypeDef ADC_CommonInitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    /* Enable STM32_TEMPSENS_ADC_DEVICE clock. */
    (void)self;
    (void)cfg;
    RCC_APB2PeriphClockCmd(STM32_TEMPSENS_ADC_PERIPH_CLK, ENABLE);

    /* Configure NVIC for STM32_TEMPSENS_ADC_DEVICE. */
    NVIC_InitStructure.NVIC_IRQChannel = STM32_TEMPSENS_ADC_IRQCHANNEL;
    NVIC_Init(&NVIC_InitStructure);

    tempsens_rawval = 0;
    ADC_DeInit();

    /* ADC Common Init */
    ADC_CommonStructInit(&ADC_CommonInitStructure);
    ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div8;
    ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
    ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
    ADC_CommonInit(&ADC_CommonInitStructure);

    /* STM32_TEMPSENS_ADC_DEVICE configuration. */
    ADC_StructInit(&ADC_InitStructure);

    ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
    ADC_InitStructure.ADC_ScanConvMode = DISABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
    /* ADC_InitStructure.ADC_ExternalTrigConv = xxx; */
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfConversion = 1;
    ADC_Init(STM32_TEMPSENS_ADC_DEVICE, &ADC_InitStructure);
    /* STM32_TEMPSENS_ADC_DEVICE temperature sensor configuration. */
    /* The temperature sensor requires a sample time of at least 17.1 us. */
    /*
     * With ADC clock @12 MHz (PCLK2 / 6) and a sample time of 239.5 cycles,
     * the temperature sensor's required sample time can be matched.
     */

    ADC_RegularChannelConfig(STM32_TEMPSENS_ADC_DEVICE, ADC_Channel_TempSensor,
                             1, ADC_SampleTime_480Cycles);
    /* Enable temperature sensor and Vref. */
    ADC_TempSensorVrefintCmd(ENABLE);
    /* Enable STM32_TEMPSENS_ADC_DEVICE EOC interupt. */
    ADC_ITConfig(STM32_TEMPSENS_ADC_DEVICE, ADC_IT_EOC, ENABLE);
    /* Enable STM32_TEMPSENS_ADC_DEVICE. */
    ADC_Cmd(STM32_TEMPSENS_ADC_DEVICE, ENABLE);
    printfx("call adc_init\n");
    return W2H_ERR_OK;
}

static int
_deinit(const struct w2h_dev_t *self)
{
    (void)self;
    return W2H_ERR_OK;
}

static int
_read(const struct w2h_dev_t *self,  uint16_t *ptr)
{
    int32_t val;
    (void)self;
    /* Argument checks. */
    if (ptr == NULL) {
        return 1;
        /* NOTREACHED */
    }
    conv_running = 1;
    /* Start next STM32_TEMPSENS_ADC_DEVICE Software Conversion. */
    ADC_SoftwareStartConv(STM32_TEMPSENS_ADC_DEVICE);
    /* Loop until ISR has finished. */
    while (conv_running != 0) {
        /* Wait (do nothing). */
    }
    /* Convert ADC result to value in degC. */
    val = ((int32_t)tempsens_rawval * STM32_TEMPSENS_ADC_V_REF_4DD)
          / (STM32_TEMPSENS_ADC_RESOL_STEPS - 1);
    val = STM32_TEMPSENS_V_25DEGC_4DD - val;
    val /= STM32_TEMPSENS_AVG_SLOPE_MV_DEGC_1DD;
    val += 25;
    *ptr = val;
    return W2H_ERR_OK;
}




void w2h_stm32_adc_ev_irqh(const struct w2h_dev_t *self)
{
    (void)self;
    if (ADC_GetITStatus(STM32_TEMPSENS_ADC_DEVICE, ADC_IT_EOC) != RESET) {
        /*
         * The "End of conversion" bit (EOC) -- as the interrupt source --
         * is cleared by reading ADC_DR.
         */
        tempsens_rawval = ADC_GetConversionValue(STM32_TEMPSENS_ADC_DEVICE);

        conv_running = 0;
    }
}

And the problem is that, I am reading the same
conts = 0x3C4;  5 counts tolerance
Normaly, I think that even touching the uC, with my finger the conts should take other value.
I tried desabling the temp Vref, and I read:
conts =  0x05;  3 conts tolerance
I have tried spray the processor with an alcohool spray (-52 C deg), and I read more conts. Probably becouse of the variation, of internal reference.
Thank You for answer.




Posted: 6/29/2012 8:45 PM
dimitrov.valentin
  Posts : 8
Temperature (in °C) = {(VSENSE– V25) / Avg_Slope} + 25
The formula was wrong in the earliest versions of the ref. manual.
Posted: 6/29/2012 10:55 PM
baird.hal.001
  Posts : 411
And, remove the comment marks in

 /* ADC_InitStructure.ADC_ExternalTrigConv = xxx; */

and set xxx = 0.

Let us know what happens after these fixes.

Cheers, Hal


Posted: 7/2/2012 8:39 AM
pop.cristi
  Posts : 4
Hello all,
It seems that i had only a conversion problem, in converting conts to temp.
Thank you Valentin for formula correction.
However I'm still not quite not happy, with what I obteined. Measuring the temp sensor once per second, I have jumps eaven of 2 C deg.
Although the ADC clock is divided by 8 and ADC_SampleTime_480Cycles, it seems a little bit strage for me.

Thank you for feedback,
Cristian
Posted: 7/2/2012 9:50 AM
ColdWeather
  Posts : 99
> Temperature (in °C) = {(VSENSE– V25) / Avg_Slope} + 25

The equation above must be WRONG. The latest RM says:

{(V25 - VSENSE) / Avg_Slope} + 25

and it works on my boards (a part of the code):

    float
    _Vsense =  1.0 * ADC_ValueToVoltage(ADC_Values[0]);
    return (_V25 - _Vsense)*1000/_Slope + 25;    // ...and add 25^C



Posted: 7/2/2012 10:36 AM
pop.cristi
  Posts : 4
RM0033 is the last?
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/REFERENCE_MANUAL/CD00225773.pdf

Browse Private Forums

NOTE: these forums are exclusive for users of this Extranet!)