Embedded HandbookApps
All sections › XI. Sensors: connection, circuits, drivers
STM32F103, STM32F407 · level intermediate · 8 min read
Open in the interactive handbook

104. Thermocouple: MAX31855 and MAX6675

The DS18B20 stops at +125 °C, a glass-bodied thermistor at 250–300 °C, but a furnace, a soldering iron or an exhaust needs a thermocouple. It is two wires of different alloys, welded together at the end. It does not measure temperature but a difference: a voltage appears between the hot junction and the point where its wires change to copper — the cold junction. For type K this is about 41 µV per degree. The MAX6675 and MAX31855 measure these microvolts, measure the cold-junction temperature themselves and return a ready number over SPI. What is left is to parse the frame — with the sign and the fault bits — and to correct the linear conversion that the MAX31855 uses in place of the real thermocouple characteristic.

The SPI bus is section 18, temperature up to +125 °C is section 96, the 24-bit sign is section 102, connecting modules is section 95.

Terms used in the documentation

Term Meaning
thermocouple two wires of different alloys joined at one end
hot junction, measuring junction the junction at the point being measured
cold junction, reference junction where the thermocouple wires meet copper
cold-junction compensation (CJC) adding the cold-junction temperature back in
Seebeck coefficient microvolts per degree
type K (chromel–alumel) the most common thermocouple type
thermoelectric voltage, EMF the voltage the thermocouple produces
extension wire thermocouple-alloy wire for extending the leads
grounded / ungrounded junction junction tied to the sheath / insulated junction
open circuit (OC) broken wire
short to GND / VCC (SCG / SCV) short to ground / to the supply
linearization correcting for non-linearity

104.1 The thermocouple and the cold junction

Type K thermocouple on a MAX31855: three SPI wires and two thermocouple wires

The thermocouple voltage is E(hot) − E(cold), where E is the standard thermoelectric voltage table for its type. For type K:

Temperature Thermoelectric voltage
−200 °C −5.891 mV
−100 °C −3.554 mV
25 °C 1.000 mV
100 °C 4.096 mV
500 °C 20.644 mV
1000 °C 41.276 mV

So the converter measures two things: the thermocouple voltage and its own temperature — which is the cold-junction temperature, as long as the thermocouple wires run straight to its pins. A step of 0.25 °C is 10.3 µV: the microcontroller's built-in ADC cannot resolve a voltage that small.

Extending a thermocouple: copper wire moves the cold junction to the terminals, thermocouple wire keeps it at the chip


104.2 Two converters

MAX6675 MAX31855K
Frame 16 bits 32 bits
Temperature 0 … 1023.75 °C, unsigned −200 … +1350 °C for type K, signed
Step 0.25 °C 0.25 °C; cold junction 0.0625 °C
Faults "no thermocouple" open circuit, short to ground, short to supply
Supply 3.0 … 5.5 V 3.0 … 3.6 V
Conversion up to 0.22 s up to 0.1 s
SCK up to 4.3 MHz up to 5 MHz

The MAX31855 is made for different thermocouple types — the letter at the end of the name tells you which; the MAX6675 is for type K only.


104.3 Receive-only SPI

Both chips only send: while CS is low, each SCK clock shifts out the next bit, MSB first. MOSI is not needed, but the microcontroller's SPI still transmits — just to generate the clocks. Mode 0, 16-bit frame:

void tc_spi_init(void)
{
#if defined(STM32F10X_MD)
    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_SPI1EN;
    GPIOA->CRL = (GPIOA->CRL & ~0x0FFF0000u) | 0x04B30000u;         /* PA4 выход, PA5 альт. выход, PA6 вход */
#else
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
    RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
    GPIOA->MODER = (GPIOA->MODER & ~0x3F00u) | 0x2900u;             /* PA4 выход, PA5 и PA6 — AF */
    GPIOA->AFR[0] = (GPIOA->AFR[0] & ~0x0FF00000u) | 0x05500000u;   /* AF5 — SPI1 */
#endif
    GPIOA->BSRR = 1u << 4;                                          /* CS в единице */
    SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_DFF | (TC_BR << 3);
    SPI1->CR1 |= SPI_CR1_SPE;
}

The baud-rate prescaler is 32. On the F103, SPI1 is clocked from 72 MHz, which gives an SCK of 2.25 MHz; on the F407 it is clocked from 84 MHz, giving 2.625 MHz. With a prescaler of 16 it would be 4.5 and 5.25 MHz — above the MAX6675 limit; two _Static_assert catch this at build time. A whole MAX31855 frame takes 14.2 µs.

uint32_t tc_read(unsigned words)
{
    GPIOA->BSRR = 1u << (4 + 16);       /* CS в ноль: текущее преобразование прерывается */
    uint32_t v = tc_xfer16();
    if (words == 2)
        v = v << 16 | tc_xfer16();
    while (SPI1->SR & SPI_SR_BSY) {}
    GPIOA->BSRR = 1u << 4;              /* CS в единицу: пошло новое преобразование */
    return v;
}

Pulling CS low aborts the conversion in progress; raising it starts a new one. The MAX6675 takes up to 0.22 s per conversion: if you read it more often, the number never updates. So poll it no more often than once every 250 ms.


104.4 The MAX6675 frame

