When you need temperature measurements that remain stable across years and extreme thermal ranges, thermistors and digital sensors like the DS18B20 fall short. Platinum Resistance Temperature Detectors (PT100) are the industrial standard for precision, but they require careful analog front-end design. This guide covers the exact hardware, math, and debugging steps for integrating PT100 RTD sensors and circuits using the MAX31865 signal conditioner with an ESP32 or Arduino.

The Sensing Principle: How RTDs and Bridge Circuits Work

Platinum Resistance Temperature Detectors (PT100) rely on the highly predictable positive temperature coefficient of platinum. At exactly 0°C, a standard PT100 exhibits 100.00 Ω of resistance, increasing by roughly 0.385 Ω per °C. Unlike thermistors, which are highly non-linear and limited in range, PT100 sensors and circuits maintain exceptional stability and linearity from -200°C to +850°C. According to Omega Engineering's RTD theory guide, the repeatability of platinum makes it the benchmark for laboratory and industrial thermal profiling.

Because the resistance change is minuscule (a 1°C change is only 0.385 Ω), you cannot read a PT100 directly with a microcontroller's 10-bit or 12-bit ADC. You need a dedicated bridge circuit and amplifier. The MAX31865 acts as a complete signal-conditioning front-end. It drives a precise, low-noise excitation current through the RTD and a reference resistor ($R_{REF}$), measures the differential voltage, and digitizes the ratio via an internal 15-bit sigma-delta ADC. The microcontroller then reads a clean, noise-immune digital stream over SPI, completely bypassing the need to design your own analog amplification stage.

Hardware Specs and Wiring Matrix

The MAX31865 operates strictly as a digital SPI peripheral, meaning the analog-to-digital conversion happens entirely on the breakout board. Below is the critical specification matrix for the IC and the standard Adafruit breakout (Product ID 3328), which includes the necessary biasing capacitors and termination resistors for 2, 3, and 4-wire RTD configurations.

Parameter Specification / Value Design Notes
VDD Supply Range 3.0V to 3.6V Do not exceed 3.6V. Use a dedicated 3.3V LDO if your main rail is noisy.
Logic Level (V_IH) 0.7 × VDD (approx 2.3V) Directly compatible with ESP32 (3.3V) and Arduino Due. Use a level shifter for 5V Uno.
Reference Resistor ($R_{REF}$) 430 Ω (PT100) / 4.3 kΩ (PT1000) Determines measurement span. Must be 0.1% tolerance for high accuracy.
ADC Resolution 15-bit (32,768 steps) Yields ~0.03°C theoretical resolution with a 430 Ω reference.
Excitation Current ~0.7 mA (PT100) / ~0.07 mA (PT1000) Kept low to prevent RTD self-heating errors.

ESP32 to MAX31865 SPI Pinout

The MAX31865 requires SPI Mode 3 (CPOL=1, CPHA=1). If your SPI library defaults to Mode 0, the IC will return garbage data or zeros. Wire the breakout to your ESP32 as follows:

MAX31865 Pin ESP32 DevKit Pin Function
VIN / VDD 3V3 Power supply (3.3V only)
GND GND Common ground reference
SCK GPIO 18 (VSPI SCK) SPI Clock (Mode 3)
SDO (MISO) GPIO 19 (VSPI MISO) Serial Data Out (to MCU)
SDI (MOSI) GPIO 23 (VSPI MOSI) Serial Data In (from MCU)
CS GPIO 5 (VSPI SS) Chip Select (Active LOW)
RDY Not Connected (or GPIO 4) Data Ready interrupt (optional, polling is usually fine)
Callout: 3-Wire Lead Compensation
If you are using a 3-wire PT100 (identified by two red wires and one white/transparent wire), you must bridge the two red wires to the RTD+ and RTD- terminals, and the white wire to RTD-. The MAX31865 measures the resistance of the white lead and mathematically subtracts it from the total reading, eliminating the error introduced by long cable runs. Ensure you set the 3-wire configuration bit (D1) in the MAX31865 config register via your library.

Output Signal Math: Raw ADC to Celsius Conversion

The output of the MAX31865 is strictly digital: a 15-bit unsigned integer delivered over SPI. The raw ADC code represents the ratio of the RTD resistance to the reference resistor ($R_{REF}$). To get a physical temperature, you must perform a two-step conversion: first, calculate the actual RTD resistance, then convert that resistance to Celsius.

Step 1: Raw ADC to Resistance

The 15-bit ADC has a maximum value of 32,768 ($2^{15}$). The formula to extract the RTD resistance is:

$$R_{RTD} = \frac{ADC_{code} \times R_{REF}}{32768}$$

