[SOLVED] reading Blue Pill processor temperature sensor

electrobling
Mon Feb 26, 2018 1:20 pm
It’s been several days now that I’m stuck on this. Basically, I could not find any example anywhere to read the processor temperature using the sensor that is connected to the ADC. The STM32ADC library is chock full of functions that should do the trick, but strangely, they seem to be broken. After many hours of trying to combine them into a working program, I am still stuck. I have been over and over the class and utility files, which I have open in Eclipse. I have tried doing it both with and without interrupts. The fundamental issue is that most of the functions that seem obviously necessary to do the job, cause the BP to crash with a flashing light on PC13 and no response from serial. Here is a test program for the no interrupt approach:
#include <STM32ADC.h>
STM32ADC adc(ADC1);

uint8 tempSensor = 16;

void setup() {
Serial.begin(115200);
adc.calibrate();
adc.setSampleRate(ADC_SMPR_13_5);

// enabling either of the
// following two lines crash the system (PC13 is flashing):

// adc.setChannels(&tempSensor, 1);
// adc.enableInternalReading();
}

void loop() {
while (Serial.available() == 0);
Serial.read();
adc.startConversion();
float cpu_temp = adc.readTemp();
Serial.print("temp: ");
Serial.println(cpu_temp);
}


stevestrong
Mon Feb 26, 2018 1:48 pm
Have you tried this example: https://github.com/rogerclarkmelbourne/ … Sensor.ino ?

mrburnette
Mon Feb 26, 2018 6:32 pm
… Pito has his version too: viewtopic.php?t=1317

So, mine or Pito’s, either should work.

Ray

This is the Google search that found Pito’s code:
internal temperature sensor site:stm32duino.com


electrobling
Tue Feb 27, 2018 5:39 am
I found Pito’s code earlier on. It didn’t compile for me without errors. I think due to different Arduino IDE versions. But the above linked code compiled and ran successfully. I worked out the math to scale it to Centigrade using efficient fixed point calculations. The math in the library is way, way grossly wrong but I adapted it. I will post it soon. Thanks for the help.

stevestrong
Tue Feb 27, 2018 4:19 pm
[electrobling – Tue Feb 27, 2018 5:39 am] –
The math in the library is way, way grossly wrong but I adapted it. I will post it soon.

Please do so.


electrobling
Tue Feb 27, 2018 5:57 pm
Here is the test code:
#include <libmaple/adc.h>

const float AverageSlope = 0.0043; // V/oC, range specified .004 to .0046
const float V25 = 1.43; //Nominal volts, range specified 1.34 - 1.52
const uint16 voltsAt25C = round((V25 / 3.3) * 4096.0); // nominal ADC value at 25C

void setup() {
Serial.begin(115200);
setup_temperature_sensor();
}

void loop() {
//pause for a key input
while (Serial.available() == 0);
Serial.read();

uint16 reading = adc_read(ADC1, 16);

// show the raw ADC offset
int differential = voltsAt25C - reading;
Serial.print("raw ADC offset: ");
Serial.println(differential);

// convert ADC reading to Volts
float voltage = 3.3 * reading / 4096;
Serial.print("computed ADC volts: ");
Serial.println(voltage);

// show floating point computation value
float cpu_temp = (float)((V25 - voltage) / AverageSlope) + 25.0;
Serial.print("float calculated temp: ");
Serial.println(cpu_temp);

// compute temperature scaled by 100 as:
// long scaledTemp = 33L * differential * 100000L / 4096 / 43 + 2500;

// expression numerator and denominator factored by 32 to avoid
// possible integer overflow:
//
long scaledTemp = 33L * 3125 * differential / (128 * 43) + 2500;

Serial.print("scaled integer temp: ");
Serial.println(scaledTemp);

Serial.print("scaled integer temp as float: ");
float makeFloat = (float)scaledTemp / 100;
Serial.println(makeFloat);
Serial.println();
}

