0

How do I read CPU temperature in Arduino?
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

How do I read CPU temperature in Arduino?

by ewbrom on Tue Mar 19, 2019 2:13 pm

Hi,
I'm running the Trinket M0 in the Arduino environment, and would like to read the CPU's internal temperature sensor. I found the information for CircuitPython, but not Arduino.

Thanks in advance,
Erik

ewbrom
 
Posts: 2
Joined: Tue Mar 19, 2019 2:10 pm

Re: How do I read CPU temperature in Arduino?

by XRAD on Wed Mar 20, 2019 9:04 pm

The SMART SAMD21 family does have internal temp sensors: 'Ctrl F' when on the Samd21 data sheet will give 37 references.

Some code logic needs to be followed for function:
https://www.avrfreaks.net/forum/samd21- ... -pin-issue

seems like a cool project. Hope it works out! With access to only a few pins, you would probably have to reconfigure the internal ADC settings to get the readings(which may only be available on certain pins). Post some code when you get it working.

XRAD
 
Posts: 440
Joined: Sat Nov 19, 2016 3:28 pm

Re: How do I read CPU temperature in Arduino?

by BryonMiller on Thu Mar 21, 2019 9:08 am

@ewbrom, here are routines I use for a Feather M0. Should work for Trinket since it is same SAMD21. You must call tempSetup() (or logdata()) before calling tempDefF().

Let me know if it does not work for you.

Code: Select all | TOGGLE FULL SIZE
int ROOM_TEMP_VAL_INT,ROOM_TEMP_VAL_DEC,HOT_TEMP_VAL_INT,HOT_TEMP_VAL_DEC;
int ROOM_INT1V_VAL,HOT_INT1V_VAL,ROOM_ADC_VAL,HOT_ADC_VAL;

int oldResolution,oldGain,oldReference;

void tempSetup()
{
//read Temperature Log Row Content
logdata();
}

float tempDegF()
{
uint32_t itemp = readInternalTemperature();
float temperature = map(itemp,
   ROOM_ADC_VAL,
   HOT_ADC_VAL,
   ROOM_TEMP_VAL_INT*10+ROOM_TEMP_VAL_DEC,
   HOT_TEMP_VAL_INT*10+HOT_TEMP_VAL_DEC)/10.0;
temperature = 32.0+temperature*9/5;
return temperature;
}

void logdata()
{
/* read Temperature Log Row Content per
Atmel SAM D21E / SAM D21G / SAM D21J
SMART ARM-Based Microcontroller DATASHEET
Section 36.9.8.2
*/
uint64_t value = *(uint64_t*)0x00806030;
Serial.print((uint32_t) (value >> 32),HEX);
Serial.println((uint32_t) value,HEX);
ROOM_TEMP_VAL_INT =  value & 0x00000000000000FF;
ROOM_TEMP_VAL_DEC = (value & 0x0000000000000F00) >> 8;
HOT_TEMP_VAL_INT =  (value & 0x00000000000FF000) >> 12;
HOT_TEMP_VAL_DEC =  (value & 0x0000000000F00000) >> 20;
ROOM_INT1V_VAL =    (value & 0x00000000FF000000) >> 24;
HOT_INT1V_VAL =     (value & 0x000000FF00000000) >> 32;
ROOM_ADC_VAL =      (value & 0x000FFF0000000000) >> 40;
HOT_ADC_VAL =       (value & 0xFFF0000000000000) >> 52;
Serial.print("ROOM_TEMP_VAL_INT ");Serial.println(ROOM_TEMP_VAL_INT);
Serial.print("ROOM_TEMP_VAL_DEC ");Serial.println(ROOM_TEMP_VAL_DEC);
Serial.print("HOT_TEMP_VAL_INT ");Serial.println(HOT_TEMP_VAL_INT);
Serial.print("HOT_TEMP_VAL_DEC ");Serial.println(HOT_TEMP_VAL_DEC);
Serial.print("ROOM_INT1V_VAL ");Serial.println(ROOM_INT1V_VAL);
Serial.print("HOT_INT1V_VAL ");Serial.println(HOT_INT1V_VAL);
Serial.print("ROOM_ADC_VAL ");Serial.println(ROOM_ADC_VAL);
Serial.print("HOT_ADC_VAL ");Serial.println(HOT_ADC_VAL);

}

