STM32 MCU - El sensor de temperatura da valores extraños

Estoy jugando con una placa Nucleo-F103RB STM32 y estoy tratando de medir la temperatura ambiente usando su sensor interno. Activo el ADC y obtengo datos normalmente a través de la HAL_ADC_GetValue()función (el valor es de alrededor de 1700 - 1800 y varía con la temperatura como debería) pero el problema es que obtengo números realmente extraños cuando convierto a Celsius usando la fórmula dada en el manual, a saber :

V 25 V A D C A v gramo S yo o pag mi + 25
(alrededor de 70-80 grados cuando la temperatura real no supera los 25).

Sospecho que tiene que ver con la forma en que estoy convirtiendo el valor de ADC en voltios, pero no puedo ver algo obviamente incorrecto, así que vine a preguntar aquí.

El código está aquí:

#include "TempMsr.h"

volatile uint32_t sensorData = 0;
volatile uint32_t temp = 0;

uint32_t getTemp(ADC_HandleTypeDef* ADCHandle)
{
    sensorData = HAL_ADC_GetValue(ADCHandle);
    temp = ((V25 * 1000 - sensorData * 0.8) / AVGSLOPE) + 25;

    //V25 and sensorData must be in mV for this formula to work, as the
    //AVGSLOPE value is given in mV/oC

    //the 0.8 multiplication comes from dividing the max ADC voltage (3.3V) with its resolution (12 bits => 4096) which is 0.8mV/ADC unit

    return temp;
}

Su archivo de cabecera:

#ifndef TEMPMSR_H_
#define TEMPMSR_H_

#include "stm32f1xx_hal.h"

#define AVGSLOPE 4.3
//average slope of T-V chart according to datasheet pg 79
//(min is 4 mV/C, max 4.6, default (4.3): typical)

#define V25 1.43
//voltage of temperature sensor at 25C according to datasheet pg 79 (in V)
//(min is 1.34, max is 1.52, default(1.43): typical)

uint32_t getTemp(ADC_HandleTypeDef* ADCHandle);


#endif /* TEMPMSR_H_ */

¡Gracias de antemano!

EDITAR: Acabo de notar en el manual de referencia que el sensor tiene un sesgo (de hasta +- 45 grados) debido al proceso de fabricación, que es diferente en cada chip y no lo calculé para mi MCU particular ni lo incluí en la formula. ¿Podría ser este el problema?

¿Intentaste calcular a mano? ¿Obtienes el mismo resultado? Veo que escribiste la fórmula como matemáticas de coma flotante, mientras usas números enteros sin signo.
@MarkoBuršič Al hacer esto a mano en este momento, obtengo 5, que sigue siendo incorrecto. ADC da 1895, (que multiplicado por 0,8 es 1526mV)
El problema es que mezclas salvajemente el punto flotante y el punto fijo, sin ningún pensamiento detrás. Cada operando de cada operador tiene un tipo, y el tipo que elija importa mucho. No hay absolutamente ninguna necesidad de usar punto flotante para esta ecuación simple. Tampoco necesita usar mV, puede convertir de mV a valor bruto y mantener todo en un punto fijo entero. Y si no recuerdo mal, Cortex M3 ni siquiera tiene FPU. No es una computadora.

Respuestas (4)

No soy experto en C, tal vez

Tienes que analizar uint para flotar, luego calcular, luego analizar nuevamente para uint, si el resultado tiene que ser uint.

{
    sensorData = HAL_ADC_GetValue(ADCHandle);
    temp = (uint32_t)(((V25 * 1000.0 - (float)sensorData * 0.8) / AVGSLOPE) + 25.0);

    //V25 and sensorData must be in mV for this formula to work, as the
    //AVGSLOPE value is given in mV/oC

    //the 0.8 multiplication comes from dividing the max ADC voltage (3.3V) with its resolution (12 bits => 4096) which is 0.8mV/ADC unit

    return temp;
}
Hice esto ahora mismo, obtengo 5.
Nota: es mejor (para el rendimiento) multiplicar primero por 8 que dividir por 10, por lo que no se necesitan cálculos flotantes. Tenga cuidado con los valores excesivos o insuficientes.
Resuelto. ¡Recuerden siempre lanzar sus números correctamente, niños! Además, no tomé en cuenta el sesgo del sensor, lo que significa que el 5 en realidad era correcto.

