2
\$\begingroup\$

I'm fooling around with a Nucleo-F103RB STM32 board and I'm trying to measure the ambient temperature using its internal sensor. I activate the ADC and get data normally via the HAL_ADC_GetValue() function (the value is around 1700 - 1800 and varies with temperature as it should) but the problem is that I get really weird numbers when converting to Celsius using the formula given in the manual, namely: $$\frac{V_{25} - V_{ADC}}{AvgSlope} + 25$$ (about 70-80 degrees when the real temperature is no more than 25).

I suspect that has to do with the way I'm converting the ADC value into volts, but I can't see something obviously wrong, so I came to ask here.

Code is here :

#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;
}

Its header file:

#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_ */

Thanks in advance!

EDIT: I just noticed in the reference manual that the sensor has a bias (of up to +- 45 degrees) due to the manufacturing process, which is different on every chip and I have neither calculated it for my particular MCU nor included it in the formula. Could this be the problem?

\$\endgroup\$
  • \$\begingroup\$ Did you try to calculate by hand? Do you get the same result? I see you wrote the formula as float point math, while you are using unsigned integers. \$\endgroup\$ – Marko Buršič Oct 12 '18 at 12:57
  • \$\begingroup\$ @MarkoBuršič Doing this by hand right now, I get 5, which is still wrong. ADC gives out 1895, (which multiplied by 0.8 is 1526mV) \$\endgroup\$ – lightspot21 Oct 12 '18 at 13:07
  • \$\begingroup\$ The problem is that you wildly mix floating point and fixed point, without any thought behind it. Every operand to every operator has a type, and which type you pick matters a lot. There is absolutely no need whatsoever to use floating point for this simple equation. Nor do you need to use mV, you can convert from mV to raw value and keep everything in integer fixed point. And if I remember correctly, Cortex M3 doesn't even have a FPU. It is not a PC. \$\endgroup\$ – Lundin Oct 15 '18 at 10:52
1
\$\begingroup\$

I'm not C expert, perhaps

You have to parse uint to float, then calculate, then parse again to uint, if the result has to be 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;
}
\$\endgroup\$
  • \$\begingroup\$ Did this right now, I get 5. \$\endgroup\$ – lightspot21 Oct 12 '18 at 13:10
  • \$\begingroup\$ Note: it is better (for performance) to first multiply by 8, than divide by 10, so no float calculations are needed. Watch out for over/underflowing values. \$\endgroup\$ – Michel Keijzers Oct 12 '18 at 14:28
  • \$\begingroup\$ Solved. Always remember to cast your numbers correctly, kids! Also, I didn't account for the bias of the sensor, which means that the 5 was correct actually. \$\endgroup\$ – lightspot21 Oct 13 '18 at 9:05
0
\$\begingroup\$

An on-chip temperature sensor is not going to measure the temperature of the ambient air, it's going to measure the temperature of the chip it is part of. A temperature sensor built in to a microcontroller is measuring the microcontroller's temperature, which should be significantly higher than the ambient air temperature if the microcontroller is doing any work.

\$\endgroup\$
  • \$\begingroup\$ In principle, yes. But not by much on a mid low end MCU such as this. An SoC with more silicon running at ten to twenty times the clock, sure, self heating is a real problem. But for this part, only a few degrees unless there is an electrical fault or circuitry external to the chip is heating it. \$\endgroup\$ – Chris Stratton Oct 12 '18 at 14:57
  • \$\begingroup\$ Or to put it another way, if the chip was actually at the 70-80 C reported, touching it would result in a burned finger. While in reality it's not likely to be able to be felt as even warm, unless something else is putting heat into it. \$\endgroup\$ – Chris Stratton Oct 12 '18 at 15:41
  • \$\begingroup\$ @ChrisStratton Well, there's a lot of mass between the chip and the surface of the package...I'm not sure that you would burn your finger if the die was at 70 C but you are right that it would certainly feel warm. The main point I was trying to make is that the sensor would not be reporting the ambient air temperature. \$\endgroup\$ – Elliot Alderson Oct 12 '18 at 18:45
  • \$\begingroup\$ But only barely so in this case. While the question is about a drastic difference. Hence the issue is not what you are suggesting. If this plays a role at all, that will only be evident after the huge issues standing first in the way is overcome. And no, there really isn't much mass there - the overall mass is likely less than a gram. \$\endgroup\$ – Chris Stratton Oct 12 '18 at 18:53
  • \$\begingroup\$ @ElliotAlderson stm32F103 will not not increase its temperarture even by one degree. \$\endgroup\$ – P__J__ Oct 14 '18 at 22:20
0
\$\begingroup\$

Having done temperature sensing on a STM32 before, I have a reason to believe that the formula is incorrect, while an older STM32F207 documentation had the correct formula.

As the slope is positive, larger measurements (ADC value or voltage) means larger temperature. So the formula should have (Vadc-V25), not (V25-Vadc).

Still your point on the offsets are valid. The V25 measurement has a +/- 90 mV tolerance which calculates to about +/- 21 degrees celcius tolerance. ST documentation has stated it is not accurate for measuring absolute temperatures without calibration, while it can be used to track changes in temperature. In practice, it has been accurate enough without calibration to control a fan to prevent a product from overheating.

\$\endgroup\$
  • \$\begingroup\$ Who told you about 90mV tolerance? Do not trust him anymore. \$\endgroup\$ – P__J__ Oct 14 '18 at 22:22
  • \$\begingroup\$ The very latest datasheet of the STM32F103 chip in question. \$\endgroup\$ – Justme Oct 15 '18 at 18:46
0
\$\begingroup\$

On STM32F0 and STM32L4 we are working with at the moment, the internal temperature sensor is pre calibrated during production and can also be calibrated during runtime with the internal voltage reference.

The calculation of the temperature is also different from the normal adc value to voltage calculation because it includes the calibration values.

Maybe your controller does have the same feature. The description should be available in the ADC chapter in the Reference Manual. I would say that the resolution in our application is +/- 1 degree.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.