// Wait for synchronization of registers between the clock domains
static __inline__ void syncADC() __attribute__((always_inline, unused));
static void syncADC() {
  while (ADC->STATUS.bit.SYNCBUSY == 1)
    ;
}

uint32_t readInternalTemperature(void)
// thanks to much help from the file "wiring_analog tempsensor"
{
// save original analogRead setup data
//  this is only needed if you're planning on using
//  ADC's and you don't want to worry about this
//  function thrashing their setup.
oldResolution = ADC->CTRLB.bit.RESSEL;
oldGain = ADC->INPUTCTRL.bit.GAIN;
oldReference = ADC->REFCTRL.bit.REFSEL;

uint32_t valueRead = 0;

analogReadResolution(12);
analogReference(AR_INTERNAL1V0);

SYSCTRL->VREF.bit.TSEN = 1;
ADC->SAMPCTRL.reg = 4;//ADC_TEMP_SAMPLE_LENGTH;
syncADC();
ADC->AVGCTRL.reg = ADC_AVGCTRL_ADJRES(2) | ADC_AVGCTRL_SAMPLENUM_4;
syncADC();
//  ADC->INPUTCTRL.bit.MUXPOS = ADC_POSITIVE_INPUT_TEMP; // Temperature sensor
ADC->INPUTCTRL.bit.MUXPOS = 0x18; // Temperature sensor
//  ADC->INPUTCTRL.bit.MUXNEG = ADC_NEGATIVE_INPUT_GND; // Internal ground
ADC->INPUTCTRL.bit.MUXNEG = 0x18; // Internal ground

// Control A
/*
* Before enabling the ADC, the asynchronous clock source must be selected and enabled, and the ADC reference must be
* configured. The first conversion after the reference is changed must not be used.
*/
syncADC();
ADC->CTRLA.bit.ENABLE = 1;             // Enable ADC

// Start conversion
syncADC();
ADC->SWTRIG.bit.START = 1;

while (ADC->INTFLAG.bit.RESRDY == 0);   // Waiting for conversion to complete
// Clear the Data Ready flag
ADC->INTFLAG.reg = ADC_INTFLAG_RESRDY;

// Start conversion again, since The first conversion after the reference is changed must not be used.
syncADC();
ADC->SWTRIG.bit.START = 1;

// Store the value
while (ADC->INTFLAG.bit.RESRDY == 0);   // Waiting for conversion to complete
valueRead = ADC->RESULT.reg;

syncADC();
ADC->CTRLA.bit.ENABLE = 0;             // Disable ADC
syncADC();

ADC->CTRLB.bit.RESSEL = oldResolution;
syncADC();
ADC->INPUTCTRL.bit.GAIN = oldGain;
syncADC();
ADC->REFCTRL.bit.REFSEL = oldReference;
syncADC();


return valueRead;
}


I found that CPU temp starts out at ambient temp but rises as the core of the CPU warms up. Temp stabilizes at surrounding temp+offset after a while. You'll have to figure out the offset and the while.

Bryon

BryonMiller
 
Posts: 165
Joined: Fri Mar 04, 2016 10:34 am

Re: How do I read CPU temperature in Arduino?

by ewbrom on Thu Mar 21, 2019 11:42 pm

Bryon,
Yes, that works! Problem solved, thank you very much.

Erik

ewbrom
 
Posts: 2
Joined: Tue Mar 19, 2019 2:10 pm

Please be positive and constructive with your questions and comments.