No artigo anterior, falamos sobre a taxa de amostragem do conversor AD o que nos ajudou a entender sobre esse periférico no Arduino UNO. Nesse artigo vamos explorar o sensor de temperatura interno do ATmega328P, que também está agregado ao conversor A/D.
O sensor é um diodo que produz uma tensão proporcional a temperatura interna do microcontrolador. No ATmega328P este sensor está ligado ao canal 8 (ADC8) do conversor. O sensor possui uma relação linear entre tensão e temperatura, porém a tensão de saída do sensor varia de um chip para outro, devido ao seu processo de fabricação.
A temperatura interna do microcontrolador aumenta durante o seu funcionamento e, por exemplo, se um pino é usado para acionar um LED, a temperatura irá aumentar mais.
A temperatura interna pode ser monitorada para verificar se não há problema no sistema. Por exemplo, se a temperatura durante o funcionamento normal acresce por volta de 5°C e no momento ela atingiu 20°C a mais, isso indica um problema no sistema.
A faixa de temperatura de operação do Atmega328 vai de -40°C a 85°C, conforme exibido em sua folha de dados.
Esse sensor não pode ser utilizado para medir a temperatura ambiente, porém ao ligar o microcontrolador, quando o mesmo estiver desligado por um bom tempo, a temperatura lida será bem próxima da temperatura ambiente.
Abaixo são exibidos os valores típicos de temperatura versus tensão, porem para cada chip, a tensão pode variar:
A sensibilidade é de aproximadamente 1 mV/°C e precisão do valor medido é de +/- 10°C. Essa precisão pode ser melhorada para aproximadamente 2°C se o ganho e offset forem medidos e usados na equação de temperatura. Isso pode ser feito conforme sugerido no application note: AVR122 – Calibration of AVR’s internal temperature reference, com a seguinte equação:

O valor de ganho e offset são diferentes para tipos de microcontroladores. Conforme sugerido pelo tutorial no site no site Arduino Playground – InternalTemperatureSensor, a equação para o ATmega328P é:
temperatura = (ADC – 324.31) / 1.22
Sketch para teste
Primeiramente vamos entender o que será necessário configurar nos registradores do ADC. Conforme explicado na folha de dados do ATmega328P, para utilizar o sensor de tensão é necessário escolher o canal ADC8 e selecionar a tensão de referência interna de 1,1V.
Para selecionar a tensão de referência interna é necessário configurar o registrador ADMUX, os bits 7:6 – REFS1:RFS0, conforme a tabela a seguir:

Como pode-se observar na tabela deve-se colocar nível lógico 1 nesses dois bits para selecionar a referência de tensão interna.
Agora vamos selecionar o canal 8(ADC8), este canal não é selecionado através da função do arduino, devemos configurar no ADMUX os bits 3:0 – MUX3:0, conforme tabela abaixo:
Dessa forma vamos criar uma função para configuração e leitura do sensor conforme sketch a seguir:
void setup()
{
Serial.begin(9600);
Serial.println(F("Sensor de temperatura interna"));
}
void loop()
{
// exibe a temperatura em °C
Serial.println(GetTemp(),1);
delay(1000);
}
double GetTemp(void)
{
unsigned int valorADC;
double temperatura;
ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3)); //seleciona tensão interna de 1,1 V e canal 8
ADCSRA |= _BV(ADEN); // habilita o conversor AD
delay(20); // aguarda estabilização da tensão
ADCSRA |= _BV(ADSC); // inicia a conversão
//aguarda o fim da conversão
while (bit_is_set(ADCSRA,ADSC));
// le o valor da conversão
valorADC = ADCW;
// calcula o valor da temperatura
temperatura = (valorADC - 324.31 ) / 1.22;
// retorna o valor da temperatura em °C
return (temperatura);
}
A figura a seguir exibe os valores lidos de temperatura:
Saiba mais
Arduino – Entradas/Saídas digitais
Referências
Arduino Playground – InternalTemperatureSensor
AVR122 – Calibration of AVR’s internal temperature reference







Olá
Uma dúvida. O que acontece se eu tiver o pino AREF ligado ao VCC (3.6V)?
Na linha 19 não entendi como ele diz se o valor é 0 ou 1 para selecionar a tensão interna e o adc8. Alguém ainda por aí?
Guilherme, a macro _BV coloca nivel 1 no bit passdo como parametro. No caso, para selecionar a tensão interna, precisamos definir nivel lógico 1 para REFS1:RFS0, portanto na linha 19 fazemos: ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3));
Nessa operação é feito a operação OU para cada bit. Ah, o _BV(MUX3)) é para selecionar o canal 8.
Sugiro a leitura do artigo: https://embarcados.com.br/bits-em-linguagem-c/
Fico à disposição.
Essa rotina causa algum problema de leitura nas outras portas analógicas ao selecionar a tensão interna de referência 1v1 ?
Testei e funcionou legal….. bem sensível.
Maravilha, agora da para monitorar a temperatura interna do AVR.
Muito interessante, não tinha me atentado a este recurso dos avr´s.
Testarei em breve. Parabens pelo post.
Abraço.
Obrigado, Thiago.
Depois me conte como foi o seu teste. abraços
ótima publicação irei testar
Maravilha Jeferson, depois conte para nós os seus resultados. Abraços
Será que funciona também no nodemcu esp8266?
Não. Esse código foi feito para o ATmega328.
Nossa, esse artigo já foi postado á algum tempo, mas caso o autor ainda esteja por aí gostaria de fazer uma pergunta; Alterando a tensão interna para 1,1 v influencia noq exatamente? pq eu estou usando quase todas as portas do arduino UNO nesse meu projeto, incluindo as digitais… então eu gostaria de saber se pode acabar gerando algum problema…. eu iria usar esse seu código para acionar um cooler, caso a temperatura lida fosse maior que 60ºc. pq onde vai ficar o arduino tbm vai ficar um Relé de Estado Sólido que vai esquentar bastante…. att. Guilherme
Olá Guilherme, no caso é alterado a tensão de referencia do conversor AD para 1,1V diminui o valor da resolução. Não irá alterar nada nas portas. Da uma lida nesse artigo que fala sobre o conversor AD: https://embarcados.com.br/arduino-entradas-analogicas/ Abraços,