An NTC thermistor is the cheapest temperature sensor there is — a 10 kΩ bead, often sold in a stainless waterproof probe for water tanks, aquariums and 3D printers. Its resistance falls as it warms up.
On the ESP32 DevKit V1 it forms a divider with a 10 kΩ fixed resistor: thermistor from 3V3 to D33, resistor from D33 to GND. The sketch averages 32 calibrated millivolt readings, works out the thermistor’s resistance, and converts it to °C with the Beta equation.
Wiring
| ESP32 DevKit V1 | 10 kΩ NTC thermistor (bead or waterproof probe) | Wire | Notes |
|---|---|---|---|
| 3V3 | WIRE 1 | red | Top of the divider. Same rail as the ADC reference, never VIN. |
| D33 | WIRE 2 | yellow | ADC1 — keeps reading with Wi-Fi on. |
| GND | WIRE 2 | black | Via 10 kΩ — 10 kΩ fixed resistor from D33 to GND (the bottom of the divider). Use a 1 % metal-film resistor. |
Passive — used in a divider from the board’s 3.3 V or 5 V part, 3.3 V board. Power the divider from the same voltage as your ADC reference: 3.3 V on ESP32 and Pico, 5 V on Uno. Then the divider output can never exceed the pin limit.
Board quirks
- The divider makes 1.65 V at 25 °C — right in the middle of the ESP32 ADC’s good range. Near 0 °C (about 0.8 V) and above about 80 °C (about 2.9 V) accuracy drops, because the ADC flattens below 0.15 V and above 3.1 V and the Beta equation is only an approximation.
analogReadMilliVolts()(core 3.x) corrects each chip’s ADC with its factory calibration. RawanalogRead()counts can be off by tens of millivolts — several degrees for a thermistor.- The formula needs the real supply voltage. Measure your board’s 3V3 pin with a multimeter and put it in
VCC_MV; measure the fixed resistor too. - D33 is on ADC1. A temperature logger usually sends data over Wi-Fi, and ADC2 pins (D4, D12–D15, D25–D27) return nothing once Wi-Fi starts.
- Check the Beta value in the listing — waterproof probes from Indian sellers are usually B3950, some are B3435. A wrong Beta is off by a degree or two away from 25 °C. Calibrate in ice water (0 °C) if you need better.
Code
// 10 kΩ NTC thermistor (B = 3950) on an ESP32 DevKit V1.
// WIRE 1 → 3V3, WIRE 2 → D33 (GPIO33, ADC1), and a 10 kΩ fixed resistor from D33 to GND.
// Temperature from the Beta equation: 1/T = 1/T25_K + ln(R/R25)/B.
#include <math.h>
constexpr uint8_t NTC_PIN = 33; // ADC1_CH5: works with Wi-Fi on
constexpr float VCC_MV = 3300.0f; // the divider's supply (measure your 3V3 pin for best accuracy)
constexpr float R_FIXED = 10000.0f; // the 10 kΩ to GND — measure it with a multimeter
constexpr float R25 = 10000.0f; // NTC resistance at 25 °C
constexpr float BETA = 3950.0f; // from the seller's listing (3950 or 3435 are common)
constexpr float T25_K = 298.15f; // 25 °C in kelvin
void setup() {
Serial.begin(115200);
Serial.println("NTC 10k on GPIO33 — Beta 3950");
}
void loop() {
uint32_t sum = 0;
for (int i = 0; i < 32; i++) sum += analogReadMilliVolts(NTC_PIN);
float v = sum / 32.0f; // mV across the fixed resistor
if (v < 50 || v > VCC_MV - 50) {
Serial.printf("Out of range (%.0f mV) — open or shorted thermistor?\n", v);
delay(2000);
return;
}
float rNtc = R_FIXED * (VCC_MV - v) / v; // NTC is the top half of the divider
float tK = 1.0f / (1.0f / T25_K + logf(rNtc / R25) / BETA);
Serial.printf("V %.0f mV R_ntc %.0f Ω Temp %.1f °C\n", v, rNtc, tK - 273.15f);
delay(2000);
}// 10 kΩ NTC thermistor (B = 3950) on an ESP32 DevKit V1.
// WIRE 1 → 3V3, WIRE 2 → D33 (GPIO33, ADC1), and a 10 kΩ fixed resistor from D33 to GND.
// Temperature from the Beta equation: 1/T = 1/T25_K + ln(R/R25)/B.
#include <math.h>
constexpr uint8_t NTC_PIN = 33; // ADC1_CH5: works with Wi-Fi on
constexpr float VCC_MV = 3300.0f; // the divider's supply (measure your 3V3 pin for best accuracy)
constexpr float R_FIXED = 10000.0f; // the 10 kΩ to GND — measure it with a multimeter
constexpr float R25 = 10000.0f; // NTC resistance at 25 °C
constexpr float BETA = 3950.0f; // from the seller's listing (3950 or 3435 are common)
constexpr float T25_K = 298.15f; // 25 °C in kelvin
void setup() {
Serial.begin(115200);
Serial.println("NTC 10k on GPIO33 — Beta 3950");
}
void loop() {
uint32_t sum = 0;
for (int i = 0; i < 32; i++) sum += analogReadMilliVolts(NTC_PIN);
float v = sum / 32.0f; // mV across the fixed resistor
if (v < 50 || v > VCC_MV - 50) {
Serial.printf("Out of range (%.0f mV) — open or shorted thermistor?\n", v);
delay(2000);
return;
}
float rNtc = R_FIXED * (VCC_MV - v) / v; // NTC is the top half of the divider
float tK = 1.0f / (1.0f / T25_K + logf(rNtc / R25) / BETA);
Serial.printf("V %.0f mV R_ntc %.0f Ω Temp %.1f °C\n", v, rNtc, tK - 273.15f);
delay(2000);
}Expected serial output
NTC 10k on GPIO33 — Beta 3950
V 1650 mV R_ntc 10000 Ω Temp 25.0 °C
V 1820 mV R_ntc 8132 Ω Temp 29.7 °C
V 1999 mV R_ntc 6508 Ω Temp 35.0 °CNTC 10k on GPIO33 — Beta 3950 V 1650 mV R_ntc 10000 Ω Temp 25.0 °C V 1820 mV R_ntc 8132 Ω Temp 29.7 °C V 1999 mV R_ntc 6508 Ω Temp 35.0 °C
Common errors
Temperature goes down when the thermistor warms up
The divider is the other way round (thermistor to GND, resistor to 3V3). Swap the two parts, or change the formula to R_FIXED * v / (VCC_MV - v).
“Out of range — open or shorted thermistor?”
D33 sees almost 0 V (thermistor not connected) or almost 3.3 V (the 10 kΩ to GND is missing). Check both joints of the probe cable.
Reads 2–3 °C high next to the board
Self-heating is tiny at 0.33 mA, so this is usually heat from the ESP32 module. Put the probe at the end of its cable, away from the board.