diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index cf600b15846c..145c96197d0a 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -399,13 +399,18 @@ * * Temperature sensors available: * - * SPI RTD/Thermocouple Boards - NOTE: Ensure TEMP_n_CS_PIN is set in your pins file for each TEMP_SENSOR_n, as well as the - * ------- following for Software SPI: TEMP_n_MOSI_PIN (MAX31865 only), TEMP_n_MISO_PIN, TEMP_n_SCK_PIN. + * SPI RTD/Thermocouple Boards - IMPORTANT: Read the NOTE below! + * ------- * -5 : MAX31865 with Pt100/Pt1000, 2, 3, or 4-wire (only for sensors 0-1) * NOTE: You must uncomment/set the MAX31865_*_OHMS_n defines below. * -3 : MAX31855 with Thermocouple, -200°C to +700°C (only for sensors 0-1) * -2 : MAX6675 with Thermocouple, 0°C to +700°C (only for sensors 0-1) * + * NOTE: Ensure TEMP_n_CS_PIN is set in your pins file for each TEMP_SENSOR_n using an SPI Thermocouple. By default, + * Hardware SPI on the default serial bus is used. If you have also set TEMP_n_SCK_PIN and TEMP_n_MISO_PIN, + * Software SPI will be used on those ports instead. You can force Hardware SPI on the default bus in the + * Configuration_adv.h file. At this time, separate Hardware SPI buses for sensors are not supported. + * * Analog Themocouple Boards * ------- * -4 : AD8495 with Thermocouple @@ -496,10 +501,8 @@ #define DUMMY_THERMISTOR_999_VALUE 100 // Number of probe wires, and resistor values when using MAX31865 sensors (-5) on TEMP_SENSOR_0 / 1 -//#define MAX31865_SENSOR_WIRES_0 2 // Number of wires the connected probe uses, 2-4 (default: 2) //#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_WIRES_1 2 //#define MAX31865_SENSOR_OHMS_1 100 //#define MAX31865_CALIBRATION_OHMS_1 430 diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index ed1a672e4859..44896252bc2f 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -131,6 +131,17 @@ #define REDUNDANT_BETA 3950 // Beta value #endif +/** + * Configuration options for MAX Thermocouples (-2, -3, -5). + * FORCE_HW_SPI: Ignore SCK/MOSI/MISO pins and just use the CS pin & default SPI bus. + * MAX31865_WIRES: Set the number of wires for the probe connected to a MAX31865 board, 2-4. Default: 2 + */ +//#define TEMP_SENSOR_0_FORCE_HW_SPI +//#define TEMP_SENSOR_1_FORCE_HW_SPI +//#define MAX31865_SENSOR_WIRES_0 2 +//#define MAX31865_SENSOR_WIRES_1 2 + + // // Hephestos 2 24V heated bed upgrade kit. // https://store.bq.com/en/heated-bed-kit-hephestos2 diff --git a/Marlin/src/inc/Conditionals_post.h b/Marlin/src/inc/Conditionals_post.h index e188ebd21650..07857f531fe1 100644 --- a/Marlin/src/inc/Conditionals_post.h +++ b/Marlin/src/inc/Conditionals_post.h @@ -836,11 +836,11 @@ #endif // Software SPI - enable if MISO/SCK are defined. - #if PIN_EXISTS(TEMP_0_MISO) && PIN_EXISTS(TEMP_0_SCK) + #if PIN_EXISTS(TEMP_0_MISO) && PIN_EXISTS(TEMP_0_SCK) && DISABLED(TEMP_SENSOR_0_FORCE_HW_SPI) #if TEMP_SENSOR_0_IS_MAX31865 && !PIN_EXISTS(TEMP_0_MOSI) - #warning "TEMP_SENSOR_0 MAX31865 also needs TEMP_0_MOSI_PIN defined for Software SPI; defaulting to Hardware SPI." + #error "TEMP_SENSOR_0 MAX31865 requires TEMP_0_MOSI_PIN defined for Software SPI. To use Hardware SPI instead, undefine MISO/SCK or enable TEMP_SENSOR_0_FORCE_HW_SPI." #else - #define TEMP_SENSOR_0_USES_SW_SPI 1 + #define TEMP_SENSOR_0_HAS_SPI_PINS 1 #endif #endif @@ -905,11 +905,11 @@ #endif // Software SPI - enable if MISO/SCK are defined. - #if PIN_EXISTS(TEMP_1_MISO) && PIN_EXISTS(TEMP_1_SCK) + #if PIN_EXISTS(TEMP_1_MISO) && PIN_EXISTS(TEMP_1_SCK) && DISABLED(TEMP_SENSOR_1_FORCE_HW_SPI) #if TEMP_SENSOR_1_IS_MAX31865 && !PIN_EXISTS(TEMP_1_MOSI) - #warning "TEMP_SENSOR_1 MAX31865 also needs TEMP_1_MOSI_PIN defined for Software SPI; defaulting to Hardware SPI." + #error "TEMP_SENSOR_1 MAX31865 requires TEMP_1_MOSI_PIN defined for Software SPI. To use Hardware SPI instead, undefine MISO/SCK or enable TEMP_SENSOR_1_FORCE_HW_SPI." #else - #define TEMP_SENSOR_1_USES_SW_SPI 1 + #define TEMP_SENSOR_1_HAS_SPI_PINS 1 #endif #endif diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index d28a326913ac..d8ecafcafd09 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -89,19 +89,29 @@ #define HAS_MAXTC_LIBRARIES 1 #endif -// If we have a MAX TC with SCK and MISO pins defined, and we're not using an external library, -// the MAX TC will be read via Hardware SPI on a different pin. -#if (TEMP_SENSOR_IS_ANY_MAX_TC(0) && PINS_EXIST(TEMP_0_SCK, TEMP_0_MOSI)) - #define TEMP_SENSOR_0_USES_SEPARATE_SPI 1 -#endif -#if (TEMP_SENSOR_IS_ANY_MAX_TC(1) && PINS_EXIST(TEMP_1_SCK, TEMP_1_MOSI)) - #define TEMP_SENSOR_1_USES_SEPARATE_SPI 1 +// If we have a MAX TC with SCK and MISO pins defined, it's either on a separate/dedicated Hardware +// SPI bus, or some pins for Software SPI. Alternate Hardware SPI buses are not supported yet, so +// your SPI options are: +// +// 1. Only CS pin(s) defined: Hardware SPI on the default bus (usually the SD card SPI). +// 2. CS, MISO, and SCK pins defined: Software SPI on a separate bus, as defined by MISO, SCK. +// 3. CS, MISO, and SCK pins w/ FORCE_HW_SPI: Hardware SPI on the default bus, ignoring MISO, SCK. +// +#if TEMP_SENSOR_IS_ANY_MAX_TC(0) && TEMP_SENSOR_0_HAS_SPI_PINS && DISABLED(TEMP_SENSOR_0_FORCE_HW_SPI) + #define TEMP_SENSOR_0_USES_SW_SPI 1 #endif +#if TEMP_SENSOR_IS_ANY_MAX_TC(1) && TEMP_SENSOR_1_HAS_SPI_PINS && DISABLED(TEMP_SENSOR_1_FORCE_HW_SPI) + #define TEMP_SENSOR_1_USES_SW_SPI 1 + // Two sensors using the same Software SPI bus + #if TEMP_SENSOR_0_USES_SW_SPI && TEMP_0_SCK_PIN == TEMP_1_SCK_PIN && TEMP_0_MISO_PIN == TEMP_1_MISO_PIN + #define TEMP_SENSOR_SAME_SPI_BUS 1 + #endif +#endif -#if TEMP_SENSOR_0_USES_SEPARATE_SPI || TEMP_SENSOR_1_USES_SEPARATE_SPI +#if TEMP_SENSOR_0_USES_SW_SPI || TEMP_SENSOR_1_USES_SW_SPI #include "../libs/private_spi.h" - #define HAS_MAXTC_SEPARATE_SPI 1 + #define HAS_MAXTC_SW_SPI 1 #endif #if ENABLED(PID_EXTRUSION_SCALING) @@ -189,13 +199,22 @@ const char str_t_thermal_runaway[] PROGMEM = STR_T_THERMAL_RUNAWAY, // #if HAS_MAX_TC - #if HAS_MAXTC_SEPARATE_SPI - //TODO: what about multi_tc? - template SoftSPI SPIclass::softSPI; - SPIclass max_tc_spi; + #if !HAS_MAXTC_LIBRARIES + // Initialize SoftSPI for non-lib Software SPI; Libraries take care of it themselves. + #if TEMP_SENSOR_0_USES_SW_SPI + template SoftSPI SPIclass::softSPI; + SPIclass max_tc_spi_0; + #endif + #if TEMP_SENSOR_1_USES_SW_SPI + #if TEMP_SENSOR_SAME_SPI_BUS + SPIclass &max_tc_spi_1 = max_tc_spi_0; + #else + template SoftSPI SPIclass::softSPI; + SPIclass max_tc_spi_1; + #endif + #endif #endif - #define MAXTC_INIT(n, M) \ MAX##M max##M##_##n = MAX##M( \ TEMP_##n##_CS_PIN \ @@ -226,6 +245,7 @@ const char str_t_thermal_runaway[] PROGMEM = STR_T_THERMAL_RUNAWAY, #endif // MAX31865 always uses a library, unlike '55 & 6675 + // FIXME: The MAX31865 lib should use SoftSPI/MarlinSerial instead of SPI/raw pin manipulation #if HAS_MAX31865 #define _MAX31865_0_SW TEMP_SENSOR_0_USES_SW_SPI #define _MAX31865_1_SW TEMP_SENSOR_1_USES_SW_SPI @@ -2189,8 +2209,13 @@ void Temperature::init() { INIT_FAN_PIN(CONTROLLER_FAN_PIN); #endif - #if HAS_MAXTC_SEPARATE_SPI - max_tc_spi.init(); + #if !HAS_MAXTC_LIBRARIES + #if TEMP_SENSOR_0_USES_SW_SPI + max_tc_spi_0.init(); + #endif + #if TEMP_SENSOR_1_USES_SW_SPI && !TEMP_SENSOR_SAME_SPI_BUS + max_tc_spi_1.init(); + #endif #endif HAL_adc_init(); @@ -2618,7 +2643,7 @@ void Temperature::disable_all_heaters() { static celsius_t max_tc_temp_previous[MAX_TC_COUNT] = { 0 }; #define THERMO_TEMP(I) max_tc_temp_previous[I] #define THERMO_SEL(A,B) (hindex ? (B) : (A)) - #define MAXTC_WRITE(V) do{ switch (hindex) { case 1: WRITE(TEMP_1_CS_PIN, V); break; default: WRITE(TEMP_0_CS_PIN, V); } }while(0) + #define MAXTC_CS_WRITE(V) do{ switch (hindex) { case 1: WRITE(TEMP_1_CS_PIN, V); break; default: WRITE(TEMP_0_CS_PIN, V); } }while(0) #else // When we have only 1 max tc, THERMO_SEL will pick the appropriate sensor // variable, and MAXTC_*() macros will be hardcoded to the correct CS pin. @@ -2626,13 +2651,21 @@ void Temperature::disable_all_heaters() { #define THERMO_TEMP(I) max_tc_temp #if TEMP_SENSOR_IS_ANY_MAX_TC(0) #define THERMO_SEL(A,B) A - #define MAXTC_WRITE(V) WRITE(TEMP_0_CS_PIN, V) + #define MAXTC_CS_WRITE(V) WRITE(TEMP_0_CS_PIN, V) #else #define THERMO_SEL(A,B) B - #define MAXTC_WRITE(V) WRITE(TEMP_1_CS_PIN, V) + #define MAXTC_CS_WRITE(V) WRITE(TEMP_1_CS_PIN, V) #endif #endif + #if TEMP_SENSOR_0_USES_SW_SPI && TEMP_SENSOR_1_USES_SW_SPI + #define THERMO_SPI_SEL(A,B) (hindex ? (B) : (A)) + #elif TEMP_SENSOR_0_USES_SW_SPI + #define THERMO_SPI_SEL(A,B) A + #elif TEMP_SENSOR_1_USES_SW_SPI + #define THERMO_SPI_SEL(A,B) B + #endif + static uint8_t max_tc_errors[MAX_TC_COUNT] = { 0 }; // Return last-read value between readings @@ -2644,25 +2677,30 @@ void Temperature::disable_all_heaters() { max_tc_temp = 0; #if !HAS_MAXTC_LIBRARIES - #if !HAS_MAXTC_SEPARATE_SPI - // Initialize SPI using the default SPI bus. + #if !HAS_MAXTC_SW_SPI + // Initialize SPI using the default Hardware SPI bus. // FIXME: spiBegin, spiRec and spiInit doesn't work when soft spi is used. spiBegin(); spiInit(MAX_TC_SPEED_BITS); #endif - // Read a big-endian temperature value without using a library - MAXTC_WRITE(LOW); // enable MAXTC - DELAY_NS(100); // Ensure 100ns delay + MAXTC_CS_WRITE(LOW); // enable MAXTC + DELAY_NS(100); // Ensure 100ns delay + // Read a big-endian temperature value without using a library for (uint8_t i = sizeof(max_tc_temp); i--;) { - max_tc_temp |= TERN(HAS_MAXTC_SEPARATE_SPI, max_tc_spi.receive(), spiRec()); + max_tc_temp |= ( + #if HAS_MAXTC_SW_SPI + THERMO_SPI_SEL(max_tc_spi_0, max_tc_spi_1).receive() + #else + spiRec() + #endif + ); if (i > 0) max_tc_temp <<= 8; // shift left if not the last byte } - MAXTC_WRITE(HIGH); // disable MAXTC + MAXTC_CS_WRITE(HIGH); // disable MAXTC #else - // TODO: a lot of this is references to the GadgetAngel ModM versions... #if HAS_MAX6675_LIBRARY MAX6675 &max6675ref = THERMO_SEL(max6675_0, max6675_1); max_tc_temp = max6675ref.readRaw16();