Sensor de temperatura com termistor no Arduino: NTC e PTC

Por Diego J. Stefanello e Ricardo B. Morim. Publicado originalmente no blog da TOT Engenharia (2018–2019) e revisado em 2026: equações corrigidas, código reescrito e figuras refeitas.

Neste artigo vamos mostrar como usar um termistor (NTC ou PTC) como sensor de temperatura com o Arduino. O termistor é um resistor cuja resistência elétrica varia com a temperatura. Por ser barato e simples de usar, é um dos sensores de temperatura mais comuns que existem.

Termistores: nunca vi… ou será que já vi?

O termistor aparece em muitas aplicações, de termômetros clínicos e eletrodomésticos a equipamentos industriais. Um exemplo está na Figura 1: no trocador de calor de um condicionador de ar do tipo split há dois NTCs atuando como sensores de temperatura.

Dois sensores NTC fixados no trocador de calor de um ar-condicionado split, indicados por setas
Figura 1: NTCs no trocador de calor de um condicionador de ar do tipo split.

Dada a sua simplicidade e versatilidade, vamos montar um termômetro com um termistor e uma placa Arduino Uno.

NTC e PTC

Existem basicamente dois tipos de termistor: o de coeficiente de temperatura negativo (NTC, do inglês Negative Temperature Coefficient) e o de coeficiente de temperatura positivo (PTC, Positive Temperature Coefficient).

  • No NTC, a resistência diminui quando a temperatura aumenta.
  • No PTC, a resistência aumenta quando a temperatura aumenta.

Em nenhum dos dois casos a relação é linear (muito menos proporcional): no NTC, a resistência cai aproximadamente de forma exponencial com a temperatura. Por isso o fabricante fornece a curva resistência × temperatura na forma de tabela ou de equação com parâmetros. A Figura 2 mostra alguns encapsulamentos comuns.

Diversos encapsulamentos de termistores: disco, gota de epóxi, axial de vidro e SMD
Figura 2: Aspecto físico de alguns termistores. Fonte: electrical4u.com.

Simbologia e especificações

Os símbolos elétricos mais usados para o termistor estão na Figura 3.

Dois símbolos de termistor: retângulo e zigue-zague, ambos cortados por uma linha diagonal
Figura 3: Símbolos do termistor.

Ao escolher um termistor, fique atento a:

  • Resistência nominal, normalmente especificada a 25 °C (R25). Um “NTC de 10 kΩ” tem 10 kΩ a 25 °C, dentro da sua tolerância (tipicamente ±1 % a ±10 %).
  • Constante β (Beta), que descreve a inclinação da curva. O datasheet costuma informá-la entre duas temperaturas, por exemplo β25/85 = 3950 K.
  • Potência máxima e constante de dissipação (em mW/°C). A corrente que passa pelo termistor o aquece (autoaquecimento) e isso aparece como erro de medição. Por isso a corrente de polarização deve ser pequena.

O termistor como sensor de temperatura no Arduino

O Arduino não mede resistência diretamente: o conversor analógico-digital (ADC) mede tensão. A forma mais simples de converter a resistência do termistor em tensão é um divisor resistivo, o mesmo arranjo usado no artigo do sensor de luz LDR. O circuito está na Figura 4.

Esquema: termistor T1 entre +5 V e o nó ADC-ARDUINO; resistor R1 de 10 kΩ entre o nó e 0 V
Figura 4: Divisor resistivo para medir a temperatura com o ADC do Arduino.

O resistor R1 tem valor fixo e polariza o termistor T1. Quando a temperatura muda, a resistência de T1 muda e, pela Lei de Ohm, a tensão no nó entre T1 e R1 também muda. Esse nó vai para uma entrada analógica do Arduino. Com a tensão medida calculamos a resistência de T1 e, com ela, a temperatura.

Da tensão medida à resistência do termistor

Chamemos de \(R_{T1}\) a resistência do termistor e de \(V_o\) a tensão medida. Vamos supor que a entrada do ADC não drena corrente do divisor. Na prática, o datasheet do ATmega328P recomenda impedância de fonte de até 10 kΩ; aqui ela vale \(R_1 \parallel R_{T1} \approx 5\ \text{k}\Omega\) a 25 °C, então a suposição é razoável. A corrente \(i_s\) que percorre o divisor é:

