If you want to measure temperature with laboratory-grade accuracy, thermistors and thermocouples will not cut it. You need an RTD sensor circuit. However, a common pitfall for embedded hobbyists is assuming an RTD outputs a voltage you can read directly. It does not. An RTD is purely a passive, variable resistor. To interface it with an ESP32 or Arduino, you must build an analog front-end that injects a precision excitation current, measures the resulting voltage drop, and digitizes it. The industry-standard shortcut for this is the MAX31865 RTD-to-Digital converter.

In this guide, we will wire a PT100 3-wire RTD to an ESP32 via a MAX31865 breakout board, walk through the exact SPI pinout, and break down the raw ADC math required to convert 15-bit register values into degrees Celsius.

The Physics of Platinum: How RTDs Actually Measure Heat

Resistance Temperature Detectors (RTDs) rely on the highly predictable positive temperature coefficient of pure metals. While copper and nickel are sometimes used, platinum is the undisputed standard for precision work due to its chemical inertness and linear resistance curve. A standard PT100 sensor is manufactured to have exactly 100.00 Ω of resistance at 0°C, while a PT1000 has 1000.00 Ω at 0°C. According to Omega Engineering's RTD fundamentals, the most common platinum curve is the '3850' curve, meaning the resistance increases by approximately 0.385 Ω per degree Celsius for a PT100.

Unlike thermistors, which exhibit massive, highly non-linear resistance swings, or thermocouples, which generate microvolts via the Seebeck effect and require cold-junction compensation, RTDs offer exceptional long-term stability and linearity. The trade-off is that the signal is incredibly small. A 1°C change in a PT100 yields only a 0.385 Ω change. If you attempt to read this with a standard microcontroller ADC using a basic voltage divider, thermal noise and ADC non-linearity will destroy your resolution. This is why a dedicated 15-bit sigma-delta ADC like the MAX31865 is mandatory for a functional RTD sensor circuit.

Wiring the MAX31865 RTD Sensor Circuit to an ESP32

Analog vs. Digital Distinction: The RTD probe itself is strictly analog (a passive resistor). The MAX31865 chip acts as the analog-front-end (AFE), exciting the probe and outputting a digital SPI stream. Never wire a PT100 directly to an ESP32 GPIO or analog input pin; you will read floating garbage and risk damaging the pin if the probe shorts to a voltage source.

For this build, we are using an ESP32 DevKit V1 and an Adafruit MAX31865 breakout (approx. $14.95, though generic clones run about $2.50 if you verify their reference resistors). We are assuming a 3.3V logic supply and a PT100 3-wire configuration.

ESP32 to MAX31865 SPI Pinout

MAX31865 PinESP32 PinFunctionNotes
VIN3V3Power SupplySupply range: 3.0V to 5.5V. Do not use 5V on ESP32.
GNDGNDGroundCommon ground required.
SCKGPIO 18SPI ClockDefault VSPI clock.
SDO (MISO)GPIO 19Serial Data OutData from MAX31865 to ESP32.
SDI (MOSI)GPIO 23Serial Data InData from ESP32 to MAX31865.
CSGPIO 5Chip SelectActive LOW. Pull high when idle.
RDYNot ConnectedData ReadyOptional interrupt pin; polling works fine.

MAX31865 to PT100 (3-Wire Configuration)

Three-wire RTDs have two red wires and one white wire. The MAX31865 uses the second red wire to measure and cancel out the resistance of the copper lead wires.

  1. Red Wire 1: Connect to the RTD+ terminal.
  2. Red Wire 2: Connect to the RTD- terminal (labeled for 3-wire).
  3. White Wire: Connect to the RTD- terminal (labeled for 2/4-wire) and bridge the 2-wire/3-wire jumper pads on the breakout board with a blob of solder.
Safety Caveat: When probing RTDs installed inside industrial HVAC panels, boiler controllers, or motor enclosures, always de-energize the mains supply. Inductive kickback from nearby contactors or VFDs can couple onto the RTD leads and fry your microcontroller's SPI bus. Use twisted, shielded pair cable for the RTD leads, grounding the shield at the panel side only.

From Raw ADC Bits to Degrees: The Conversion Math

