2020-09-01 10:50 AM
Using a Nucleo STM32F091RC board, I have configured the ADC to measure all channels in a sequence, i.e. all 10 ADC pins that particular chip has, and the 3 internal ones: temperature, vrefint, vbat.
I calibrated the ADC, waited the time before enabling as said in the errata, measured Vrefint a bunch of times (with only that channel in the sequence at that time, just in case MUXing might create slight crosstalk), calculate VDDA from the reference and the stored values from system memory.
When I meausre voltages on the 10 external pins, they seem all correct and reasonably accurate.
Vbat also looks ok. Vrefint also looks like that is said in the datasheet.
But the internal temperature is totally off.
It measures around 95 °C, but the MCU clearly feels less than human body temperature.
I have tried 3 things to calculate it:
All 3 variants get a totally unreasonable result around 95 degrees Celsius.
I checked with freezing spray on the MCU case, and indeed, after sprays a couple seconds, the measured / calculated temperature drops to almost half that, to then raise again to ~ 95°C after a few seconds.
So the temperature channel is definitely enabled, and it is the correct index in the conversion sequence.
Also note that I used the maximum available sampling time of 239.5 ADC ticks.
The ADC value I get there is roughly 1400. it's compensated for vdda already, without compensation iw would be roughly 1500.
Are those usual values for this temperature sensor output @ 3V3?
What the heck could still be wrong?
For reference, the code from the reference manual I used (almost verbatim, just omitting the reference voltage compensation as the result would be ~ 1 anyway - and yes, I also checked what my measured VDDA is - it is very close to the nominal 3300.).
static unsigned calc_tempr(int ADC_DR)
{
/* Temperature sensor calibration value address */
#define TEMP110_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FFFF7C2))
#define TEMP30_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FFFF7B8))
int32_t temperature; /* will contain the temperature in degrees Celsius */
temperature = ADC_DR - (int32_t) *TEMP30_CAL_ADDR;
temperature = temperature * (int32_t)(110 - 30);
temperature = temperature / (int32_t)(*TEMP110_CAL_ADDR - *TEMP30_CAL_ADDR);
temperature = temperature + 30;
return temperature;
}
Solved! Go to Solution.
2020-12-04 03:50 AM
Been a while... So I have been looking back at this.
Funny. I have this chain of processing set up where, so far, all ADC channels are treated uniformly, just that they get a different to-end-unit conversion routine.
Within that uniform processing chain, channels get compensated by a measured VDDA via the VrefInt bandgap reference and factory-stored calibration data.
I overlooked that I also applied it to the temperature, too, but it has its own compensation scheme and own factory-written calibration data, and the formula doesn't call for VDDA.
I now get sensible results, e.g. it is now 21°C room temperature, and the internal temperature now measures 30°C, while the program is mostly running doing ADC conversion, some calculations on top of that, some slow-ish PWM.
Is that a reasonable value to expect?
Then I guess the mystery is solved ;)
2020-09-01 01:30 PM
Try to measure only the temperature sensor (after calibration), perhaps in a simple polled loop. Observe, whether the value changes when you hold (i.e. heat up) the chip.
[EDIT] > I checked with freezing spray on the MCU case,
Sorry I did not notice this.
Still, try to run minimal code.
[/EDIT]
You do set ADC_CCR_TSEN and wait the time given in DS (10us), do you. What's the ADC clock?
Strip the code to absolute minimum compilable and post it.
JW
2020-09-01 04:59 PM
I think you're trying the right things. Probably just a bug somewhere in your code. I would double check your assumptions.
2020-09-03 07:50 AM
I guess reading the temp. as only value in the sequence might be worth a try, I'll do that later and get back. For now priority is on something else.
2020-12-04 03:50 AM
Been a while... So I have been looking back at this.
Funny. I have this chain of processing set up where, so far, all ADC channels are treated uniformly, just that they get a different to-end-unit conversion routine.
Within that uniform processing chain, channels get compensated by a measured VDDA via the VrefInt bandgap reference and factory-stored calibration data.
I overlooked that I also applied it to the temperature, too, but it has its own compensation scheme and own factory-written calibration data, and the formula doesn't call for VDDA.
I now get sensible results, e.g. it is now 21°C room temperature, and the internal temperature now measures 30°C, while the program is mostly running doing ADC conversion, some calculations on top of that, some slow-ish PWM.
Is that a reasonable value to expect?
Then I guess the mystery is solved ;)
2020-12-04 07:14 AM
> Is that a reasonable value to expect?
Yes, a +9°C difference between ambient and chip temperature is quite normal.
Glad you got it solved.