\[i_s = \frac{5\ \text{V}}{R_{T1} + R_1}\]

e a tensão de saída é a queda em \(R_1\):

\[V_o = i_s\, R_1 = \frac{5\ \text{V} \cdot R_1}{R_{T1} + R_1}\]

Isolando \(R_{T1}\):

\[\begin{aligned} R_{T1} + R_1 &= \frac{5\ \text{V} \cdot R_1}{V_o} \\ R_{T1} &= R_1 \left( \frac{5\ \text{V}}{V_o} – 1 \right) \\ &= R_1\, \frac{5\ \text{V} – V_o}{V_o} \end{aligned}\]

Há ainda uma simplificação útil. O ADC do Uno (10 bits) entrega \(N = 1024\, V_o / V_{ref}\), e por padrão \(V_{ref}\) é a própria alimentação de 5 V que alimenta o divisor. Substituindo, a tensão desaparece da equação:

\[R_{T1} = R_1 \left( \frac{1024}{N} – 1 \right)\]

Essa é uma medição ratiométrica: variações na tensão de 5 V do USB afetam igualmente o divisor e a referência do ADC e se cancelam. Esse cancelamento só acontece se o divisor estiver ligado ao mesmo 5 V usado como referência.

Da resistência à temperatura

O termistor é não linear. Em baixas temperaturas, uma pequena variação de temperatura provoca uma grande variação de resistência; em altas temperaturas a variação é bem menor. A Figura 5 mostra a curva do NTC usado neste artigo e a leitura do ADC correspondente no circuito da Figura 4.

Gráfico em dois painéis: resistência do NTC em escala log caindo de cerca de 39 kΩ a 0 °C para 0,7 kΩ a 100 °C, e leitura do ADC subindo de cerca de 208 para 960 contagens
Figura 5: Resistência do NTC (escala logarítmica) e leitura do ADC em função da temperatura. Curva calculada pelo modelo de Steinhart–Hart ajustado às três medições deste artigo; o tracejado é extrapolação.

Há três formas usuais de converter resistência em temperatura: tabela de correspondência, equação de Steinhart–Hart e equação do fator Beta.

Método 1: tabela de correspondência

Grava-se no Arduino uma tabela com a temperatura correspondente a cada leitura do ADC (ou a faixas de leitura), interpolando entre pontos se necessário. O método é rápido e não exige cálculo com ponto flutuante, mas a tabela vale apenas para aquele termistor e aquele resistor R1. A Tabela 1 foi calculada para o nosso circuito.

Temperatura (°C)RNTC (kΩ)Vo (V)ADC (contagens)
0 *39,301,01208
10 *22,991,52310
2013,952,09428
308,752,67546
405,653,19654
503,753,64745
602,553,98816
70 *1,774,25870
80 *1,264,44909
90 *0,914,58939
100 *0,674,69960
Tabela 1: Resistência do NTC, tensão no divisor e leitura do ADC para R1 = 10 kΩ, calculadas pelo modelo ajustado. (*) Fora da faixa medida (20 °C a 60 °C): valores extrapolados.

Método 2: equação de Steinhart–Hart

Proposta por J. S. Steinhart e S. R. Hart em 1968, a equação relaciona a temperatura absoluta \(T\) (em kelvin) com a resistência \(R\) (em ohms):

\[\frac{1}{T} = A + B \ln R + C \left( \ln R \right)^3\]

\(A\), \(B\) e \(C\) são coeficientes do componente. Atenção: o \(B\) desta equação não é a constante β do datasheet; são grandezas diferentes. Alguns fabricantes publicam \(A\), \(B\) e \(C\); quando não publicam, dá para obtê-los experimentalmente. Para converter de kelvin para graus Celsius, basta subtrair 273,15.

Encontrando A, B e C experimentalmente

Meça a resistência do termistor em três temperaturas conhecidas, bem espaçadas (pelo menos 10 °C entre elas). Nós usamos 60 °C, 40 °C e 20 °C, com um termopar tipo K de multímetro como referência, preso junto ao NTC (Figura 6).

Ponta de prova com o sensor NTC 10k e um termopar tipo K lado a lado
Figura 6: NTC e termopar juntos, para medir temperatura e resistência ao mesmo tempo.

