How the calculator works
The calculator converts between resistance and temperature using the Beta (B-parameter) model — the two-coefficient approximation of the Steinhart-Hart equation found on every NTC datasheet:
1/T = 1/T₀ + (1/B) × ln(R/R₀)
Rearranged to solve for temperature:
T (K) = 1 / [1/T₀ + (1/B) × ln(R/R₀)]
And for resistance at a target temperature:
R = R₀ × exp[B × (1/T − 1/T₀)]
Where:
T— temperature in KelvinT₀= 298.15 K (25 °C) — the reference temperatureR₀— resistance at 25 °C (from datasheet, printed on the component)B— the B-value or beta coefficient in Kelvin (also written β)R— measured resistance
The three operating modes
R → Temperature: You measured resistance with an ohmmeter or a Wheatstone bridge. Enter the reading, get the temperature. Useful during bench characterization or calibration.
Temperature → R: You want to set a temperature threshold in firmware. Enter the trip temperature and the calculator gives you the resistance your comparator or ADC threshold should target.
ADC → Temperature: The most common embedded use case. The NTC is one leg of a resistor voltage divider driven from VCC. The MCU reads the ADC count and the firmware must convert it to Celsius.
Voltage divider math
The standard circuit has a fixed resistor R_fixed in series with the NTC, driven from VCC, with the ADC input at the midpoint.
NTC in lower position (GND side):
V_adc = VCC × R_ntc / (R_fixed + R_ntc)
Solving for R_ntc from ADC count:
R_ntc = R_fixed × (count / max_count) / (1 − count / max_count)
NTC in upper position (VCC side):
V_adc = VCC × R_fixed / (R_ntc + R_fixed)
R_ntc = R_fixed × (1 − count / max_count) / (count / max_count)
NTC in the lower position is more common. As temperature falls, R_ntc rises and V_adc = VCC × R_ntc / (R_fixed + R_ntc) rises with it — cold end gets high ADC counts, preserving resolution where cold-temperature accuracy matters. As temperature rises, R_ntc drops and ADC count falls. NTC in the upper position inverts the relationship: ADC count increases with temperature, which suits firmware that expects a “bigger number = hotter” threshold.
Choosing R_fixed
Match R_fixed to R₂₅ for maximum sensitivity around 25 °C. For applications centered around body temperature (37 °C) or engine temperature (80–100 °C), match R_fixed to the NTC resistance at your expected operating midpoint. This shifts the peak sensitivity of the divider to your region of interest.
B-value accuracy and the Steinhart-Hart alternative
The Beta model treats B as constant across the full temperature range — it is not. A typical 10 kΩ NTC with B = 3950 has about ±1–2 °C error at temperature extremes (−40 °C and +125 °C) compared to a calibrated Steinhart-Hart model. For most embedded applications this is acceptable.
The full Steinhart-Hart equation uses three coefficients (A, B, C) and fits a wider range to ±0.1 °C:
1/T = A + B × ln(R) + C × [ln(R)]³
Some datasheets provide A, B, C directly. Others provide resistance values at three temperatures from which you can solve the 3×3 system to find the coefficients. Use the 3-coefficient model when:
- Temperature span exceeds 80 °C
- Accuracy better than ±0.5 °C is required
- You are in a safety-critical application (battery thermal management, motor drives)
Reading the datasheet
The key parameters you need:
- R₂₅ — resistance at 25 °C. Nominal value in the part number (e.g. “10K” = 10 kΩ). Tolerance is typically ±1%, ±2%, or ±5%.
- B₂₅/₈₅ or B₂₅/₅₀ — the B-value measured between 25 °C and 85 °C (or 25 °C and 50 °C). Use the range that covers your operating temperature. Common values: 3380 K (Vishay NTCLE100), 3950 K (EPCOS/TDK B57), 3435 K (Semitec 103AT).
- Tolerance class — F = ±1%, H = ±3%, J = ±5% on resistance at 25 °C.
- Thermal time constant — how fast the thermistor tracks temperature changes. A bare 0402 bead in still air: ~5 s. Same part potted in thermal paste against a PCB copper pour: ~1 s.
Common firmware mistakes
Integer overflow in fixed-point Beta math. Evaluating exp(B × (1/T − 1/T₀)) in fixed-point requires careful scaling. B = 3950, 1/T₀ ≈ 0.00336 — multiply these together to get ~13.3. With Q16.16 representation the intermediate B/T term can overflow a 32-bit register. Use 64-bit intermediates or convert to float. On Cortex-M4 with FPU, float is cheaper than the software overflow protection.
Using ADC_count / ADC_max as a float truncation. If count and max_count are both uint16_t, count / max_count evaluates to zero for every count < max_count. Cast to float before dividing:
float ratio = (float)adc_count / (float)((1 << ADC_BITS) - 1);
Not accounting for ADC reference voltage accuracy. The formula assumes V_adc = VCC × count / max_count. If you are using the internal voltage reference (1.2 V, 2.5 V depending on the MCU) rather than VCC, the VCC in the R_ntc formula must match the actual ADC reference. Feeding a 3.3 V divider into an ADC with a 3.0 V internal reference means the top 10% of the range saturates — and your cold-temperature readings will look like short circuits.
Ignoring self-heating. Passing current through an NTC heats it. At 10 kΩ with a 3.3 V divider, peak current is ~3.3 V / (10 kΩ + 10 kΩ) = 165 µA. Power in the NTC = 165 µA × 1.65 V = ~0.27 mW. In still air, a typical glass-bead NTC has thermal resistance ~150 °C/W — meaning 0.27 mW causes ~0.04 °C self-heating. Negligible. At 100 Ω NTC in a low-resistance circuit, recalculate — self-heating can exceed 1 °C.
Sharing the NTC bias resistor between MCU power rails. If R_fixed connects to VCC and the ADC reference is VDDA (analog supply, often a filtered copy of VCC), any noise on VCC appears as temperature noise. Use a separate filtered supply for the divider, or read VCC with a different ADC channel and normalize.
Firmware implementation
Minimal Zephyr/C implementation of the ADC path using the Beta equation:
#define NTC_R25 10000.0f /* Ω */
#define NTC_BETA 3950.0f /* K */
#define NTC_R_FIXED 10000.0f /* Ω — upper divider resistor */
#define T0_K 298.15f
#define ADC_MAX 4095.0f /* 12-bit */
float ntc_adc_to_celsius(uint16_t adc_count)
{
float ratio = (float)adc_count / ADC_MAX;
float r_ntc = NTC_R_FIXED * ratio / (1.0f - ratio);
float t_k = 1.0f / (1.0f / T0_K + logf(r_ntc / NTC_R25) / NTC_BETA);
return t_k - 273.15f;
}
logf is <math.h> natural log. On Cortex-M4 with FPU enabled (-mfpu=fpv4-sp-d16 -mfloat-abi=hard), this executes in ~20 cycles including the logf approximation in newlib.
For lookup-table approaches (faster, no transcendental math): pre-compute a table of 256 ADC counts vs temperature at build time and use linear interpolation between entries. Accurate to ±0.1 °C within the table range.