Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix up MAX31865 / SPI (PT100 & PT1000) support #20074

Merged
merged 17 commits into from
Nov 11, 2020
Merged
10 changes: 5 additions & 5 deletions Marlin/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -436,11 +436,11 @@
#define DUMMY_THERMISTOR_998_VALUE 25
#define DUMMY_THERMISTOR_999_VALUE 100

// Resistor values when using a MAX31865 (sensor -5)
// Sensor value is typically 100 (PT100) or 1000 (PT1000)
// Calibration value is typically 430 ohm for AdaFruit PT100 modules and 4300 ohm for AdaFruit PT1000 modules.
//#define MAX31865_SENSOR_OHMS 100
//#define MAX31865_CALIBRATION_OHMS 430
// Resistor values when using MAX31865 sensors (-5) on TEMP_SENSOR_0 / 1
//#define MAX31865_SENSOR_OHMS_0 100 // (Ω) Typically 100 or 1000 (PT100 or PT1000)
//#define MAX31865_CALIBRATION_OHMS_0 430 // (Ω) Typically 430 for AdaFruit PT100; 4300 for AdaFruit PT1000
//#define MAX31865_SENSOR_OHMS_1 100
//#define MAX31865_CALIBRATION_OHMS_1 430

// Use temp sensor 1 as a redundant sensor with sensor 0. If the readings
// from the two sensors differ too much the print will be aborted.
Expand Down
9 changes: 7 additions & 2 deletions Marlin/src/inc/Conditionals_post.h
Original file line number Diff line number Diff line change
Expand Up @@ -445,9 +445,9 @@
#define HEATER_0_MAX6675_TMAX 1024
#endif
#if TEMP_SENSOR_0 == -5
#define MAX6675_IS_MAX31865 1
#define MAX6675_0_IS_MAX31865 1
#elif TEMP_SENSOR_0 == -3
#define MAX6675_IS_MAX31855 1
#define MAX6675_0_IS_MAX31855 1
#endif
#elif TEMP_SENSOR_0 == -4
#define HEATER_0_USES_AD8495 1
Expand All @@ -473,6 +473,11 @@
#define HEATER_1_MAX6675_TMIN 0
#define HEATER_1_MAX6675_TMAX 1024
#endif
#if TEMP_SENSOR_1 == -5
#define MAX6675_1_IS_MAX31865 1
#elif TEMP_SENSOR_1 == -3
#define MAX6675_1_IS_MAX31855 1
#endif
#if TEMP_SENSOR_1 != TEMP_SENSOR_0
#if TEMP_SENSOR_1 == -5
#error "If MAX31865 Thermocouple (-5) is used for TEMP_SENSOR_1 then TEMP_SENSOR_0 must match."
Expand Down
10 changes: 8 additions & 2 deletions Marlin/src/inc/SanityCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,10 @@
#error "MAX6675_SS is now MAX6675_SS_PIN. Please update your configuration and/or pins."
#elif defined(MAX6675_SS2)
#error "MAX6675_SS2 is now MAX6675_SS2_PIN. Please update your configuration and/or pins."
#elif defined(MAX31865_SENSOR_OHMS)
#error "MAX31865_SENSOR_OHMS is now MAX31865_SENSOR_OHMS_0. Please update your configuration."
#elif defined(MAX31865_CALIBRATION_OHMS)
#error "MAX31865_CALIBRATION_OHMS is now MAX31865_CALIBRATION_OHMS_0. Please update your configuration."
#elif defined(SPINDLE_LASER_ENABLE)
#error "SPINDLE_LASER_ENABLE is now SPINDLE_FEATURE or LASER_FEATURE. Please update your Configuration_adv.h."
#elif defined(SPINDLE_LASER_ENABLE_PIN)
Expand Down Expand Up @@ -1814,8 +1818,10 @@ static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal
#error "TEMP_SENSOR_1 is required with TEMP_SENSOR_1_AS_REDUNDANT."
#endif

#if MAX6675_IS_MAX31865 && !(defined(MAX31865_SENSOR_OHMS) && defined(MAX31865_CALIBRATION_OHMS))
#error "MAX31865_SENSOR_OHMS and MAX31865_CALIBRATION_OHMS must be set in Configuration.h when using a MAX31865 temperature sensor."
#if MAX6675_0_IS_MAX31865 && !(defined(MAX31865_SENSOR_OHMS_0) && defined(MAX31865_CALIBRATION_OHMS_0))
#error "MAX31865_SENSOR_OHMS_0 and MAX31865_CALIBRATION_OHMS_0 must be set in Configuration.h if TEMP_SENSOR_0 is MAX31865."
#elif MAX6675_1_IS_MAX31865 && !(defined(MAX31865_SENSOR_OHMS_1) && defined(MAX31865_CALIBRATION_OHMS_1))
#error "MAX31865_SENSOR_OHMS_1 and MAX31865_CALIBRATION_OHMS_1 must be set in Configuration.h if TEMP_SENSOR_1 is MAX31865."
#endif