Um procedimento simples: coloque água em um recipiente e mergulhe o conjunto da Figura 6 (proteja os terminais do NTC para não medir a resistência da água). Aqueça um pouco acima de 60 °C, deixe esfriar e anote a resistência quando a temperatura estabilizar em 60 °C. Adicione água fria aos poucos até estabilizar em 40 °C e anote de novo. Repita para 20 °C. Mexa a água antes de cada leitura para homogeneizar a temperatura. Os valores que obtivemos foram:

  • \(T_a = 60\ ^\circ\text{C} = 333{,}15\ \text{K}\) → \(R_a = 2550\ \Omega\)
  • \(T_b = 40\ ^\circ\text{C} = 313{,}15\ \text{K}\) → \(R_b = 5650\ \Omega\)
  • \(T_c = 20\ ^\circ\text{C} = 293{,}15\ \text{K}\) → \(R_c = 13950\ \Omega\)

Aplicando a equação aos três pontos, obtemos um sistema linear em \(A\), \(B\) e \(C\), cuja solução, para \(i \in \{a, b, c\}\), é:

\[\begin{aligned} L_i &= \ln R_i, \qquad Y_i = \frac{1}{T_i} \\ \gamma_b &= \frac{Y_b – Y_a}{L_b – L_a}, \qquad \gamma_c = \frac{Y_c – Y_a}{L_c – L_a} \\ C &= \frac{\gamma_c – \gamma_b}{L_c – L_b} \left( L_a + L_b + L_c \right)^{-1} \\ B &= \gamma_b – C \left( L_a^2 + L_a L_b + L_b^2 \right) \\ A &= Y_a – L_a \left( B + C L_a^2 \right) \end{aligned}\]

Com os nossos dados (Tabela 2):

PontoT (K)R (Ω)L = ln RY = 1/T (×10−3 K−1)
a333,1525507,843853,001651
b313,1556508,639413,193358
c293,15139509,543233,411223
Tabela 2: Pontos de calibração e grandezas auxiliares.

\[\begin{aligned} \gamma_b &= 2{,}409704 \times 10^{-4} \\ \gamma_c &= 2{,}410117 \times 10^{-4} \end{aligned}\]

\[\boxed{\begin{aligned} A &= 1{,}11348 \times 10^{-3} \\ B &= 2{,}40612 \times 10^{-4} \\ C &= 1{,}7591 \times 10^{-9} \end{aligned}}\]

Cuidado com o arredondamento. \(\gamma_b\) e \(\gamma_c\) diferem só na quinta casa significativa, e o coeficiente \(C\) sai justamente dessa diferença. Arredondar \(Y_a\) para 0,003, por exemplo, faz \(C\) mudar de sinal e ficar cerca de 25 vezes maior em módulo. Faça a conta em planilha ou com pelo menos 7 algarismos significativos. Pelo mesmo motivo, \(C\) é muito sensível a erros de medição (um erro de apenas 0,1 °C no ponto de 40 °C multiplica \(C\) por cerca de 30). Com apenas três pontos a curva passa exatamente por eles, e a qualidade do ajuste só pode ser avaliada com um quarto ponto de verificação.

Método 3: equação do fator Beta

O modelo Beta é a equação de Steinhart–Hart sem o termo cúbico, escrita em relação a um ponto de referência \((T_0, R_0)\), normalmente 25 °C:

\[\frac{1}{T} = \frac{1}{T_0} + \frac{1}{\beta} \ln\!\left( \frac{R}{R_0} \right)\]

ou, isolando a temperatura:

\[T = \frac{1}{\dfrac{1}{T_0} + \dfrac{1}{\beta} \ln\!\left( \dfrac{R}{R_0} \right)}\]

As temperaturas estão em kelvin (25 °C = 298,15 K). \(R_0\) é a resistência à temperatura \(T_0\) e \(\beta\) vem do datasheet ou de duas medições:

\[\begin{aligned} \beta &= \frac{\ln\left( R_c / R_a \right)}{\dfrac{1}{T_c} – \dfrac{1}{T_a}} \\[4pt] &= \frac{\ln\left( 13950 / 2550 \right)}{\dfrac{1}{293{,}15} – \dfrac{1}{333{,}15}} \approx 4149\ \text{K} \end{aligned}\]