D15 is always zero, D14…D3 are the temperature in quarter degrees, D2 is one when there is no thermocouple:

int32_t max6675_q(uint16_t frame)
{
    if (frame & MAX6675_OPEN)
        return -1;
    return (int32_t)(frame >> 3);
}

The model: code 100 is 25.00 °C, 4095 is the 1023.75 °C limit, and the same code with D2 set gives −1, "no thermocouple". The MAX6675 knows nothing about negative temperatures.


104.5 The MAX31855 frame: sign and faults

The 32-bit frame holds two signed numbers: the hot junction — 14 bits in D31…D18, in quarter degrees, and the cold junction — 12 bits in D15…D4, in sixteenths. Both are in two's complement, and the sign is extended the same way as for the HX711:

int32_t max31855_hot_q(uint32_t frame)
{
    uint32_t v = frame >> 18;
    return (v & 0x2000u) ? (int32_t)(v | 0xFFFFC000u) : (int32_t)v;
}

int32_t max31855_cold_q(uint32_t frame)
{
    uint32_t v = (frame >> 4) & 0xFFFu;
    return (v & 0x800u) ? (int32_t)(v | 0xFFFFF000u) : (int32_t)v;
}

Checking against the codes from the datasheet: 0x1900 is 1600.00 °C, 0x3C18 is −250.00 °C, 0x3FFF is −0.25 °C; cold junction 0x7F0 is 127 °C, 0xC90 is −55 °C. Without sign extension, −250 °C would turn into 3846.00 °C.

Bit D16 says that there is a fault, and D2…D0 say which one:

unsigned max31855_fault(uint32_t frame)
{
    return (frame & MAX31855_FAULT) ? (unsigned)(frame & 7u) : 0u;
}

The model with an open circuit, a short to ground and a short to the supply gives 1, 2 and 4; a healthy one gives 0. Do not take the temperature from a frame with a fault.

MAX31855 frame: 32 bits, two signed numbers and the fault


104.6 Correcting for non-linearity

The MAX31855 converts voltage to degrees with a single coefficient: it divides it by 41.276 µV/°C and adds the cold-junction temperature. That is the exact thermoelectric voltage at 1000 °C divided by 1000 — the average slope from 0 to 1000 °C. A thermocouple is non-linear, and away from that range the error grows. The model with the cold junction at 25 °C:

Hot junction MAX31855 After correction
−200 °C −142.00 −199.75
−100 °C −85.25 −99.75
100 °C 100.00 100.00
300 °C 296.50 300.00
800 °C 807.00 800.25
1200 °C 1184.00 1200.25
1350 °C 1312.25 1350.00

The correction works backwards: from the reading you recover the voltage the chip saw, add the cold-junction thermoelectric voltage and look up the temperature in the standard table — 32 points every 50 °C, 128 bytes:

static const int32_t K_UV[K_N] = {
    -5891, -4913, -3554, -1889,     0,  2023,  4096,  6138,
     8138, 10153, 12209, 14293, 16397, 18516, 20644, 22776,
    24905, 27025, 29129, 31213, 33275, 35313, 37326, 39314,
    41276, 43211, 45119, 46995, 48838, 50644, 52410, 54138,
};

int32_t max31855_true_q(uint32_t frame)
{
    int32_t hot = max31855_hot_q(frame), cold = max31855_cold_q(frame);
    int32_t uv = (int32_t)((int64_t)(hot * 4 - cold) * 41276 / 16000);    /* что увидел чип */
    return k_q(uv + k_uv(cold));
}

k_uv and k_q are linear interpolation between the points, in one direction and in the other. In a sweep from −200 to +1350 °C in 0.5 °C steps, the uncorrected error reaches 58.00 °C below zero and 37.75 °C above; after correction it is no more than 2.50 and 0.50 °C. The correction also takes the cold junction into account: 500 °C with the board at 25 °C is shown by the chip as 501.00, at 50 °C as 501.25, and after correction it comes out as 500.25 and 500.00.

MAX31855 error from −200 to +1350 °C with the cold junction at 25 °C: uncorrected up to +58.00 °C at the bottom and −37.75 °C at the top, after table correction no more than 2.50 °C


104.7 Pitfalls

−250 °C reads as 3846 °C. A 14-bit code without sign extension.

MAX6675 readings never change. CS is pulled low more often than once every 0.22 s — each read aborts the conversion. Read once every 250 ms.

The temperature falls as it heats up. The thermocouple wires are swapped: swapping plus and minus reverses the sign of the voltage.

The reading drifts when the terminals warm up. The thermocouple was extended with copper wire: the cold junction moved to the terminals, while the converter measures its own temperature. Extend only with thermocouple wire of the same type.

SCG fault with an intact thermocouple. The junction touches grounded metal, and the MAX31855 sees a short to ground. You need a thermocouple with an insulated junction.

The furnace is at 1200 °C, but the display shows 1184. The MAX31855 linear conversion without correction.

The MAX31855 does not respond or gets hot. It is powered from 5 V, but it is rated for 3.0 … 3.6 V.


104.8 Summary

Next: section 104а "Soldering iron on STM32: inside IronOS — a thermocouple in the tip, PID and USB Power Delivery" — the same thermocouple, but inside the tip: it is measured with the built-in ADC between heating pulses.

Open in the interactive handbook