/**
Expand Down
187 changes: 102 additions & 85 deletions Marlin/src/module/temperature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,30 +44,44 @@
#include "../lcd/extui/ui_api.h"
#endif

#if MAX6675_IS_MAX31865
#if MAX6675_0_IS_MAX31865 || MAX6675_1_IS_MAX31865
#include <Adafruit_MAX31865.h>
#ifndef MAX31865_CS_PIN
#define MAX31865_CS_PIN MAX6675_SS_PIN // HW:49 SW:65 for example
#if MAX6675_0_IS_MAX31865 && !defined(MAX31865_CS_PIN) && PIN_EXISTS(MAX6675_SS)
#define MAX31865_CS_PIN MAX6675_SS_PIN
#endif
#if MAX6675_1_IS_MAX31865 && !defined(MAX31865_CS2_PIN) && PIN_EXISTS(MAX6675_SS2)
#define MAX31865_CS2_PIN MAX6675_SS2_PIN
#endif
#ifndef MAX31865_MOSI_PIN
#define MAX31865_MOSI_PIN MOSI_PIN // 63
#define MAX31865_MOSI_PIN MOSI_PIN
#endif
#ifndef MAX31865_MISO_PIN
#define MAX31865_MISO_PIN MAX6675_DO_PIN // 42
#define MAX31865_MISO_PIN MAX6675_DO_PIN
#endif
#ifndef MAX31865_SCK_PIN
#define MAX31865_SCK_PIN MAX6675_SCK_PIN // 40
#define MAX31865_SCK_PIN MAX6675_SCK_PIN
#endif
#if MAX6675_0_IS_MAX31865 && PIN_EXISTS(MAX31865_CS)
#define HAS_MAX31865 1
Adafruit_MAX31865 max31865_0 = Adafruit_MAX31865(MAX31865_CS_PIN
#if MAX31865_CS_PIN != MAX6675_SS_PIN
, MAX31865_MOSI_PIN, MAX31865_MISO_PIN, MAX31865_SCK_PIN // For software SPI also set MOSI/MISO/SCK
#endif
);
#endif
#if MAX6675_1_IS_MAX31865 && PIN_EXISTS(MAX31865_CS2)
#define HAS_MAX31865 1
Adafruit_MAX31865 max31865_1 = Adafruit_MAX31865(MAX31865_CS2_PIN
#if MAX31865_CS2_PIN != MAX6675_SS2_PIN
, MAX31865_MOSI_PIN, MAX31865_MISO_PIN, MAX31865_SCK_PIN // For software SPI also set MOSI/MISO/SCK
#endif
);
#endif
Adafruit_MAX31865 max31865 = Adafruit_MAX31865(MAX31865_CS_PIN
#if MAX31865_CS_PIN != MAX6675_SS_PIN
, MAX31865_MOSI_PIN // For software SPI also set MOSI/MISO/SCK
, MAX31865_MISO_PIN
, MAX31865_SCK_PIN
#endif
);
#endif

#define MAX6675_SEPARATE_SPI (EITHER(HEATER_0_USES_MAX6675, HEATER_1_USES_MAX6675) && PINS_EXIST(MAX6675_SCK, MAX6675_DO))
#if EITHER(HEATER_0_USES_MAX6675, HEATER_1_USES_MAX6675) && PINS_EXIST(MAX6675_SCK, MAX6675_DO)
#define MAX6675_SEPARATE_SPI 1
#endif

#if MAX6675_SEPARATE_SPI
#include "../libs/private_spi.h"
Expand Down Expand Up @@ -1471,13 +1485,7 @@ void Temperature::manage_heater() {
#if HEATER_0_USER_THERMISTOR
return user_thermistor_to_deg_c(CTI_HOTEND_0, raw);
#elif HEATER_0_USES_MAX6675
return (
#if MAX6675_IS_MAX31865
max31865.temperature(MAX31865_SENSOR_OHMS, MAX31865_CALIBRATION_OHMS)
#else
raw * 0.25
#endif
);
return TERN(MAX6675_0_IS_MAX31865, max31865_0.temperature(MAX31865_SENSOR_OHMS_0, MAX31865_CALIBRATION_OHMS_0), raw * 0.25);
#elif HEATER_0_USES_AD595
return TEMP_AD595(raw);
#elif HEATER_0_USES_AD8495
Expand All @@ -1489,7 +1497,7 @@ void Temperature::manage_heater() {
#if HEATER_1_USER_THERMISTOR
return user_thermistor_to_deg_c(CTI_HOTEND_1, raw);
#elif HEATER_1_USES_MAX6675
return raw * 0.25;
return TERN(MAX6675_1_IS_MAX31865, max31865_1.temperature(MAX31865_SENSOR_OHMS_1, MAX31865_CALIBRATION_OHMS_1), raw * 0.25);
#elif HEATER_1_USES_AD595
return TEMP_AD595(raw);
#elif HEATER_1_USES_AD8495
Expand Down Expand Up @@ -1691,7 +1699,8 @@ void Temperature::updateTemperaturesFromRawValues() {
*/
void Temperature::init() {

TERN_(MAX6675_IS_MAX31865, max31865.begin(MAX31865_2WIRE)); // MAX31865_2WIRE, MAX31865_3WIRE, MAX31865_4WIRE
TERN_(MAX6675_0_IS_MAX31865, max31865_0.begin(MAX31865_2WIRE)); // MAX31865_2WIRE, MAX31865_3WIRE, MAX31865_4WIRE
TERN_(MAX6675_1_IS_MAX31865, max31865_1.begin(MAX31865_2WIRE));

#if EARLY_WATCHDOG
// Flag that the thermalManager should be running
Expand Down Expand Up @@ -2200,50 +2209,64 @@ void Temperature::disable_all_heaters() {
#define THERMOCOUPLE_MAX_ERRORS 15
#endif

int Temperature::read_max6675(
#if COUNT_6675 > 1
const uint8_t hindex
#endif
) {
#if COUNT_6675 == 1
constexpr uint8_t hindex = 0;
#else
// Needed to return the correct temp when this is called too soon
static uint16_t max6675_temp_previous[COUNT_6675] = { 0 };
#endif

static uint8_t max6675_errors[COUNT_6675] = { 0 };

int Temperature::read_max6675(TERN_(HAS_MULTI_6675, const uint8_t hindex/*=0*/)) {
#define MAX6675_HEAT_INTERVAL 250UL

#if MAX6675_IS_MAX31855
#if MAX6675_0_IS_MAX31855 || MAX6675_1_IS_MAX31855
static uint32_t max6675_temp = 2000;
#define MAX6675_ERROR_MASK 7
#define MAX6675_DISCARD_BITS 18
#define MAX6675_SPEED_BITS 3 // (_BV(SPR1)) // clock ÷ 64
#define MAX6675_SPEED_BITS 3 // (_BV(SPR1)) // clock ÷ 64
#elif HAS_MAX31865
static uint16_t max6675_temp = 2000; // From datasheet 16 bits D15-D0
#define MAX6675_ERROR_MASK 1 // D0 Bit not used
#define MAX6675_DISCARD_BITS 1 // Data is in D15-D1
#define MAX6675_SPEED_BITS 3 // (_BV(SPR1)) // clock ÷ 64
#else
static uint16_t max6675_temp = 2000;
#define MAX6675_ERROR_MASK 4
#define MAX6675_DISCARD_BITS 3
#define MAX6675_SPEED_BITS 2 // (_BV(SPR0)) // clock ÷ 16
#define MAX6675_SPEED_BITS 2 // (_BV(SPR0)) // clock ÷ 16
#endif

#if HAS_MULTI_6675
// Needed to return the correct temp when this is called between readings
static uint16_t max6675_temp_previous[COUNT_6675] = { 0 };
#define MAX6675_TEMP(I) max6675_temp_previous[I]
#define MAX6675_SEL(A,B) (hindex ? (B) : (A))
#define MAX6675_WRITE(V) do{ switch (hindex) { case 1: WRITE(MAX6675_SS2_PIN, V); break; default: WRITE(MAX6675_SS_PIN, V); } }while(0)
#define MAX6675_SET_OUTPUT() do{ switch (hindex) { case 1: SET_OUTPUT(MAX6675_SS2_PIN); break; default: SET_OUTPUT(MAX6675_SS_PIN); } }while(0)
#else
constexpr uint8_t hindex = 0;
#define MAX6675_TEMP(I) max6675_temp
#if MAX6675_1_IS_MAX31865
#define MAX6675_SEL(A,B) B
#else
#define MAX6675_SEL(A,B) A
#endif
#if HEATER_0_USES_MAX6675
#define MAX6675_WRITE(V) WRITE(MAX6675_SS_PIN, V)
#define MAX6675_SET_OUTPUT() SET_OUTPUT(MAX6675_SS_PIN)
#else
#define MAX6675_WRITE(V) WRITE(MAX6675_SS2_PIN, V)
#define MAX6675_SET_OUTPUT() SET_OUTPUT(MAX6675_SS2_PIN)
#endif
#endif

static uint8_t max6675_errors[COUNT_6675] = { 0 };

// Return last-read value between readings
static millis_t next_max6675_ms[COUNT_6675] = { 0 };
millis_t ms = millis();
if (PENDING(ms, next_max6675_ms[hindex]))
return int(
#if COUNT_6675 == 1
max6675_temp
#else
max6675_temp_previous[hindex] // Need to return the correct previous value
#endif
);

if (PENDING(ms, next_max6675_ms[hindex])) return int(MAX6675_TEMP(hindex));
next_max6675_ms[hindex] = ms + MAX6675_HEAT_INTERVAL;

#if MAX6675_IS_MAX31865
max6675_temp = int(max31865.temperature(MAX31865_SENSOR_OHMS, MAX31865_CALIBRATION_OHMS));
#if HAS_MAX31865
Adafruit_MAX31865 &maxref = MAX6675_SEL(max31865_0, max31865_1);
max6675_temp = int(maxref.temperature(
MAX6675_SEL(MAX31865_SENSOR_OHMS_0, MAX31865_SENSOR_OHMS_1),
MAX6675_SEL(MAX31865_CALIBRATION_OHMS_0, MAX31865_CALIBRATION_OHMS_1)
));
#endif

//
Expand All @@ -2254,39 +2277,24 @@ void Temperature::disable_all_heaters() {
spiInit(MAX6675_SPEED_BITS);
#endif

#if COUNT_6675 > 1
#define WRITE_MAX6675(V) do{ switch (hindex) { case 1: WRITE(MAX6675_SS2_PIN, V); break; default: WRITE(MAX6675_SS_PIN, V); } }while(0)
#define SET_OUTPUT_MAX6675() do{ switch (hindex) { case 1: SET_OUTPUT(MAX6675_SS2_PIN); break; default: SET_OUTPUT(MAX6675_SS_PIN); } }while(0)
#elif HEATER_1_USES_MAX6675
#define WRITE_MAX6675(V) WRITE(MAX6675_SS2_PIN, V)
#define SET_OUTPUT_MAX6675() SET_OUTPUT(MAX6675_SS2_PIN)
#else
#define WRITE_MAX6675(V) WRITE(MAX6675_SS_PIN, V)
#define SET_OUTPUT_MAX6675() SET_OUTPUT(MAX6675_SS_PIN)
#endif

SET_OUTPUT_MAX6675();
WRITE_MAX6675(LOW); // enable TT_MAX6675
MAX6675_SET_OUTPUT();
MAX6675_WRITE(LOW); // enable TT_MAX6675

DELAY_NS(100); // Ensure 100ns delay

// Read a big-endian temperature value
max6675_temp = 0;
for (uint8_t i = sizeof(max6675_temp); i--;) {
max6675_temp |= (
#if MAX6675_SEPARATE_SPI
max6675_spi.receive()
#else
spiRec()
#endif
);
max6675_temp |= TERN(MAX6675_SEPARATE_SPI, max6675_spi.receive(), spiRec());
if (i > 0) max6675_temp <<= 8; // shift left if not the last byte
}

WRITE_MAX6675(HIGH); // disable TT_MAX6675
MAX6675_WRITE(HIGH); // disable TT_MAX6675

const uint8_t fault_31865 = TERN1(HAS_MAX31865, maxref.readFault());

if (DISABLED(IGNORE_THERMOCOUPLE_ERRORS) && (max6675_temp & MAX6675_ERROR_MASK)) {
max6675_errors[hindex] += 1;
if (DISABLED(IGNORE_THERMOCOUPLE_ERRORS) && (max6675_temp & MAX6675_ERROR_MASK) && fault_31865) {
max6675_errors[hindex]++;
if (max6675_errors[hindex] > THERMOCOUPLE_MAX_ERRORS) {
SERIAL_ERROR_START();
SERIAL_ECHOPGM("Temp measurement error! ");
Expand All @@ -2298,18 +2306,29 @@ void Temperature::disable_all_heaters() {
SERIAL_ECHOLNPGM("Short to GND");
else if (max6675_temp & 4)
SERIAL_ECHOLNPGM("Short to VCC");
#elif HAS_MAX31865
if (fault_31865) {
maxref.clearFault();
SERIAL_ECHOPAIR("MAX31865 Fault :(", fault_31865, ") >>");
if (fault_31865 & MAX31865_FAULT_HIGHTHRESH)
SERIAL_ECHOLNPGM("RTD High Threshold");
else if (fault_31865 & MAX31865_FAULT_LOWTHRESH)
SERIAL_ECHOLNPGM("RTD Low Threshold");
else if (fault_31865 & MAX31865_FAULT_REFINLOW)
SERIAL_ECHOLNPGM("REFIN- > 0.85 x Bias");
else if (fault_31865 & MAX31865_FAULT_REFINHIGH)
SERIAL_ECHOLNPGM("REFIN- < 0.85 x Bias - FORCE- open");
else if (fault_31865 & MAX31865_FAULT_RTDINLOW)
SERIAL_ECHOLNPGM("REFIN- < 0.85 x Bias - FORCE- open");
else if (fault_31865 & MAX31865_FAULT_OVUV)
SERIAL_ECHOLNPGM("Under/Over voltage");
}
#else
SERIAL_ECHOLNPGM("MAX6675");
#endif

// Thermocouple open
max6675_temp = 4 * (
#if COUNT_6675 > 1
hindex ? HEATER_1_MAX6675_TMAX : HEATER_0_MAX6675_TMAX
#else
TERN(HEATER_1_USES_MAX6675, HEATER_1_MAX6675_TMAX, HEATER_0_MAX6675_TMAX)
#endif
);
max6675_temp = 4 * MAX6675_SEL(HEATER_0_MAX6675_TMAX, HEATER_1_MAX6675_TMAX);
}
else
max6675_temp >>= MAX6675_DISCARD_BITS;
Expand All @@ -2319,13 +2338,11 @@ void Temperature::disable_all_heaters() {
max6675_errors[hindex] = 0;
}

#if ENABLED(MAX6675_IS_MAX31855)
#if MAX6675_0_IS_MAX31855 || MAX6675_1_IS_MAX31855
if (max6675_temp & 0x00002000) max6675_temp |= 0xFFFFC000; // Support negative temperature
#endif

#if COUNT_6675 > 1
max6675_temp_previous[hindex] = max6675_temp;
#endif
MAX6675_TEMP(hindex) = max6675_temp;

return int(max6675_temp);
}
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/module/temperature.h
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,7 @@ class Temperature {
#if HAS_MAX6675
#define COUNT_6675 1 + BOTH(HEATER_0_USES_MAX6675, HEATER_1_USES_MAX6675)
#if COUNT_6675 > 1
#define HAS_MULTI_6675
#define HAS_MULTI_6675 1
#define READ_MAX6675(N) read_max6675(N)
#else
#define READ_MAX6675(N) read_max6675()
Expand Down
8 changes: 4 additions & 4 deletions buildroot/share/PlatformIO/variants/archim/variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ extern "C"{
*----------------------------------------------------------------------------*/

// Number of pins defined in PinDescription array
#define PINS_COUNT (79U)
#define NUM_DIGITAL_PINS (66U)
#define NUM_ANALOG_INPUTS (12U)
#define analogInputToDigitalPin(p) ((p < 12U) ? (p) + 54U : -1)
#define PINS_COUNT 79
#define NUM_DIGITAL_PINS 66
#define NUM_ANALOG_INPUTS 12
#define analogInputToDigitalPin(p) ((p < 12) ? (p) + 54 : -1)

#define digitalPinToPort(P) ( g_APinDescription[P].pPort )
#define digitalPinToBitMask(P) ( g_APinDescription[P].ulPin )
Expand Down
2 changes: 1 addition & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ HAS_L64XX = Arduino-L6470@0.8.0
src_filter=+<src/libs/L64XX> +<src/module/stepper/L64xx.cpp> +<src/gcode/feature/L6470>
NEOPIXEL_LED = Adafruit NeoPixel@1.5.0
src_filter=+<src/feature/leds/neopixel.cpp>
MAX6675_IS_MAX31865 = Adafruit MAX31865 library@~1.1.0
MAX6675_._IS_MAX31865 = Adafruit MAX31865 library@~1.1.0
USES_LIQUIDCRYSTAL = LiquidCrystal@1.5.0
USES_LIQUIDCRYSTAL_I2C = marcoschwartz/LiquidCrystal_I2C@1.1.4
USES_LIQUIDTWI2 = LiquidTWI2@1.2.7
Expand Down