Um detalhe importante: o nosso NTC, vendido como “10 kΩ”, tem cerca de 11,0 kΩ a 25 °C segundo o modelo ajustado (cerca de 10 % acima do nominal). Usar \(R_0 = 10\ \text{k}\Omega\) nominal em vez do valor real desloca a leitura de 2 °C a 2,5 °C para baixo nessa faixa. Com \(R_0\) e \(\beta\) calibrados, os métodos Beta e Steinhart–Hart concordam em menos de 0,01 °C entre 20 °C e 60 °C. Nesse intervalo, para esse sensor, calibrar o componente importa mais do que escolher o modelo. O termo cúbico de Steinhart–Hart passa a fazer diferença em faixas de temperatura mais largas.

Montando o termômetro com NTC e Arduino

Usaremos um NTC, que é o tipo mais fácil de encontrar. Com um PTC o circuito é o mesmo; muda apenas o modelo de conversão no código. Você vai precisar de:

  • Arduino Uno
  • NTC de 10 kΩ
  • Resistor de 10 kΩ
  • Protoboard
  • Jumpers

Monte o circuito conforme a Figura 7, com a placa desligada. O componente de corpo transparente é o NTC: no Tinkercad não há um modelo de termistor com o formato real.

Montagem no Tinkercad: Arduino Uno, resistor e sensor na protoboard, ligados a 5 V, GND e A0
Figura 7: Montagem do circuito na protoboard (Tinkercad).

A Figura 8 mostra a montagem real.

Foto da montagem real: Arduino Uno, resistor e NTC de gota preta na protoboard
Figura 8: Montagem final na protoboard.

Código

O código abaixo lê o ADC várias vezes e tira a média para reduzir o ruído. Em seguida calcula a resistência do NTC e mostra a temperatura pelos dois métodos lado a lado, no Monitor Serial a 115200 bps. Os coeficientes são os do nosso NTC: para o seu, refaça a calibração ou use os valores do datasheet.

/*
 * Termometro com NTC 10 k e Arduino Uno
 *
 * Circuito: NTC entre +5 V e A0; R1 = 10 k entre A0 e GND.
 * O sketch converte a leitura do ADC em resistencia do NTC e calcula a
 * temperatura por dois metodos, lado a lado:
 *   - equacao de Steinhart-Hart (coeficientes A, B, C);
 *   - equacao do fator Beta (B25, R25).
 *
 * Os coeficientes abaixo foram obtidos a partir das medicoes do artigo
 * (60 C / 2550 ohm, 40 C / 5650 ohm, 20 C / 13950 ohm). Para o seu NTC,
 * refaca a calibracao ou use os valores do datasheet.
 *
 * Autores: Diego J. Stefanello e Ricardo B. Morim
 * Versao: 2.0 (revisada)
 */

#include <math.h>

/* ---------- Hardware ---------- */
const uint8_t  PIN_NTC        = A0;
const float    R1_OHM         = 10000.0f;   /* resistor fixo do divisor (lado do GND) */
const float    ADC_FULL_SCALE = 1024.0f;    /* ATmega328P: ADC = Vin * 1024 / Vref */
const uint8_t  N_SAMPLES      = 16;         /* leituras somadas para reduzir ruido */

/* ---------- Steinhart-Hart: 1/T = A + B ln(R) + C ln(R)^3 ---------- */
const float    SH_A           = 1.113481e-3f;
const float    SH_B           = 2.406116e-4f;
const float    SH_C           = 1.759095e-9f;

/* ---------- Fator Beta: 1/T = 1/T0 + (1/Beta) ln(R/R0) ---------- */
const float    BETA_K         = 4149.0f;    /* calculado das medicoes; datasheet: use o B25/85 */
const float    R0_OHM         = 11003.0f;   /* resistencia medida a 25 C; nominal seria 10000 */
const float    T0_K           = 298.15f;    /* 25 C */

const float    KELVIN_OFFSET  = 273.15f;

/* Retorna a media das leituras do ADC, centrada no degrau (+0,5 LSB). */
float readAdcMean(void)
{
	uint16_t sum = 0;    /* 16 x 1023 = 16368 cabe em 16 bits */
	uint8_t  i;

	for (i = 0; i < N_SAMPLES; i++)
	{
		sum += (uint16_t)analogRead(PIN_NTC);
	}
	/* o codigo k representa a faixa [k, k+1) LSB: o centro e k + 0,5 */
	return (float)sum / (float)N_SAMPLES + 0.5f;
}