Worked Example:
Assume you are using a standard PT100 breakout with a 430 Ω reference resistor. Your ESP32 reads an ADC code of 13850 from the SPI bus.

  • $R_{RTD} = (13850 \times 430) / 32768$
  • $R_{RTD} = 5955500 / 32768 = 181.74 \Omega$

Step 2: Resistance to Temperature

For temperatures above 0°C, a simplified linear approximation is often sufficient for hobbyist builds. The standard temperature coefficient ($\alpha$) for a PT100 is 0.00385 Ω/Ω/°C.

$$T = \frac{R_{RTD} - 100}{100 \times \alpha} = \frac{R_{RTD} - 100}{0.385}$$

Using our example: $T = (181.74 - 100) / 0.385 = 212.31°C$.

However, if you are measuring sub-zero temperatures or require laboratory-grade accuracy across the full span, the linear approximation introduces an error of up to 1.5°C at the extremes. You must use the Callendar-Van Dusen (CVD) equation. For temperatures $T < 0°C$, the CVD equation is:

$$R(T) = R_0 [1 + AT + BT^2 + C(T - 100)T^3]$$

Where $R_0 = 100 \Omega$, and the standard IEC 60751 coefficients are $A = 3.9083 \times 10^{-3}$, $B = -5.775 \times 10^{-7}$, and $C = -4.183 \times 10^{-12}$. Most modern embedded libraries (like the Adafruit MAX31865 library) handle the CVD root-finding algorithm under the hood, but understanding the math is critical when debugging anomalous sub-zero readings.

Interference, Calibration, and Fault Debugging

Even with a dedicated IC, precision thermal measurements are vulnerable to environmental and electrical interference. The most common failure modes in RTD sensors and circuits stem from EMI coupling, self-heating, and reference drift.

Common Interference Sources

  1. 50/60Hz Mains Coupling: Long, unshielded RTD leads act as antennas for AC mains noise. The MAX31865 includes a hardware 50Hz/60Hz rejection filter. You must set the D0 bit in the Configuration Register (0x00) to enable this filter. If your system is in a region with 50Hz mains (EU/UK/AU), the filter notch is tuned accordingly; for 60Hz (US), the internal clock divider adjusts the integration time to reject the specific harmonic.
  2. Self-Heating: The excitation current passing through the PT100 generates $I^2R$ heat. In still air or low-thermal-mass environments, this can artificially elevate the reading by 0.1°C to 0.5°C. The MAX31865 mitigates this by only applying the bias current during the actual conversion cycle (pulsed operation), but you should avoid running continuous conversion loops faster than necessary.
  3. $R_{REF}$ Tolerance Drift: This is the most overlooked calibration error. Many budget breakout boards ship with a 1% tolerance 430 Ω resistor. A 1% error in $R_{REF}$ translates directly to a ~2.5°C error in your final temperature reading. For precision builds, desolder the stock resistor and replace it with a 0.1% or 0.05% tolerance metal foil resistor (e.g., Vishay Y1442 series).

Fault Register Debugging

The MAX31865 features a dedicated Fault Status Register (0x07). When your code reads an impossible temperature (e.g., 1000°C or -200°C), do not assume the sensor is broken. Read the fault register. According to the Analog Devices MAX31865 datasheet, the bits map to specific physical wiring faults:

Fault Bit (D7-D0) Meaning Physical Cause & Fix
D7 (HIGH) RTD High Threshold RTD resistance exceeds the high limit register. Check for short to VDD or open circuit.
D6 (LOW) RTD Low Threshold RTD resistance is below the low limit. Check for a dead short across the RTD terminals.
D2 (REF-) REF- out of range The reference resistor is missing, broken, or the solder joint on the breakout is cracked.
D0 (Reserved) Reserved / General Often indicates VBIAS is not enabled. Ensure your init code sets D7 (VBIAS) in the config register.
Bench Tip: The VBIAS Gotcha
A frequent mistake when porting code from Arduino to ESP32 is forgetting to initialize the VBIAS bit. The MAX31865 requires the VBIAS bit (D7 in register 0x00) to be set to '1' before starting a conversion. If you read all zeros on the MISO line and your fault register shows D0 or D2 errors, your SPI wiring is likely fine, but the analog front-end is powered down. Always write 0x80 (or 0x82 for 3-wire mode) to the config register before triggering a one-shot conversion.

By treating the MAX31865 not just as a passive ADC, but as an active bridge controller, and by verifying your $R_{REF}$ hardware tolerance, you can achieve laboratory-grade thermal stability in your embedded projects. Always verify your SPI clock polarity, leverage the internal 50/60Hz filters, and let the Callendar-Van Dusen math handle the non-linear extremes of the platinum curve.