Habiendo realizado la detección de temperatura en un STM32 anteriormente, tengo una razón para creer que la fórmula es incorrecta, mientras que una documentación anterior de STM32F207 tenía la fórmula correcta.

Como la pendiente es positiva, las medidas más grandes (valor ADC o voltaje) significan una temperatura más alta. Entonces la fórmula debería tener (Vadc-V25), no (V25-Vadc).

Aún así, su punto sobre las compensaciones es válido. La medición V25 tiene una tolerancia de +/- 90 mV que calcula una tolerancia de aproximadamente +/- 21 grados centígrados. La documentación de ST ha indicado que no es preciso para medir temperaturas absolutas sin calibración, mientras que puede usarse para rastrear cambios de temperatura. En la práctica, ha sido lo suficientemente preciso sin calibración para controlar un ventilador para evitar que un producto se sobrecaliente.

¿Quién te habló de la tolerancia de 90mV? No confíes más en él.
La hoja de datos más reciente del chip STM32F103 en cuestión.

Un sensor de temperatura en el chip no va a medir la temperatura del aire ambiente, va a medir la temperatura del chip del que forma parte. Un sensor de temperatura integrado en un microcontrolador mide la temperatura del microcontrolador, que debería ser significativamente más alta que la temperatura del aire ambiente si el microcontrolador está haciendo algún trabajo.

En principio, sí. Pero no mucho en un MCU de gama media-baja como este. Un SoC con más silicio funcionando de diez a veinte veces el reloj, claro, el autocalentamiento es un problema real. Pero para esta parte, solo unos pocos grados a menos que haya una falla eléctrica o un circuito externo al chip lo esté calentando.
O para decirlo de otra manera, si el chip estuviera realmente en los 70-80 C informados, tocarlo resultaría en una quemadura en el dedo. Si bien en realidad no es probable que se sienta cálido, a menos que algo más lo esté calentando.
@ChrisStratton Bueno, hay mucha masa entre el chip y la superficie del paquete... No estoy seguro de que se queme el dedo si la matriz estuviera a 70 C, pero tiene razón en que sin duda se sentiría caliente. El punto principal que estaba tratando de hacer es que el sensor no informaría la temperatura del aire ambiente.
Pero apenas así en este caso. Mientras que la pregunta es sobre una diferencia drástica. Por lo tanto, el problema no es lo que está sugiriendo. Si esto juega un papel en absoluto, eso solo será evidente después de que se superen los grandes problemas que se interponen primero en el camino. Y no, realmente no hay mucha masa allí: la masa total es probablemente menos de un gramo.
@ElliotAlderson stm32F103 no aumentará su temperatura ni siquiera en un grado.
@P__J__ Si entiendo correctamente la hoja de datos, la corriente de la fuente de alimentación a 72 MHz puede ser de 65 mA. A 3,6 V, eso es 234 mW. Con el LQFP100, la resistencia térmica es de 46 grados por vatio, por lo que la matriz estaría 10 grados más caliente que la temperatura ambiente.

En STM32F0 y STM32L4 con los que estamos trabajando en este momento, el sensor de temperatura interno está precalibrado durante la producción y también se puede calibrar durante el tiempo de ejecución con la referencia de voltaje interno.

El cálculo de la temperatura también es diferente del valor adc normal al cálculo del voltaje porque incluye los valores de calibración.

Tal vez su controlador tenga la misma característica. La descripción debe estar disponible en el capítulo ADC en el Manual de referencia. Diría que la resolución en nuestra aplicación es de +/- 1 grado.