void setup_temperature_sensor() {
adc_reg_map *regs = ADC1->regs;

// 3. Set the TSVREFE bit in the ADC control register 2 (ADC_CR2) to wake up the
// temperature sensor from power down mode. Do this first 'cause according to
// the Datasheet section 5.3.21 it takes from 4 to 10 uS to power up the sensor.

regs->CR2 |= ADC_CR2_TSVREFE;

// 2. Select a sample time of 17.1 μs
// set channel 16 sample time to 239.5 cycles
// 239.5 cycles of the ADC clock (72MHz/6=12MHz) is over 17.1us (about 20us), but no smaller
// sample time exceeds 17.1us.

regs->SMPR1 = (0b111 << (3 * 6)); // set channel 16, the temp. sensor
}


mrburnette
Tue Feb 27, 2018 7:25 pm
[electrobling – Tue Feb 27, 2018 5:57 pm] –

Today could be the first time that a chunk of frozen meat was used as a CPU cooler! :)

I know you are 2nd in line behind me and we are likely not near the front of the line :lol:


electrobling
Wed Feb 28, 2018 7:03 pm
I worked on this last night and found a solution. I’m focused on making the library work, not just getting readings. There are two problems with the library as it now stands. One is the math. That one is straightforward and requires only minor changes to STM32ADC::readTemp(). The other is more subtle, and I seek advice, as the explanation escapes me and that is not a good basis on which to launch a pull request. Essentially, as it stands, calling STM32ADC::enableInternalReading() causes the system to crash with a flashing PC13. That happens on two different installations on two different PCs that I use. That function is a wrapper for enable_internal_reading(), which is implemented in util_adc.c, which is a component of the library itself. When enable_internal_reading() is relocated from util_adc to the libmaple adc.h and adc.c, all is well, and I can compile a reasonable sketch like:
#include <STM32ADC.h>
STM32ADC adc(ADC1);

void setup() {
Serial.begin(115200);
adc.calibrate();
adc.enableInternalReading();
adc.setSampleRate(ADC_SMPR_239_5);
}

void loop() {
//pause for a key input
while (Serial.available() == 0);
Serial.read();

float CPUtemp = adc.readTemp();
Serial.print("CPU internal temp : ");
Serial.print(CPUtemp);
Serial.println(" C");
}


stevestrong
Wed Feb 28, 2018 7:14 pm
I have meanwhile massively reworked the same ADC lib for F4, so i will have a look on this.
Do you get some warning messages during build?
Turn verbose on.

electrobling
Wed Feb 28, 2018 8:10 pm
I get no warnings with verbose enabled. Edit – (slap forehead) that was the modified version. I’ll put everything back like it was and try again.

stevestrong
Wed Feb 28, 2018 10:17 pm
Well, I do get a warning when trying to compile your example:
C:\Users\Luser\AppData\Local\Temp\arduino_build_730770\libraries\STM32ADC\STM32ADC.cpp.o: In function `STM32ADC::enableInternalReading()':

C:\Users\Luser\Documents\Arduino\hardware\Arduino_STM32\STM32F1\libraries\STM32ADC\src/STM32ADC.cpp:47: warning: undefined reference to `enable_internal_reading(adc_dev*)'


electrobling
Thu Mar 01, 2018 4:51 am
Thanks, that fix works perfectly. Looking forward to using the library upgrade you’re working on.

zoomx
Mon Mar 05, 2018 9:26 am
Maybe it is useful to add a function to read the raw value, something like this
uint16_t STM32ADC::readTempi() {
uint16_t result = adc_read(_dev, 16);
return result;
}

mrburnette
Mon Mar 05, 2018 1:07 pm
All of this cpu-temperature-sensor is somewhat academic since any old silicon diode or transistor can be made into a temperature sensor.
https://en.wikipedia.org/wiki/Silicon_b … ure_sensor

