Introduction: Hidden Arduino Thermometer

About: ProvideYourOwn.com is a website devoted to people who want to make their own things and provide for their own needs. We provide information, encouragement and resources to empower people to become free from th…
Did you know that many Arduinos and ATtiny chips have a built-in thermometer? The temperature is not calibrated, so you must take a couple of readings to characterize it. I found the original idea in the article - Secret Thermometer . I have added support for the Leonardo as well as several ATtinys, and provided a function for characterizing it.

Reading the Temperature Sensor

Here is the code for reading the raw data:

long readTemp() { 
  // Read temperature sensor against 1.1V reference
  #if defined(__AVR_ATmega32U4__)
    ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0);
    ADCSRB = _BV(MUX5); // the MUX5 bit is in the ADCSRB register
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
    ADMUX = _BV(REFS1) | _BV(MUX5) | _BV(MUX1);
  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
    ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1) | _BV(MUX0);
  #else
    ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(MUX3);
  #endif

  delay(2); // Wait for ADMUX setting to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring

  uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
  uint8_t high = ADCH; // unlocks both
  long result = (high << 8) | low; // combine the two

  return result;
}

Massaging the Raw Data

Once you have the raw data, you can calibrate it by measuring two known temperatures and scaling as appropriate. Here is a simple little function to perform that normalization:
float normalizeTemperature(long rawData) { 
  // replace these constants with your 2 data points
  // these are sample values that will get you in the ballpark (in degrees C)
  float temp1 = 0;
  long data1 = 274;
  float temp2 = 25.0;
  long data2 = 304;
 
  // calculate the scale factor
  float scaleFactor = (temp2 - temp1) / (data2 - data1);

  // now calculate the temperature
  float temp = scaleFactor * (rawData - data1) + temp1;

  return temp;
}

Calibrating

To get the four constants needed, simply run the sketch/program calling the readTemp() function at room temperature. Note the temperature and the raw data point. Enter these values for either set of data points. Next, either put your Arduino in the fridge or the oven (at a really low setting) and measure your second two data points. Replace the four constants with your data. It does not matter which order you list them. You can also enter your data in either Celsius or Fahrenheit. The linear calculation is independent of units as long as you are consistent in which system you use.

I have tested this code on the Leonardo, but it should also work on the Uno, and ATtinyx4 & ATtinyx5 series chips as well. If you like this trick, there is a companion instructable/article on measuring Vcc using the internal 1.1 volt reference that may be of interest as well.
Electronics Tips and Tricks

Participated in the
Electronics Tips and Tricks