An NTC sensor (Negative Temperature Coefficient thermistor) does not output a voltage or a digital signal on its own; it is a variable resistor. To interface a raw NTC sensor with a microcontroller like the ESP32, you must build a voltage divider circuit to convert its resistance changes into an analog voltage that the onboard ADC (Analog-to-Digital Converter) can read. This guide provides the exact wiring, the raw-to-unit mathematical scaling, and the hardware workarounds required to get accurate temperature readings without falling victim to the ESP32's notorious ADC non-linearity.

The NTC Sensing Principle and Output Signal

An NTC sensor relies on sintered semiconductor ceramics (typically manganese, nickel, and cobalt oxides). At low temperatures, the electrons in the ceramic matrix are tightly bound, resulting in high electrical resistance. As thermal energy increases, more charge carriers are freed into the conduction band, causing the resistance to drop exponentially. This non-linear relationship means a 10kΩ NTC sensor does not drop exactly 100Ω per degree; it might drop 2,000Ω between 0°C and 10°C, but only 200Ω between 80°C and 90°C.

Because the output signal of a raw NTC sensor is purely resistive, it requires an external excitation voltage and a fixed series resistor to create a measurable analog voltage output. The microcontroller's ADC reads this voltage, which must then be mathematically inverted back into resistance, and finally scaled into a physical temperature unit (Celsius or Fahrenheit) using thermistor-specific coefficients. If you are using a pre-packaged digital temperature module (like a DS18B20), it handles this internally via 1-Wire or I2C, but for bare NTC components, the analog voltage divider and software scaling are mandatory.

Table 1: Resistance vs. Temperature for a Standard 10kΩ NTC (Beta = 3950)
Temperature (°C) Resistance (Ω) Voltage Output (3.3V VCC, 10kΩ Series R) ESP32 12-bit ADC Raw Value (Approx)
-10°C 42,500 Ω 2.67 V 3315
0°C 27,280 Ω 2.42 V 3005
25°C (Room) 10,000 Ω 1.65 V 2048
50°C 3,602 Ω 0.87 V 1080
85°C 722 Ω 0.22 V 273

Hardware Wiring and Component Selection

To read the NTC sensor, we use a high-side voltage divider configuration. The 3.3V supply connects to a fixed precision resistor, which connects to the ADC pin and the NTC sensor. The other leg of the NTC sensor connects to ground. As the NTC heats up and its resistance drops, the voltage at the ADC pin decreases. We use a 10kΩ fixed series resistor because it perfectly matches the NTC's 10kΩ resistance at 25°C, placing the nominal room-temperature output right at the midpoint of the ESP32's ADC range (1.65V), which is the most linear region of the converter.

Component Selection Tip: Use a 1% tolerance metal film resistor for the series resistor. A standard 5% carbon resistor will introduce up to 1.5°C of error at room temperature before the NTC's own tolerance is even factored in.
Table 2: ESP32 DevKit V1 to NTC Voltage Divider Wiring
ESP32 Pin Function Connection Target Notes / Supply Range
3V3 Power Supply Leg 1 of 10kΩ Series Resistor Must be exactly 3.3V. Do not use 5V, or you will fry the ADC.
GPIO 34 Analog Input (ADC1_CH6) Junction of Series R and NTC ADC1 pins (32-39) are required. ADC2 pins conflict with WiFi.
GND Ground Reference Leg 2 of NTC Sensor Keep ground return path short to avoid noise.

Raw ADC to Temperature: The Math and Code

Converting the raw 12-bit ADC integer into a usable Celsius reading requires a three-step mathematical pipeline. First, we convert the raw ADC value to voltage. Second, we use the voltage divider algebraic inversion to find the NTC's current resistance. Finally, we apply the Beta parameter equation to convert resistance to temperature in Kelvin, and then shift it to Celsius.

Step 1: ADC to Voltage
V_adc = (Raw_ADC / 4095.0) * 3.3

Step 2: Voltage to Resistance
Because the NTC is on the low side (connected to GND), the voltage divider formula is V_adc = 3.3 * (R_ntc / (R_series + R_ntc)).
Inverting this to solve for the NTC resistance yields:
R_ntc = R_series * (V_adc / (3.3 - V_adc))

