
Max6675 is an Arduino library for MAX6675 chip with a K type thermocouple.
The library is based upon (stripped and adapted version of) the https://github.com/RobTillaart/MAX31855_RT library.
Currently the library is experimental, so use with care.
Hardware has finally arrived (April 2022) and I had time to do my first round of tests with an UNO at 16 MHz. The library works and it reads temperatures well, both with HW SPI and SW SPI.
The MAX6675 is a chip to convert the reading of a K-type thermocouple to a temperature. The MAX6675 only supports positive degrees Celsius.
The values are read with an precision of 0.25°C. Typical noise seen during usage are ± 0.5°C, so using a low pass filter on the temperature might be a good idea.
The working of thermocouples (TC) is based upon Seebeck effect. Different TC’s have a different Seebeck Coefficient (SC) expressed in µV/°C. See http://www.analog.com/library/analogDialogue/archives/44-10/thermocouple.html
The library is tested with a breakout board with following pins:
+---------------------+
| signal out | --> MISO
| - chip select | <-- SELECT
TC here | clock | <-- CLOCK processor side
| + VCC | --- VCC
| GND | --- GND
+---------------------+
Version 0.3.0 introduced a breaking change to improve handling the SPI dependency. The user has to call SPI.begin() or equivalent before calling AD.begin(). Optionally the user can provide parameters to the SPI.begin(…)
The version 0.2.0 has breaking changes in the interface. The essence is removal of ESP32 specific code from the library. This makes it possible to support the ESP32-S3 and other processors in the future. Also it makes the library a bit simpler to maintain.
Note the order of the parameters of the software SPI constructor has changed in 0.2.0.
- https://github.com/RobTillaart/MAX6675
- https://github.com/RobTillaart/MAX31850
- https://github.com/RobTillaart/MAX31855_RT
- https://github.com/RobTillaart/Temperature conversion to (exotic) temperature scales.
Default pin connections.
HW SPI | UNO | ESP32 VSPI | ESP32 HSPI | Notes |
---|---|---|---|---|
CLOCK | 13 | 18 | 14 | |
MISO | 12 | 19 | 12 | |
MOSI | 11 | 23 | 13 | not used… |
SELECT | eg. 4 | 5 | 15 | can be others too. |
Performance read() function, timing in us.
- UNO @ 16 MHz
- TODO ESP32 @ 240 MHz
mode | clock | timing UNO | timing ESP32 | Notes |
---|---|---|---|---|
HW SPI | 4000000 | 36 | highest supported. | |
HW SPI | 3500000 | 40 | ||
HW SPI | 3000000 | 40 | ||
HW SPI | 2500000 | 40 | ||
HW SPI | 2000000 | 40-44 | ||
HW SPI | 1500000 | 48 | ||
HW SPI | 1000000 | 48-52 | ||
HW SPI | 500000 | 64-68 | ||
SW SPI | bit bang | 276 |
Note the UNO micros() has a 4 us precision, but it is clear that
4 Mb is not even twice the speed of 0.5 Mb.
Tested with MAX6675_test_HWSPI.ino
#include "MAX6675.h"
- MAX6675(uint8_t select, SPIClassRP2040 * mySPI) hardware SPI R2040
- MAX6675(uint8_t select, SPIClass * mySPI) hardware SPI other
- MAX6675(uint8_t select, uint8_t miso, uint8_t clock) software SPI
- void begin() initialize internals
To be used only if one needs a specific speed.
- void setSPIspeed(uint32_t speed) set SPI transfer rate.
- uint32_t getSPIspeed() returns SPI transfer rate.
- void setSWSPIdelay(uint16_t del = 0) for tuning SW SPI signal quality. Del is the time in micros added per bit. Even numbers keep the duty cycle of the clock around 50%.
- uint16_t getSWSPIdelay() get set value in micros.
- uint8_t read() makes a temperature measurement. It returns the status of the read (0, 4 or 129)
- uint8_t getStatus() returns the last status value of read(). Will stay the same until a new read() call.
- float getTemperature() returns last temperature in Celsius. (will be obsolete in future).
- float getCelsius() returns last temperature in Celsius. (more explicit scale). Will stay the same until a new read() call.
- float getFahrenheit() wrapper around getCelsius(). Returns last temperature in Fahrenheit. Will stay the same until a new read() call.
Table: values returned from uint8_t read() and uint8_t getStatus()
Note: this list is a subset of MAX31855 errors.
Define | value | Description | Action | Notes |
---|---|---|---|---|
STATUS_OK | 0 | OK | ||
STATUS_ERROR | 4 | Thermocouple short to VCC | check wiring | |
STATUS_NOREAD | 128 | No read done yet | check wiring | only before first read() |
STATUS_NO_COMMUNICATION | 129 | No communication | check wiring |
After uint8_t read() returns STATUS_OK you can get the temperature with getCelsius() or getFahrenheit().
Repeated calls to getCelsius() or getFahrenheit() will give the same value until a new measurement is made by calling read().
Note: if the read() fails the value of getCelsius() can become incorrect. So it is important to check the return value of read().
The library supports a fixed offset to calibrate the thermocouple. For this the functions float getOffset() and void setOffset(float offset) are available. This offset is “added” in the getCelsius() function.
Note:
- the offset is a constant in degrees Celsius (for Fahrenheit offset multiply by 1.8)
- the offset used is a float, so decimals can be used. A typical usage is to call setOffset(273.15) to get degrees ° Kelvin.
- the offset can be positive or negative.
- the offset can cause negative temperatures to pop up at the lower end.
As the tc object holds its last known temperature it is easy to determine the delta with the last known temperature, e.g. for trend analysis.
float last = tc.getCelsius();
int state = tc.read();
if (state == STATUS_OK)
{
float new = tc.getCelsius();
float delta = new - last;
// process data
}
The tc object keeps track of the last time read() is called in the function uint32_t lastRead(). The time is tracked in millis(). This makes it easy to read the sensor at certain intervals.
if (millis() - tc.lastRead() >= interval)
{
int state = tc.read();
if (state == STATUS_OK)
{
float new = tc.getCelsius();
// process read value.
}
else
{
// handle error
}
}
The function uint32_t getRawData() allows you to get all the 32 bits raw data from the board, after the standard uint8_t tc.read() call.
Example code can be found in the examples folder.
int state = thermocouple.read();
uint32_t value = thermocouple.getRawData(); // Read the raw Data value from the module
This allows one to compact the measurement e.g. for storage or sending over a network.
To have proper working of the MAX6675 board, you need to add a pull-up resistor (e.g. 4K7 – 1K depending on wire length) between the MISO pin (from constructor call) and the VCC (5 Volt). This improves the signal quality and will allow you to detect if there is proper communication with the board. Without pull-up one might get random noise that could look like real data.
Note: the MISO pin can be different from each board, please refer to your board datasheet.
If the MAX6675 board is not connected tc.read() will return STATUS_NO_COMMUNICATION.
You can verify this by tc.getRawData() which will give 16 HIGH bits or 0xFFFF).
You can use a simple code to detect connection error board:
uint8_t status = thermocouple.read();
if (status == STATUS_NO_COMMUNICATION)
{
Serial.println("NO COMMUNICATION");
}
or
uint8_t status = thermocouple.read();
if (thermocouple.getRawData() == 0xFFFF)
{
Serial.println("NO COMMUNICATION");
}
See examples
- update and verify documentation (as it is copied from MAX31855 lib)
- keep interface in sync with MAX31855 if possible.
- create example to distinguish between MAX6675 and MAX31855
If you appreciate my libraries, you can support the development and maintenance. Improve the quality of the libraries by providing issues and Pull Requests, or donate through PayPal or GitHub sponsors.
Thank you,

Leave a Reply