Lectura del sensor de temperatura interno STM32

2

Estoy tratando de leer el sensor de temperatura interno. Cada vez, el valor de conversión de ADC es 296, lo que resulta en una temperatura negativa. ¿Debo agregar algo al código siguiente, habilitar algunos periféricos o mis cálculos son incorrectos?

#define TEMP_SENSOR_AVG_SLOPE_MV_PER_CELSIUS                        2.5f
#define TEMP_SENSOR_VOLTAGE_MV_AT_25                                760.0f
#define ADC_REFERENCE_VOLTAGE_MV                                    1210.0f
#define ADC_MAX_OUTPUT_VALUE                                        4095.0f

int32_t sensorValue, temperature;

__HAL_ADC_ENABLE(&hadc1);

// Disable Vbat signal from input channel and wake up temp sensor from power down mode
ADC->CCR &= ~(ADC_CCR_TSVREFE);


HAL_ADC_Start(&hadc1);
if(HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK)
{
    sensorValue = (int32_t)HAL_ADC_GetValue(&hadc1);
    HAL_ADC_Stop(&hadc1);
    sensorValue = sensorValue * ADC_REFERENCE_VOLTAGE_MV / ADC_MAX_OUTPUT_VALUE;
    temperature = (int32_t)((sensorValue - TEMP_SENSOR_VOLTAGE_MV_AT_25) / TEMP_SENSOR_AVG_SLOPE_MV_PER_CELSIUS + 25);
}
else
{
    temperature = -273;
}

return temperature;

--EDIT

#define TEMP_SENSOR_AVG_SLOPE_MV_PER_CELSIUS                        2.5f
#define TEMP_SENSOR_VOLTAGE_MV_AT_25                                760.0f
#define ADC_REFERENCE_VOLTAGE_MV                                    3300.0f
#define ADC_MAX_OUTPUT_VALUE                                        4095.0f
#define TEMP110_CAL_VALUE                                           ((uint16_t*)((uint32_t)0x1FFF7A2E))
#define TEMP30_CAL_VALUE                                            ((uint16_t*)((uint32_t)0x1FFF7A2C))
#define TEMP110                                                     110.0f
#define TEMP30                                                      30.0f

int32_t temperature;
float sensorValue;
float adcCalValue30 = (float)(*TEMP30_CAL_VALUE);
float adcCalValue110 = (float)(*TEMP110_CAL_VALUE);

__HAL_ADC_ENABLE(&hadc1);

// Disable Vbat signal from input channel and wake up temp sensor from power down mode
ADC->CCR |= ADC_CCR_TSVREFE;
ADC->CCR &= ~ADC_CCR_VBATE ;


HAL_ADC_Start(&hadc1);
if(HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK)
{
    sensorValue = (float)HAL_ADC_GetValue(&hadc1);
    HAL_ADC_Stop(&hadc1);
    temperature = (int32_t)((TEMP110 - TEMP30) / ((float)(*TEMP110_CAL_VALUE) - (float)(*TEMP30_CAL_VALUE)) * (sensorValue - (float)(*TEMP30_CAL_VALUE)) + TEMP30);
}
else
{
    temperature = -273;
}

return temperature;

configuración de ADC:

  ADC_ChannelConfTypeDef sConfig;

    /**Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion) 
    */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

    /**Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time. 
    */
  sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
  sConfig.Offset = 0;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }

Estoy obteniendo la salida alrededor de 35 grados. ¿Está bien tener una compensación tan grande?

    
pregunta VIPPER

2 respuestas

4

Como señaló PeterJ, el primer defecto es que debes configurar el bit ADC_CCR_TSVREFE y no restablecerlo.

No tengo idea de cómo configura la muestra y el tiempo de espera, pero espero que sea correcto. Debe tener al menos 10 µs para una medición precisa (sección de hoja de datos sobre el sensor de temperatura).

Su siguiente gran defecto es que piensa que el voltaje de referencia es de 1.21 V. Ese es el valor nominal de \ $ V_ {refint} \ $. Este voltaje no es el voltaje de referencia para el ADC. El voltaje de referencia suele ser \ $ V_ {DDA} \ $ o un voltaje diferente suministrado externamente en el pin \ $ V_ {REF +} \ $ -. Pero no puede ser más alto que \ $ V_ {DDA} \ $ ni puede ser más bajo que \ $ V_ {DDA} \ $ - 1.2 V.

Con su resultado de conversión de 950, y tomando 3.3 V, terminaría con 27.2 ° C, lo que parece un buen comienzo. Si tienes 3 V, sería -0.6 ° C, lo que también parece estar bien.

¿Por qué considero que -0.6 ° C es un buen valor? Porque el cálculo usando los valores promedio es una mierda.

No sé por qué, pero STM no promueve mucho sus valores calibrados. Cada dispositivo tiene dos valores brutos de ADC tomados a 30 ° C y 110 ° C a 3.3 V almacenados internamente. Usando esos valores, usted obtiene valores de temperatura más razonables sin realizar la calibración.

Algo a lo largo de estas líneas debería hacer:

// see datasheet for position of the calibration values, this is for STM32F429
const uint16_t* const ADC_TEMP_3V3_30C =  reinterpret_cast<uint16_t*>(0x1FFF7A2C);
const uint16_t* const ADC_TEMP_3V3_110C =  reinterpret_cast<uint16_t*>(0x1FFF7A2E);
const float CALIBRATION_REFERENCE_VOLTAGE = 3.3F;

const float REFERENCE_VOLTAGE = 3.0F; // supplied with Vref+ or VDDA

// scale constants to current reference voltage
float adcCalTemp30C = static_cast<float>(*ADC_TEMP_3V3_30C) * (REFERENCE_VOLTAGE/CALIBRATION_REFERENCE_VOLTAGE);
float adcCalTemp110C = static_cast<float>(*ADC_TEMP_3V3_110C) * (REFERENCE_VOLTAGE/CALIBRATION_REFERENCE_VOLTAGE);

uint16_t adcTempValue = SAMPLED VALUE;

float temperature = (static_cast<float>(adcTempValue) - adcCalTemp30C)/(adcCalTemp110C - adcCalTemp30C) * (110.0F - 30.0F) + 30.0F;

Estoy acostumbrado a C ++, así que tal vez no sea tu estilo de codificación, pero eso no debería ser un gran problema.

    
respondido por el Arsenal
2
// Disable Vbat signal from input channel and wake up temp sensor from power down mode
ADC->CCR &= ~(ADC_CCR_TSVREFE);

En realidad está justo enfrente :)

  

Leyendo la temperatura Para usar el sensor:   3. Seleccione el canal de entrada ADC1_IN18.   4. Seleccione un tiempo de muestreo mayor que el tiempo de muestreo mínimo especificado en la hoja de datos.   5. Establezca el bit TSVREFE en el registro ADC_CCR para activar el sensor de temperatura desde el modo de apagado   6. Inicie la conversión de ADC configurando el bit SWSTART (o mediante un disparador externo)   7. Lea los datos resultantes del SENTIDO V en el registro de datos ADC   8. Calcule la temperatura usando la siguiente fórmula: Temperatura (en ° C) = {(V SENSE - V 25) / Avg_Slope} + 25 Donde: - V 25 = V SENSE   valor para 25 ° C - Avg_Slope = pendiente promedio de la temperatura vs. V   Curva SENSE (dada en mV / ° C o µV / ° C) Consulte la hoja de datos   Sección de características eléctricas para los valores reales de V 25 y   Avg_Slope.

    
respondido por el P__J__

Lea otras preguntas en las etiquetas