However, using the uC as an ambient temperature sensor implies that the uC will remain at ambient temperature: requiring the sink/source output CMOS drivers to be minimally loaded and the uC to have sufficient air flow to dissipate any self-heating.

IMHO, it is rather absurd unless the intent is to keep watch on the uC temperature proper, as in over-clocking or heavy current loading of the output. It is an interesting lab experiment, but minimally useful in any real-world device. You will get better results from a 10-cent thermistor and use of the Steinhart-Hart approximation. If 5% or less results are needed for a limited range, a thermocouple driven 8-bit A/D with look-up table will suffice: Old PICAXE example.

Ray


mrburnette
Mon Mar 05, 2018 1:15 pm

Looking forward to using the library upgrade you’re working on.

The technique is so simple that a library is simply an overkill in my opinion. Too many STM32DUINO users are hooked completely on libraries. Break your chains and write your own function or write your own library. Libraries are a two-edged sword for Arduino … yes, the Arduino infrastructure is quickly made available but the experimenter/programmer is locked-into a paradigm created by someone else. Far too many end-users simply cannot do anything if there is not a library to make it happen! This is sadness.

Challenge yourself to minimize the use of libraries for your own projects. Rework a common library that you use often, maybe a display library or a GPS library. If you are an experimenter, never write the same code the same way … there are a zillion ways to get from point A to point B … discover something new.

Ray


zoomx
Tue Mar 06, 2018 9:31 am
I never thought to use the internal temperature sensor as a working sensor.
I tested it only for fun, calibration mean only to have numbers more similar to real ones. But I found that internal was better than a DHT11 (okay, it’s easy!)
Here is an example, six days (I have 14 months of data)

SensorsTest.jpg
SensorsTest.jpg (51.83 KiB) Viewed 684 times

mrburnette
Tue Mar 06, 2018 12:56 pm
[zoomx – Tue Mar 06, 2018 9:31 am] –

I tested it only for fun, …
In this test the MCU did nothing, only a measure every 20 seconds using delay and it was inside my office.

zoomx,

I agree it is fun and the graph is rather interesting. You and I however have been schooled into knowing that the use of the internal band-gap diode is not generally for ambient temperature, some newbies may not know that. My remarks about the sensor use were more academic such that the reader did not go down a path of thinking that would lead to the belief that its use would be a good idea. :D

Ray


RogerClark
Tue Mar 06, 2018 9:01 pm
@zoomx

I had to remove the link to the image, because that site serves porn images if you click on the link

Please just upload the image to the forum


zoomx
Wed Mar 07, 2018 10:42 am
:shock:

Done! Thanks Roger and excuse my mistake using the first image hosting service that I found.


RogerClark
Wed Mar 07, 2018 8:54 pm
@zoomx

No worries.

Looks better to have the full size image in the forum anyway…

BTW. Did you put the STM32 into low power / sleep mode in between taking readings ?

I remember doing some tests when I was overclocking the STM32 to 128Mhz and it started to get warmer by a few degrees.
The heating was not a problem for its operation, as I think it was less than 5 deg increase in temperature at 128Mhz (probably 2 or 3 deg)
But, perhaps this is not a problem when running at 72Mhz


zoomx
Thu Mar 08, 2018 9:15 am
I used an Arduino and the test was made about sensors not the internal temperature. As I wrote the Atmega did nothing between measures, it was only in delay.

I am planning a test with many sensors using Arduino and an STM32 but I have to put it outside since in office temperature variation is not good for the experiment (but good for me!).
I am planning a measure also against MCU load and maybe I will use a borrowed FLIR thermal camera.


mrburnette
Thu Mar 08, 2018 12:54 pm
[zoomx – Thu Mar 08, 2018 9:15 am] –

and maybe I will use a borrowed FLIR thermal camera.

Yea! Pictures … so cool …colloquially speaking :lol:


Leave a Reply

Your email address will not be published. Required fields are marked *