Arduino / AVR internal temperature sensor interface
Measure Arduino chip temperature
Intro
Here we describe a class for reading out the temperature sensor inside the ATmega328. This class is inspired on the library “InternalTemp” from SpikedCola and marcello.romani. The class ChipTemp is kept as small and simple as possible.
Details
- Resolution 1 degree or 0.1 degree
- Accuracy >=1°C
- Requires between 166 and 204 bytes program memory
- Both the offset and the gain can be calibrated and set in decimals
Restrictions
The temperature sensor inside the ATmega328 has many restrictions. The accuracy without calibration is very poor. An accuracy of >=1% can be achieved but requires a complicated two point calibration. Even than, the accuracy will be influenced by the chip self heating and ADC noise. The internal temperature sensor is useful when just an indication of the temperature is required. But because ChipTemp only uses about 200 bytes, it never hurts to add it to the software to monitor the chip temperature.
Mostly it is preferable to use special IC’s such as the analog LM335 or the digital LM75 temperature sensors which cost less than $2.
Example graph
Graph °Celsius and °deci-Celsius
Temperature sensor
The sensor is a diode that produces a temperature dependent voltage. This voltage is measured with the 10 bit ADC. The voltage has a linear relationship to temperature of about 1.06 mV/°C, whereby 1 LSB = 1mV.
Test software
Connect an ATmega328 Arduino board and run ChipTempTest.pde to print the internal temperature in degrees Celsius, Fahrenheit, deci-Celsius and deci-Fahrenheit to the screen. Deci means that the temperature resolution is 0.1 degree.
#include <avr/pgmspace.h>
#include "ChipTemp.h" ChipTemp chipTemp; void setup() void loop() |
ChipTemp class
Place the files ChipTemp.cpp and ChipTemp.h in a new library subfolder \libraries\ChipTemp. For troubleshooting see HERE.
ChipTemp.cpp
#if ARDUINO >= 100
#include "Arduino.h" #include "ChipTemp.h" ChipTemp::ChipTemp() inline void ChipTemp::initialize() inline int ChipTemp::readAdc() int ChipTemp::deciCelsius() int ChipTemp::celsius() int ChipTemp::deciFahrenheit() int ChipTemp::fahrenheit() |
ChipTemp.h
#ifndef ChipTemp_H
#define ChipTemp_H
// ATmega328 temperature sensor interface // Calibration values, set in decimals static const int samples = 1000; // must be >= 1000, else the gain setting has no effect // Compile time calculations class ChipTemp #endif |
Notes to the software
- The initialisation has to be done each time, because ADMUX can be overwritten in meantime.
- To get a usefull accuracy we have to take the average of 1000 samples. This reduces the ADC noise. Also the resolution is increased to 0.1°, but is not the reason because the accuracy can never be 0.1°.
- Some calculations are done during compile time and thus uses no program memory.
- The accuracy at optimal circumstances can be 1%, which is higher than the resolution of 0.1 degree.
- Small modifications make ChipTemp also useful as interface for external analog temperature sensors.
Rounding
In mathematically respect, rounding is a tricky business. The method round half up is widely used in many disciplines. This is the lidfunction Celsius () with using rounding half up:
int ChipTemp::celsius() |
See here the result:
We see that the rounding is unsymmetrical. Therefore we don’t use the round half up method.
Accuracy
The diode voltage is highly linear, but due to process variations the temperature sensor output voltage varies from one chip to another. Also, the internal voltage reference used as the ADC reference voltage varies with temperature. Calibration is therefore mandatory to achieve useful results. Also the ADC Noise Reduction Mode can be used to increase accuracy.
Calibration
For a detailed calibration description, see the Atmel application note AVR122: Calibration of the AVR's internal temperature reference. Two calibration methods are useful:
- One-point calibration. Offset removal using room temperature as reference gives +/-5°C accuracy from -30°C to 100°C and +/-3°C accuracy between 0°C and 85°C.
- Two-point calibration. Here, +/-1°C accuracy from 5°C to 95°C can be achieved.
One-point calibration
Set the offset in ChipTemp.h to:
offset’ = deciCelsius * gain / 10 + offset – gain * T
Definitions
offset’ = the new offset value for ChipTemp.h
gain = 1.06154
offset = is the offset in ChipTemp.h (335.2)
T = room temperature
Formula distraction
deciCelsius = 10 * (ADC - offset) / gain
ADC = gain’ * T + offset’
deciCelsius = (gain’ * T + offset’ – offset) * 10 / gain
if offset’ = offset and gain’ = gain
deciCelsius = 10T
Assume gain’ = gain
offset’ = deciCelsius * gain / 10 + offset – gain * T
Set offset in ChipTemp.h to offset’
To be done
The ADC Noise Reduction Mode can be used to increase accuracy but this has not yet been implemented.