If you need to measure temperature between -40°C and 105°C with an accuracy of ±1°C, the NTC 10K 3950 thermistor paired with an Arduino Uno R3 is the most cost-effective and reliable choice. You will wire it in a voltage divider configuration with a 10K 1% tolerance fixed resistor, read the analog voltage on pin A0, and convert the ADC value to Celsius using the Steinhart-Hart (Beta parameter) equation.
The Verdict: Which Arduino Thermistor to Choose
Not all thermistors are created equal. The right pick depends entirely on your temperature range and required precision. Use this decision tree to select the correct sensor for your embedded project.
| Sensor Type | Best For | Temperature Range | Decision Rule |
|---|---|---|---|
| NTC 10K 3950 (Epoxy) | General purpose, 3D printers, ambient air, liquid baths | -40°C to +105°C | Default Pick. Choose this for 90% of hobbyist and maker projects. Cheap, robust, and easy to solder. |
| NTC 100K 3950 (Glass Bead) | High-temperature environments, 3D printer hotends | -40°C to +300°C | Choose this only if your target exceeds 105°C. Requires a 100K pull-up resistor instead of 10K. |
| PT1000 (RTD) | Industrial precision, laboratory equipment | -200°C to +850°C | Choose this if you need ±0.1°C accuracy. Requires a dedicated amplifier like the MAX31865; cannot be wired directly to an Arduino analog pin. |
Final Recommendation: For standard environmental monitoring, HVAC control, or basic weather stations, buy a pack of NTC 10K 3950 epoxy-coated thermistors. They cost roughly $0.20 each and interface directly with the Arduino's 10-bit ADC without extra silicon.
Parts List and Pin Mapping
To achieve the ±1°C accuracy promised by the datasheet, you cannot use just any resistor for the voltage divider. The fixed resistor must be high precision.
Required Components
- Microcontroller: Arduino Uno R3 (ATmega328P) or Arduino Nano v3. (Code targets 5V logic boards with 10-bit ADC).
- Sensor: NTC 10K Thermistor, B-value 3950 (Epoxy coated).
- Fixed Resistor: 10K Ohm, 1% tolerance, metal film. (Using a standard 5% carbon film resistor will introduce a baseline error of up to 3°C).
- Hardware: Half-size breadboard, male-to-male jumper wires.
Pin Mapping Table
| Component | Pin / Lead | Arduino Uno R3 Pin | Function |
|---|---|---|---|
| Fixed 10K Resistor | Lead 1 | 5V | Voltage Reference (VCC) |
| Fixed 10K Resistor | Lead 2 | A0 (Analog In) | Voltage Divider Midpoint |
| NTC Thermistor | Lead 1 | A0 (Analog In) | Voltage Divider Midpoint |
| NTC Thermistor | Lead 2 | GND | Circuit Ground |
Step-by-Step Voltage Divider Wiring
The Arduino cannot read resistance directly; it reads voltage. We use a voltage divider to convert the thermistor's changing resistance into a changing voltage.
- Insert the fixed 10K resistor into the breadboard. Connect one leg to the Arduino's 5V pin.
- Connect the midpoint. Connect the other leg of the fixed resistor to Arduino pin A0. This is your signal wire.
- Insert the NTC thermistor. Connect one lead of the thermistor to the same A0 midpoint row on the breadboard.
- Ground the circuit. Connect the second lead of the thermistor to the Arduino's GND pin.
- Verify the topology. You should have VCC (5V) dropping across the fixed resistor, then across the thermistor to GND. Pin A0 sits exactly between them.
Complete Compilable Steinhart-Hart Code
The following C++ code is written for the Arduino IDE. It uses the Beta parameter equation (a simplified Steinhart-Hart equation) optimized for the 3950 B-coefficient. It includes critical bounds-checking to prevent math domain errors that crash the serial output.
#include <math.h>
// --- PIN DEFINITIONS ---
#define THERMISTOR_PIN A0
// --- THERMISTOR SPECIFICATIONS (NTC 10K 3950) ---
#define NOMINAL_RESISTANCE 10000.0 // Resistance at 25 degrees C (in Ohms)
#define NOMINAL_TEMPERATURE 25.0 // Nominal temperature (in Celsius)
#define B_COEFFICIENT 3950.0 // B-value from datasheet
#define SERIES_RESISTOR 10000.0 // Value of the fixed pull-up resistor
// --- ADC SPECIFICATIONS ---
#define ADC_MAX 1023.0
void setup() {
Serial.begin(115200);
while (!Serial) {
; // Wait for serial port to connect (needed for native USB boards)
}
Serial.println("Arduino Thermistor NTC 10K 3950 Initialized.");
// Set analog reference to default (5V on Uno R3)
analogReference(DEFAULT);
}
void loop() {
// Read the raw ADC value (0 to 1023)
int rawAdc = analogRead(THERMISTOR_PIN);
// --- ERROR HANDLING: Prevent Math Domain Errors ---
// If ADC is 0, the thermistor is shorted or wired to GND directly.
// If ADC is 1023, the thermistor is disconnected (open circuit).
if (rawAdc <= 1 || rawAdc >= ADC_MAX - 1) {
Serial.print("ERROR: ADC out of bounds. Raw value: ");
Serial.println(rawAdc);
Serial.println("Check for open circuit (disconnected) or short circuit.");
delay(2000);
return; // Skip calculation to prevent log(0) or divide-by-zero
}
// Convert ADC value to resistance
// Formula: R_therm = R_series * (ADC / (1023 - ADC))
float resistance = SERIES_RESISTOR * ((float)rawAdc / (ADC_MAX - (float)rawAdc));
// Steinhart-Hart (Beta Parameter) Equation
// 1/T = 1/T0 + (1/B) * ln(R/R0)
float steinhart;
steinhart = resistance / NOMINAL_RESISTANCE; // (R/R0)
steinhart = log(steinhart); // ln(R/R0)
steinhart /= B_COEFFICIENT; // (1/B) * ln(R/R0)
steinhart += 1.0 / (NOMINAL_TEMPERATURE + 273.15); // + (1/T0)
steinhart = 1.0 / steinhart; // Invert to get T in Kelvin
steinhart -= 273.15; // Convert Kelvin to Celsius
// Output results
Serial.print("ADC: ");
Serial.print(rawAdc);
Serial.print(" | Resistance: ");
Serial.print(resistance, 1);
Serial.print(" Ohms | Temperature: ");
Serial.print(steinhart, 2);
Serial.println(" C");
delay(1000); // Read once per second
}
Debugging: First Three Things to Check When It Fails
When working with analog sensors, the Serial Monitor will often output garbage data or static values if the physical layer is flawed. If your build fails, follow this ranked troubleshooting path.
1. Serial Monitor Prints nan, inf, or ERROR: ADC out of bounds
The Cause: The Arduino is reading an ADC value of exactly 0 or 1023. This triggers a log(0) or division-by-zero in the Steinhart-Hart math, resulting in nan (Not a Number). Physically, this means the voltage divider is broken.
The Fix:
- If ADC is 1023: The thermistor is disconnected. Check the GND wire and ensure the thermistor leads are fully seated in the breadboard.
- If ADC is 0: The A0 pin is shorted to GND, or the fixed 10K resistor is missing/disconnected from the 5V rail.
2. Temperature Reads Exactly 25.00°C (or a static, incorrect number)
The Cause: The math is executing, but the coefficients are wrong, or you are using a 3.3V board (like an Arduino Due or ESP32) while the code assumes a 5V reference, skewing the resistance calculation. Alternatively, you bought a 10K 3380 B-value thermistor but the code uses 3950.
The Fix: Verify the B-coefficient printed on your supplier's datasheet. If using a 3.3V board, change analogReference(DEFAULT) to match your board's logic level, or power the voltage divider from the 3.3V pin instead of 5V so the ratio remains accurate regardless of VCC fluctuations.
3. Readings Fluctuate Wildly (Jumping 2°C to 4°C per second)
The Cause: High-impedance analog circuits act as antennas. You are picking up 50Hz/60Hz electromagnetic interference (EMI) from nearby mains wiring, or your breadboard contacts have variable resistance.
The Fix: Solder the thermistor directly to a perfboard rather than using a breadboard for long-term deployment. For immediate software mitigation, implement oversampling (see below).
Extending or Simplifying the Build
Depending on your project timeline and precision requirements, you can alter this baseline design.
How to Simplify: Use a Pre-Built Module
If you do not want to source 1% resistors and manage breadboard wiring, purchase a KY-013 Temperature Sensor Module. It costs about $1.50 and features the NTC 10K thermistor and a fixed 10K SMD resistor already wired in a voltage divider on a small PCB. It maps directly to the exact same code provided above; just wire its VCC, GND, and Signal pins to your microcontroller.
How to Extend: Hardware Filtering and Software Oversampling
To achieve laboratory-grade stability and eliminate the wild fluctuations mentioned in the debugging section, apply these two upgrades:
- Hardware (Low-Pass Filter): Solder a 0.1µF (100nF) ceramic capacitor directly across the thermistor leads (between A0 and GND). This creates an RC low-pass filter that shorts high-frequency EMI noise to ground before it reaches the ADC.
- Software (Oversampling): The Arduino's 10-bit ADC has inherent quantization noise. Replace the single
analogRead()in the code with a loop that takes 16 rapid readings, sums them, and divides by 16. This mathematically increases your effective resolution from 10-bit to 12-bit, smoothing out micro-fluctuations without adding hardware delay.
For deeper mathematical context on the Steinhart-Hart equation and thermistor physics, refer to the Adafruit Thermistor Tutorial. For official documentation on the Arduino ADC behavior and reference voltages, consult the Arduino analogRead() Reference.






