How the Thermistor Sensor NTC Actually Works
A Negative Temperature Coefficient (NTC) thermistor is a passive, solid-state resistor whose electrical resistance decreases predictably as its temperature rises. Unlike active digital sensors (like the DS18B20) that output pre-calculated data over I2C or 1-Wire, a raw thermistor sensor NTC outputs only resistance. To interface it with a microcontroller's analog-to-digital converter (ADC), you must force a current through it using a voltage divider circuit, converting the changing resistance into a measurable analog voltage.
Because the resistance-to-temperature curve is highly non-linear (exponential rather than a straight line), you cannot simply map the ADC reading to a temperature using a basic linear scale. Instead, you must apply logarithmic scaling—typically the Beta parameter equation for rough estimates, or the Steinhart-Hart equation for precision work. The physical output of your circuit is strictly an analog DC voltage between 0V and your supply rail (usually 3.3V or 5V), which the microcontroller samples and mathematically linearizes in firmware.
Hardware Specs, Pinout, and Resistance Data
Most hobbyist and industrial applications use a 10K NTC thermistor with a Beta (β) value of 3950. While you can buy pre-built modules with onboard comparators and pull-up resistors, wiring a bare glass-encapsulated or epoxy-coated NTC is cheaper, more reliable, and avoids the module's proprietary resistor tolerances. Below is the standard wiring configuration for a bare component.
| Connection Point | Wiring Target | Notes & Supply Range |
|---|---|---|
| Thermistor Lead 1 | Microcontroller ADC Pin (e.g., GPIO 34) | Connect a 100nF ceramic capacitor between this pin and GND to filter EMI. |
| Thermistor Lead 1 | 10K Pull-Up Resistor | The other end of this resistor goes to VCC (3.3V or 5V). Use a 1% tolerance metal film resistor. |
| Thermistor Lead 2 | System Ground (GND) | Keep the ground path shared with the microcontroller's analog ground to prevent offset errors. |
Because the NTC curve is exponential, knowing the exact resistance at specific temperature milestones is critical for validating your hardware. The table below shows the theoretical resistance for a standard 10K 3950 Beta thermistor across its common operating range. You can use your multimeter in an ice bath (0°C) or boiling water (100°C, adjusted for altitude) to verify your specific component against these benchmarks.
| Temperature (°C) | Temperature (°F) | Resistance (kΩ) | Expected ADC Voltage (3.3V VCC, 10K Pull-Up) |
|---|---|---|---|
| -20°C | -4°F | 67.81 kΩ | 2.87 V |
| 0°C | 32°F | 27.28 kΩ | 2.42 V |
| 25°C | 77°F | 10.00 kΩ | 1.65 V |
| 50°C | 122°F | 3.60 kΩ | 0.89 V |
| 85°C | 185°F | 1.20 kΩ | 0.35 V |
| 100°C | 212°F | 0.75 kΩ | 0.23 V |
The Math: Raw ADC to Celsius (Steinhart-Hart)
Converting the raw ADC reading into a physical temperature unit requires two mathematical steps: extracting the thermistor's resistance from the voltage divider, and applying the Steinhart-Hart equation. According to Ametherm's thermistor engineering guides, the Steinhart-Hart equation provides accuracy within ±0.1°C across a wide range, vastly outperforming the simpler Beta parameter equation which drifts heavily outside the 25°C to 50°C window.
Step 1: Voltage Divider Math
With a 10K pull-up resistor to VCC and the NTC to GND, the voltage at the ADC pin ($V_{adc}$) is:
$$V_{adc} = V_{cc} \times \frac{R_{ntc}}{R_{pullup} + R_{ntc}}$$
Rearranging to solve for the thermistor resistance ($R_{ntc}$):
$$R_{ntc} = R_{pullup} \times \frac{V_{adc}}{V_{cc} - V_{adc}}$$
If using a 12-bit ADC (like the ESP32, where max reading is 4095), you can substitute the voltage ratio directly with the ADC counts:
$$R_{ntc} = 10000 \times \frac{ADC_{raw}}{4095 - ADC_{raw}}$$
Step 2: Steinhart-Hart Equation
Once you have $R_{ntc}$ in ohms, apply the Steinhart-Hart formula to find Temperature ($T$) in Kelvin:
$$\frac{1}{T} = A + B \ln(R_{ntc}) + C (\ln(R_{ntc}))^3$$
For a standard 10K 3950 NTC, the coefficients are approximately:
A = 1.127645142e-3
B = 2.342827094e-4
C = 0.877546832e-7
Below is the complete, compilable C++ code for the Arduino IDE (tested on ESP32 DevKit v1 and Arduino Uno). It includes an oversampling loop to mitigate ADC noise, which is especially critical on the ESP32.
#include <math.h>
// Hardware pins
const int THERMISTOR_PIN = 34; // ESP32 ADC1 pin (GPIO 34)
const float PULLUP_RES = 10000.0; // 10K pull-up resistor
const float ADC_MAX = 4095.0; // 12-bit ADC for ESP32 (use 1023.0 for Arduino Uno)
// Steinhart-Hart coefficients for 10K 3950 NTC
const float A = 1.127645142e-3;
const float B = 2.342827094e-4;
const float C = 0.877546832e-7;
float readThermistorCelsius() {
// 1. Oversample to reduce noise (read 32 times and average)
long sum = 0;
for (int i = 0; i < 32; i++) {
sum += analogRead(THERMISTOR_PIN);
delayMicroseconds(500); // Allow ADC sample-and-hold cap to settle
}
float adc_avg = sum / 32.0;
// Prevent division by zero if thermistor is disconnected or shorted
if (adc_avg >= ADC_MAX - 1) return -999.0;
if (adc_avg <= 1) return 999.0;
// 2. Calculate Resistance
float r_ntc = PULLUP_RES * (adc_avg / (ADC_MAX - adc_avg));
// 3. Steinhart-Hart Math
float ln_r = log(r_ntc);
float temp_k = 1.0 / (A + (B * ln_r) + (C * pow(ln_r, 3)));
// 4. Convert Kelvin to Celsius
return temp_k - 273.15;
}
void setup() {
Serial.begin(115200);
analogReadResolution(12); // Explicitly set 12-bit for ESP32
}
void loop() {
float tempC = readThermistorCelsius();
Serial.print("Temperature: ");
Serial.print(tempC, 2);
Serial.println(" °C");
delay(1000);
}
Interference, Self-Heating, and Calibration Pitfalls
Getting the math right is only half the battle. In real-world embedded deployments, environmental and electrical factors will corrupt your readings if left unaddressed. Here are the primary interference sources and how to engineer around them.
1. Self-Heating Errors
Because a thermistor is a resistor, passing current through it generates heat ($P = I^2R$). If your pull-up resistor is too small (e.g., 1K), the current will physically heat the thermistor bead, causing it to read 1°C to 3°C higher than ambient. By using a 10K or 47K pull-up on a 3.3V rail, you limit the current to roughly 165µA or 68µA respectively, keeping self-heating well below 0.1°C in still air. For battery-powered IoT nodes, drive the pull-up resistor from a GPIO pin and only set the GPIO HIGH for 50ms before taking a reading, dropping average power consumption to near zero.
2. EMI and Long Wire Runs
NTC thermistors have high impedance, especially at cold temperatures (e.g., 67kΩ at -20°C). High-impedance analog lines act as antennas for electromagnetic interference from switching power supplies, relays, and AC mains. If your sensor is more than 12 inches from the microcontroller, use twisted-pair wire. More importantly, solder a 100nF ceramic capacitor directly across the ADC pin and GND at the microcontroller end. This forms a low-pass RC filter that shorts high-frequency noise to ground before the ADC samples it.
The ESP32's internal ADC is notoriously non-linear near the supply rails (below 0.15V and above 2.6V on a 3.3V VCC). As seen in the Espressif ADC calibration documentation, raw readings in these zones will skew your temperature calculations by several degrees. If you are measuring extreme temperatures (like a freezer at -20°C where Vout is 2.87V), you must either use an external I2C ADC like the ADS1115, or apply Espressif's
esp_adc_cal library in your firmware to correct the curve.
3. Calibration and Scaling Drift
Out-of-the-box 10K 3950 thermistors typically carry a ±1% to ±2% tolerance, which translates to roughly ±0.5°C at room temperature. If your application requires higher precision, you must perform a two-point calibration. Submerge the sealed sensor in a stirred ice-water bath (exactly 0.0°C) and record the raw ADC average. Then, place it in a controlled environment alongside a NIST-traceable digital thermometer. Adjust the Steinhart-Hart 'A' coefficient in your code slightly until the serial output matches your reference thermometer. For a deeper dive into component tolerances and linearization networks, All About Circuits provides excellent foundational theory on thermistor network design.