Once your hardware is hooked up, the MAX31865 does the heavy lifting of injecting a precision current and measuring the voltage drop. However, the chip does not output degrees Celsius. It outputs a raw 15-bit integer representing the ratio of the RTD resistance to the onboard reference resistor (Rref).

The Raw-to-Resistance Formula

The MAX31865 uses a 15-bit ADC, meaning the maximum raw value is 32,767 (0x7FFF). The formula to extract the actual RTD resistance is:

R_RTD = (Raw_ADC_Code × Rref) / 32768

Worked Numeric Example:
Assume you are using a PT100 with a standard 430 Ω, 0.1% tolerance reference resistor on the MAX31865 board. You read a raw ADC value of 16384 from the SPI register.
1. R_RTD = (16384 × 430) / 32768
2. R_RTD = 215.0 Ω

Scaling to Temperature (Callendar-Van Dusen)

To convert 215.0 Ω into a physical temperature unit, we must account for the platinum curve. For temperatures above 0°C, a linear approximation works reasonably well for hobbyist grades:

Temp = (R_RTD - 100) / 0.385
Temp = (215.0 - 100) / 0.385 = 298.7°C

However, as detailed in Analog Devices' RTD measurement guide, the platinum curve is slightly parabolic. For true laboratory accuracy, you must use the Callendar-Van Dusen (CVD) equation, which applies specific polynomial constants (A, B, C) based on the ITS-90 temperature scale. Fortunately, if you are using the Adafruit MAX31865 Arduino library, you can bypass manual polynomial math by calling max.temperature(100, 430), which handles the CVD scaling internally.

Common Interference Sources and Calibration

Even with a 15-bit ADC, your RTD sensor circuit can fall victim to environmental noise:

  • Lead Wire Resistance: In a 2-wire setup, 20 AWG copper wire adds about 0.05 Ω per foot. For a PT100, that is a 0.13°C error per foot. Always use 3-wire or 4-wire topologies for runs longer than 3 feet.
  • 50/60Hz Mains Coupling: Running RTD cables parallel to AC mains wiring induces common-mode noise. The MAX31865 features a configurable 50Hz/60Hz rejection filter in its configuration register (Bit 0). Ensure your firmware sets this bit based on your local grid frequency.
  • Thermal EMF: If you use dissimilar metals at your terminal blocks (e.g., copper wire crimped to a nickel-plated spade lug), temperature gradients across the junction will generate microvolts of error. Keep terminal blocks away from heat sinks.

RTD Sensor Circuit FAQs: Troubleshooting and Design Choices

Why is my RTD sensor circuit reading exactly 85°C or throwing fault code 0x04?

If your serial monitor spits out a constant 85.0°C or the MAX31865 fault register returns 0x04 (RTDIN High), you have an open circuit. The MAX31865 expects to see a resistance within a specific window. If the wire is broken, or if the terminal block screws are loose, the ADC saturates at the high rail. Check your physical connections, verify the continuity of the PT100 probe with a multimeter (it should read ~109 Ω at room temperature), and ensure the 2-wire/3-wire jumper on the breakout board matches your physical wiring.

Can I build an RTD sensor circuit using just a voltage divider and the ESP32 internal ADC?

Technically yes, but practically no. The ESP32's internal 12-bit ADC is notoriously non-linear, suffers from high noise floors, and has a limited input impedance. A PT100 changes by only 0.385 Ω per degree. A simple 5V voltage divider will not yield the millivolt-level resolution required to resolve sub-degree changes, and self-heating from the divider current will skew your readings. Always use a dedicated high-resolution ADC like the MAX31865, MAX31856, or an external instrumentation amplifier (like the INA826) for professional results.

Should I use a PT100 or PT1000 for long-distance wiring in my RTD sensor circuit?

Choose the PT1000 for long runs. A PT1000 has a base resistance of 1000 Ω at 0°C and changes by ~3.85 Ω/°C. Because the baseline resistance is ten times higher, the fixed resistance of your copper lead wires becomes a much smaller percentage of the total circuit resistance. This drastically reduces the error margin in 2-wire setups and makes 3-wire cancellation math much more forgiving. If you switch to a PT1000, remember to change the Rref resistor on your MAX31865 board from 430 Ω to 4.3 kΩ to maintain the correct ADC scaling ratio.