|
|
@ -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 |
|
|
|
Adafruit_MAX31865 max31865 = Adafruit_MAX31865(MAX31865_CS_PIN |
|
|
|
#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 // For software SPI also set MOSI/MISO/SCK
|
|
|
|
, MAX31865_MISO_PIN |
|
|
|
, MAX31865_SCK_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 |
|
|
|
#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" |
|
|
@ -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 |
|
|
@ -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 |
|
|
@ -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
|
|
|
@ -2200,27 +2209,19 @@ 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
|
|
|
|
#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 |
|
|
@ -2228,22 +2229,44 @@ void Temperature::disable_all_heaters() { |
|
|
|
#define MAX6675_SPEED_BITS 2 // (_BV(SPR0)) // clock ÷ 16
|
|
|
|
#endif |
|
|
|
|
|
|
|
// 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 |
|
|
|
#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 |
|
|
|
max6675_temp_previous[hindex] // Need to return the correct previous value
|
|
|
|
#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(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 |
|
|
|
|
|
|
|
//
|
|
|
@ -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
|
|
|
|
|
|
|
|
if (DISABLED(IGNORE_THERMOCOUPLE_ERRORS) && (max6675_temp & MAX6675_ERROR_MASK)) { |
|
|
|
max6675_errors[hindex] += 1; |
|
|
|
const uint8_t fault_31865 = TERN1(HAS_MAX31865, maxref.readFault()); |
|
|
|
|
|
|
|
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! "); |
|
|
@ -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; |
|
|
@ -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); |
|
|
|
} |
|
|
|