/* Resistencia do NTC a partir da leitura do ADC (divisor ratiometrico). */
float ntcResistance(float adc)
{
	return R1_OHM * (ADC_FULL_SCALE / adc - 1.0f);
}

/* Temperatura em C pela equacao de Steinhart-Hart. */
float tempSteinhartHart(float rNtc)
{
	float lnR = log(rNtc);

	return 1.0f / (SH_A + SH_B * lnR + SH_C * lnR * lnR * lnR) - KELVIN_OFFSET;
}

/* Temperatura em C pela equacao do fator Beta. */
float tempBeta(float rNtc)
{
	float invT = 1.0f / T0_K + log(rNtc / R0_OHM) / BETA_K;

	return 1.0f / invT - KELVIN_OFFSET;
}

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

void loop()
{
	float adc = readAdcMean();

	/* Protecao: 0 indica NTC aberto; valores no topo indicam NTC em curto. */
	if ((adc < 1.0f) || (adc > 1023.0f))
	{
		Serial.println(F("Erro: leitura fora da faixa (verifique o NTC)"));
		delay(1000);
		return;
	}

	float rNtc = ntcResistance(adc);

	Serial.print(F("ADC: "));
	Serial.print(adc, 1);
	Serial.print(F("  R: "));
	Serial.print(rNtc, 0);
	Serial.print(F(" ohm  S-H: "));
	Serial.print(tempSteinhartHart(rNtc), 1);
	Serial.print(F(" C  Beta: "));
	Serial.print(tempBeta(rNtc), 1);
	Serial.println(F(" C"));

	delay(1000);
}

Alguns detalhes de implementação:

  • A leitura média recebe +0,5 porque o código \(k\) do ADC representa a faixa de tensão entre \(k\) e \(k+1\) LSB; somar meio LSB elimina o viés de truncamento.
  • Leituras nos extremos (0 ou 1023) indicam NTC aberto ou em curto e geram mensagem de erro em vez de uma divisão por zero.
  • No Uno, double e float são ambos de 32 bits; a precisão é suficiente para esses cálculos.

No Monitor Serial você verá a temperatura medida a cada segundo. A Figura 9 mostra a saída da primeira versão deste projeto, que exibia apenas a parte inteira da temperatura.

Monitor Serial do Arduino mostrando linhas 'Temperatura: 24°C' a 31°C
Figura 9: Saída no Monitor Serial (versão original do código).

Limitações e boas práticas

  • Autoaquecimento: com R1 = 10 kΩ e 5 V, o NTC dissipa cerca de 0,6 mW a 25 °C. Com uma constante de dissipação típica de alguns mW/°C para NTCs pequenos em ar parado (confira o datasheet), isso representa alguns décimos de grau de erro.
  • Resolução não é exatidão: em torno de 25 °C cada contagem do ADC equivale a cerca de 0,08 °C (0,3 °C perto de 80 °C), mas a exatidão é limitada pela tolerância de R1, pela calibração e pela referência usada. Um termopar de multímetro tem tipicamente exatidão de ±1 °C a ±3 °C, e a calibração herda esse erro.
  • Faixa de validade: coeficientes obtidos entre 20 °C e 60 °C não devem ser usados muito fora dessa faixa sem um ponto de verificação.
  • Escolha de R1: a sensibilidade é maior quando R1 é próximo da resistência do NTC no meio da faixa de interesse; 10 kΩ é uma boa escolha para medir em torno da temperatura ambiente.
  • Ruído: com cabos longos, um capacitor de 100 nF entre a entrada analógica e o GND ajuda a estabilizar a leitura.

Conclusão

Mostramos como ler um termistor com o Arduino usando um divisor resistivo e três formas de converter resistência em temperatura: tabela, Steinhart–Hart e fator Beta. Para este NTC, na faixa de 20 °C a 60 °C, os dois modelos se equivalem desde que o componente seja calibrado. A maior fonte de erro está nos parâmetros (R0, β), não na escolha do modelo.

Teste os dois métodos no seu circuito e compartilhe os resultados nos comentários. Se tiver alguma dificuldade, deixe sua dúvida que teremos prazer em ajudar!

Compartilhe

Facebook
WhatsApp
Email

Posts recentes

Nem toda inovação começa dentro de uma fábrica. Muitas tecnologias

Leia mais »