Step 3: Resistance to Temperature (Beta Equation)
The Beta equation is a simplified version of the Steinhart-Hart equation that uses a single material constant (Beta, usually 3950 for hobbyist glass-bead NTCs).
1 / T_kelvin = (1 / T0) + (1 / Beta) * ln(R_ntc / R0)
Where T0 is 298.15K (25°C in Kelvin) and R0 is 10,000Ω.

// ESP32 NTC Sensor Reading Code (Arduino Core)
const int NTC_PIN = 34;
const float SERIES_RESISTOR = 10000.0;
const float NOMINAL_RESISTANCE = 10000.0;
const float NOMINAL_TEMPERATURE = 25.0; // Celsius
const float B_COEFFICIENT = 3950.0;
const float VCC = 3.3;
const int ADC_MAX = 4095;

void setup() {
  Serial.begin(115200);
  analogReadResolution(12); // Ensure 12-bit resolution
}

void loop() {
  // Read raw ADC and average 16 samples to reduce noise
  long total = 0;
  for(int i=0; i<16; i++) {
    total += analogRead(NTC_PIN);
    delay(2);
  }
  float raw_adc = total / 16.0;

  // Step 1: ADC to Voltage
  float voltage = (raw_adc / ADC_MAX) * VCC;
  
  // Prevent division by zero at extreme cold
  if (voltage >= VCC - 0.01) voltage = VCC - 0.01;

  // Step 2: Voltage to Resistance
  float resistance = SERIES_RESISTOR * (voltage / (VCC - voltage));

  // Step 3: Resistance to Temperature (Beta Equation)
  float steinhart;
  steinhart = resistance / NOMINAL_RESISTANCE;     // (R/Ro)
  steinhart = log(steinhart);                      // ln(R/Ro)
  steinhart /= B_COEFFICIENT;                      // 1/B * ln(R/Ro)
  steinhart += 1.0 / (NOMINAL_TEMPERATURE + 273.15); // + (1/To)
  steinhart = 1.0 / steinhart;                     // Invert
  steinhart -= 273.15;                             // Convert to Celsius

  Serial.print("Temperature: ");
  Serial.print(steinhart);
  Serial.println(" *C");
  
  delay(1000);
}

Interference, Calibration, and ESP32 ADC Quirks

While the math above is theoretically sound, real-world bench testing reveals three major interference sources that will corrupt your NTC sensor readings if left unaddressed.

1. ESP32 ADC Non-Linearity
The internal ADC on the ESP32 is notoriously non-linear at the extremes of its range. According to Espressif's official ADC documentation, readings below 0.15V and above 3.1V are highly inaccurate and should be discarded. Looking back at Table 1, you will see that at 85°C, the voltage drops to 0.22V, dangerously close to the non-linear dead zone. If you need to measure temperatures above 70°C reliably with an ESP32, you must either lower the series resistor value (e.g., to 4.7kΩ) to shift the voltage curve upward, or bypass the internal ADC entirely and use an external I2C ADC like the ADS1115.

2. Self-Heating Errors
When current flows through the NTC sensor, it dissipates power as heat (P = V² / R), artificially raising the temperature of the ceramic bead. A typical 2mm glass bead NTC has a dissipation constant of roughly 1.5 mW/°C. In our 3.3V circuit with a 10kΩ series resistor, the maximum current at 25°C is 0.165mA, dissipating about 0.27mW. This causes a self-heating error of roughly 0.18°C, which is acceptable for most ambient air measurements. However, if you are measuring still air or need high precision, power the voltage divider from a GPIO pin and only drive the pin HIGH for a few milliseconds before taking the reading, keeping the duty cycle low to prevent thermal buildup.

3. Lead Wire Resistance and Calibration
Copper wire has resistance. If you run 22 AWG jumper wires three feet to your NTC sensor, you are adding roughly 0.1Ω per foot. While 0.3Ω seems negligible against 10,000Ω, at higher temperatures where the NTC drops to 700Ω, that lead resistance introduces a measurable skew. For remote sensing, use a 3-wire or 4-wire Kelvin measurement setup, or simply calibrate the NOMINAL_RESISTANCE variable in your code to account for the fixed lead resistance. For ultimate accuracy across a wide temperature span, abandon the single-point Beta equation and calculate the three-coefficient Steinhart-Hart equation using the specific A, B, and C constants provided in your thermistor's factory datasheet.