From 346daa2aafefacbeb2f4c72ffc2fd625cfef4eb5 Mon Sep 17 00:00:00 2001 From: Giuliano Zaro <3684609+GMagician@users.noreply.github.com> Date: Wed, 18 Nov 2020 08:27:21 +0100 Subject: [PATCH] SMUFF (MMU2 clone) support (#19912) --- Marlin/Configuration.h | 34 +- Marlin/Configuration_adv.h | 60 ++- Marlin/src/HAL/LPC1768/inc/SanityCheck.h | 4 +- Marlin/src/MarlinCore.cpp | 21 +- Marlin/src/feature/{snmm.cpp => mmu/mmu.cpp} | 4 +- Marlin/src/feature/{snmm.h => mmu/mmu.h} | 0 .../mmu2-serial-protocol.md} | 0 Marlin/src/feature/{mmu2 => mmu}/mmu2.cpp | 474 +++++++++--------- Marlin/src/feature/{mmu2 => mmu}/mmu2.h | 22 +- Marlin/src/gcode/config/M220.cpp | 4 +- Marlin/src/gcode/control/T.cpp | 8 +- Marlin/src/gcode/feature/pause/M701_M702.cpp | 16 +- Marlin/src/gcode/feature/prusa_MMU2/M403.cpp | 6 +- Marlin/src/gcode/gcode.cpp | 2 +- Marlin/src/gcode/gcode.h | 4 +- Marlin/src/gcode/parser.cpp | 2 +- Marlin/src/inc/Conditionals_LCD.h | 42 +- Marlin/src/inc/SanityCheck.h | 140 +++--- Marlin/src/lcd/menu/menu_main.cpp | 2 +- Marlin/src/lcd/menu/menu_mmu2.cpp | 34 +- Marlin/src/module/settings.cpp | 243 ++++----- Marlin/src/module/stepper/indirection.h | 7 +- Marlin/src/module/tool_change.cpp | 16 +- Marlin/src/pins/lpc1768/pins_MKS_SBASE.h | 4 +- Marlin/src/pins/pins.h | 7 +- Marlin/src/pins/pins_postprocess.h | 10 +- Marlin/src/pins/stm32f4/pins_BTT_GTR_V1_0.h | 4 +- buildroot/tests/mega2560-tests | 18 +- platformio.ini | 10 +- 29 files changed, 602 insertions(+), 596 deletions(-) rename Marlin/src/feature/{snmm.cpp => mmu/mmu.cpp} (95%) rename Marlin/src/feature/{snmm.h => mmu/mmu.h} (100%) rename Marlin/src/feature/{mmu2/serial-protocol.md => mmu/mmu2-serial-protocol.md} (100%) rename Marlin/src/feature/{mmu2 => mmu}/mmu2.cpp (75%) rename Marlin/src/feature/{mmu2 => mmu}/mmu2.h (84%) diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index be512e371cba..4521895fdce2 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -158,33 +158,19 @@ #endif /** - * Průša MK2 Single Nozzle Multi-Material Multiplexer, and variants. - * - * This device allows one stepper driver on a control board to drive - * two to eight stepper motors, one at a time, in a manner suitable - * for extruders. - * - * This option only allows the multiplexer to switch on tool-change. - * Additional options to configure custom E moves are pending. - */ -//#define MK2_MULTIPLEXER -#if ENABLED(MK2_MULTIPLEXER) - // Override the default DIO selector pins here, if needed. - // Some pins files may provide defaults for these pins. - //#define E_MUX0_PIN 40 // Always Required - //#define E_MUX1_PIN 42 // Needed for 3 to 8 inputs - //#define E_MUX2_PIN 44 // Needed for 5 to 8 inputs -#endif - -/** - * Průša Multi-Material Unit v2 + * Multi-Material Unit + * Set to one of these predefined models: * - * Requires NOZZLE_PARK_FEATURE to park print head in case MMU unit fails. - * Requires EXTRUDERS = 5 + * PRUSA_MMU1 : Průša MMU1 (The "multiplexer" version) + * PRUSA_MMU2 : Průša MMU2 + * PRUSA_MMU2S : Průša MMU2S (Requires MK3S extruder with motion sensor, EXTRUDERS = 5) + * SMUFF_EMU_MMU2 : Technik Gegg SMUFF (Průša MMU2 emulation mode) + * SMUFF_EMU_MMU2S : Technik Gegg SMUFF (Průša MMU2S emulation mode) * - * For additional configuration see Configuration_adv.h + * Requires NOZZLE_PARK_FEATURE to park print head in case MMU unit fails. + * See additional options in Configuration_adv.h. */ -//#define PRUSA_MMU2 +//#define MMU_MODEL PRUSA_MMU2 // A dual extruder that uses a single stepper motor //#define SWITCHING_EXTRUDER diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index fa7323a66642..68d31ceaff9f 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -3532,11 +3532,24 @@ #endif /** - * Průša Multi-Material Unit v2 + * Průša Multi-Material Unit (MMU) * Enable in Configuration.h + * + * These devices allow a single stepper driver on the board to drive + * multi-material feeders with any number of stepper motors. */ -#if ENABLED(PRUSA_MMU2) - +#if HAS_PRUSA_MMU1 + /** + * This option only allows the multiplexer to switch on tool-change. + * Additional options to configure custom E moves are pending. + * + * Override the default DIO selector pins here, if needed. + * Some pins files may provide defaults for these pins. + */ + //#define E_MUX0_PIN 40 // Always Required + //#define E_MUX1_PIN 42 // Needed for 3 to 8 inputs + //#define E_MUX2_PIN 44 // Needed for 5 to 8 inputs +#elif HAS_PRUSA_MMU2 // Serial port used for communication with MMU2. // For AVR enable the UART port used for the MMU. (e.g., mmuSerial) // For 32-bit boards check your HAL for available serial ports. (e.g., Serial2) @@ -3554,7 +3567,7 @@ // Add an LCD menu for MMU2 //#define MMU2_MENUS - #if ENABLED(MMU2_MENUS) + #if EITHER(MMU2_MENUS, HAS_PRUSA_MMU2S) // Settings for filament load / unload from the LCD menu. // This is for Průša MK3-style extruders. Customize for your hardware. #define MMU2_FILAMENTCHANGE_EJECT_FEED 80.0 @@ -3579,29 +3592,12 @@ { -50.0, 2000 } #endif - /** - * MMU Extruder Sensor - * - * Support for a Průša (or other) IR Sensor to detect filament near the extruder - * and make loading more reliable. Suitable for an extruder equipped with a filament - * sensor less than 38mm from the gears. - * - * During loading the extruder will stop when the sensor is triggered, then do a last - * move up to the gears. If no filament is detected, the MMU2 can make some more attempts. - * If all attempts fail, a filament runout will be triggered. - */ - //#define MMU_EXTRUDER_SENSOR - #if ENABLED(MMU_EXTRUDER_SENSOR) - #define MMU_LOADING_ATTEMPTS_NR 5 // max. number of attempts to load filament if first load fail - #endif - /** * Using a sensor like the MMU2S * This mode requires a MK3S extruder with a sensor at the extruder idler, like the MMU2S. * See https://help.prusa3d.com/en/guide/3b-mk3s-mk2-5s-extruder-upgrade_41560, step 11 */ - //#define PRUSA_MMU2_S_MODE - #if ENABLED(PRUSA_MMU2_S_MODE) + #if HAS_PRUSA_MMU2S #define MMU2_C0_RETRY 5 // Number of retries (total time = timeout*retries) #define MMU2_CAN_LOAD_FEEDRATE 800 // (mm/min) @@ -3617,11 +3613,29 @@ #define MMU2_CAN_LOAD_INCREMENT_SEQUENCE \ { -MMU2_CAN_LOAD_INCREMENT, MMU2_CAN_LOAD_FEEDRATE } + #else + + /** + * MMU1 Extruder Sensor + * + * Support for a Průša (or other) IR Sensor to detect filament near the extruder + * and make loading more reliable. Suitable for an extruder equipped with a filament + * sensor less than 38mm from the gears. + * + * During loading the extruder will stop when the sensor is triggered, then do a last + * move up to the gears. If no filament is detected, the MMU2 can make some more attempts. + * If all attempts fail, a filament runout will be triggered. + */ + //#define MMU_EXTRUDER_SENSOR + #if ENABLED(MMU_EXTRUDER_SENSOR) + #define MMU_LOADING_ATTEMPTS_NR 5 // max. number of attempts to load filament if first load fail + #endif + #endif //#define MMU2_DEBUG // Write debug info to serial output -#endif // PRUSA_MMU2 +#endif // HAS_PRUSA_MMU2 /** * Advanced Print Counter settings diff --git a/Marlin/src/HAL/LPC1768/inc/SanityCheck.h b/Marlin/src/HAL/LPC1768/inc/SanityCheck.h index 8b7d27742d40..21d149fcafe6 100644 --- a/Marlin/src/HAL/LPC1768/inc/SanityCheck.h +++ b/Marlin/src/HAL/LPC1768/inc/SanityCheck.h @@ -97,8 +97,8 @@ static_assert(DISABLED(BAUD_RATE_GCODE), "BAUD_RATE_GCODE is not yet supported o #define IS_RX0(P) (P == P0_03) #if IS_TX0(TMC_SW_MISO) || IS_RX0(TMC_SW_MOSI) #error "Serial port pins (0) conflict with Trinamic SPI pins!" - #elif ENABLED(MK2_MULTIPLEXER) && (IS_TX0(E_MUX1_PIN) || IS_RX0(E_MUX0_PIN)) - #error "Serial port pins (0) conflict with MK2 multiplexer pins!" + #elif HAS_PRUSA_MMU1 && (IS_TX0(E_MUX1_PIN) || IS_RX0(E_MUX0_PIN)) + #error "Serial port pins (0) conflict with Multi-Material-Unit multiplexer pins!" #elif (AXIS_HAS_SPI(X) && IS_TX0(X_CS_PIN)) || (AXIS_HAS_SPI(Y) && IS_RX0(Y_CS_PIN)) #error "Serial port pins (0) conflict with X/Y axis SPI pins!" #endif diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index acd1321af45e..60765c98331e 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -213,8 +213,8 @@ #include "feature/controllerfan.h" #endif -#if ENABLED(PRUSA_MMU2) - #include "feature/mmu2/mmu2.h" +#if HAS_PRUSA_MMU2 + #include "feature/mmu/mmu2.h" #endif #if HAS_L64XX @@ -713,9 +713,7 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) { TERN_(HAS_FILAMENT_SENSOR, runout.run()); // Run HAL idle tasks - #ifdef HAL_IDLETASK - HAL_idletask(); - #endif + TERN_(HAL_IDLETASK, HAL_idletask()); // Check network connection TERN_(HAS_ETHERNET, ethernet.check()); @@ -772,7 +770,7 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) { #endif // Update the Průša MMU2 - TERN_(PRUSA_MMU2, mmu2.mmu_loop()); + TERN_(HAS_PRUSA_MMU2, mmu2.mmu_loop()); // Handle Joystick jogging TERN_(POLL_JOG, joystick.inject_jog_moves()); @@ -780,9 +778,8 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) { // Direct Stepping TERN_(DIRECT_STEPPING, page_manager.write_responses()); - #if HAS_TFT_LVGL_UI - LV_TASK_HANDLER(); - #endif + // Update the LVGL interface + TERN_(HAS_TFT_LVGL_UI, LV_TASK_HANDLER()); } /** @@ -1187,8 +1184,8 @@ void setup() { SETUP_RUN(caselight.update_brightness()); #endif - #if ENABLED(MK2_MULTIPLEXER) - SETUP_LOG("MK2_MULTIPLEXER"); + #if HAS_PRUSA_MMU1 + SETUP_LOG("Prusa MMU1"); SET_OUTPUT(E_MUX0_PIN); SET_OUTPUT(E_MUX1_PIN); SET_OUTPUT(E_MUX2_PIN); @@ -1268,7 +1265,7 @@ void setup() { SETUP_RUN(test_tmc_connection(true, true, true, true)); #endif - #if ENABLED(PRUSA_MMU2) + #if HAS_PRUSA_MMU2 SETUP_RUN(mmu2.init()); #endif diff --git a/Marlin/src/feature/snmm.cpp b/Marlin/src/feature/mmu/mmu.cpp similarity index 95% rename from Marlin/src/feature/snmm.cpp rename to Marlin/src/feature/mmu/mmu.cpp index 25723f7b38c3..2b48823ee799 100644 --- a/Marlin/src/feature/snmm.cpp +++ b/Marlin/src/feature/mmu/mmu.cpp @@ -22,7 +22,7 @@ #include "../inc/MarlinConfig.h" -#if ENABLED(MK2_MULTIPLEXER) +#if HAS_PRUSA_MMU1 #include "../module/stepper.h" @@ -35,4 +35,4 @@ void select_multiplexed_stepper(const uint8_t e) { safe_delay(100); } -#endif // MK2_MULTIPLEXER +#endif // HAS_PRUSA_MMU1 diff --git a/Marlin/src/feature/snmm.h b/Marlin/src/feature/mmu/mmu.h similarity index 100% rename from Marlin/src/feature/snmm.h rename to Marlin/src/feature/mmu/mmu.h diff --git a/Marlin/src/feature/mmu2/serial-protocol.md b/Marlin/src/feature/mmu/mmu2-serial-protocol.md similarity index 100% rename from Marlin/src/feature/mmu2/serial-protocol.md rename to Marlin/src/feature/mmu/mmu2-serial-protocol.md diff --git a/Marlin/src/feature/mmu2/mmu2.cpp b/Marlin/src/feature/mmu/mmu2.cpp similarity index 75% rename from Marlin/src/feature/mmu2/mmu2.cpp rename to Marlin/src/feature/mmu/mmu2.cpp index d76476e719f3..61adcfca72a7 100644 --- a/Marlin/src/feature/mmu2/mmu2.cpp +++ b/Marlin/src/feature/mmu/mmu2.cpp @@ -22,7 +22,7 @@ #include "../../inc/MarlinConfig.h" -#if ENABLED(PRUSA_MMU2) +#if HAS_PRUSA_MMU2 #include "mmu2.h" #include "../../lcd/menu/menu_mmu2.h" @@ -94,7 +94,7 @@ MMU2 mmu2; #define mmuSerial MMU2_SERIAL bool MMU2::enabled, MMU2::ready, MMU2::mmu_print_saved; -#if ENABLED(PRUSA_MMU2_S_MODE) +#if HAS_PRUSA_MMU2S bool MMU2::mmu2s_triggered; #endif uint8_t MMU2::cmd, MMU2::cmd_arg, MMU2::last_cmd, MMU2::extruder; @@ -105,23 +105,19 @@ int16_t MMU2::version = -1, MMU2::buildnr = -1; millis_t MMU2::prev_request, MMU2::prev_P0_request; char MMU2::rx_buffer[MMU_RX_SIZE], MMU2::tx_buffer[MMU_TX_SIZE]; -#if BOTH(HAS_LCD_MENU, MMU2_MENUS) - - struct E_Step { - float extrude; //!< extrude distance in mm - feedRate_t feedRate; //!< feed rate in mm/s - }; - - static constexpr E_Step - ramming_sequence[] PROGMEM = { MMU2_RAMMING_SEQUENCE } - , load_to_nozzle_sequence[] PROGMEM = { MMU2_LOAD_TO_NOZZLE_SEQUENCE } - #if ENABLED(PRUSA_MMU2_S_MODE) - , can_load_sequence[] PROGMEM = { MMU2_CAN_LOAD_SEQUENCE } - , can_load_increment_sequence[] PROGMEM = { MMU2_CAN_LOAD_INCREMENT_SEQUENCE } - #endif - ; - -#endif // MMU2_MENUS +struct E_Step { + float extrude; //!< extrude distance in mm + feedRate_t feedRate; //!< feed rate in mm/s +}; + +static constexpr E_Step + ramming_sequence[] PROGMEM = { MMU2_RAMMING_SEQUENCE } + , load_to_nozzle_sequence[] PROGMEM = { MMU2_LOAD_TO_NOZZLE_SEQUENCE } + #if HAS_PRUSA_MMU2S + , can_load_sequence[] PROGMEM = { MMU2_CAN_LOAD_SEQUENCE } + , can_load_increment_sequence[] PROGMEM = { MMU2_CAN_LOAD_INCREMENT_SEQUENCE } + #endif +; MMU2::MMU2() { rx_buffer[0] = '\0'; @@ -162,7 +158,7 @@ uint8_t MMU2::get_current_tool() { return extruder == MMU2_NO_TOOL ? -1 : extruder; } -#if EITHER(PRUSA_MMU2_S_MODE, MMU_EXTRUDER_SENSOR) +#if EITHER(HAS_PRUSA_MMU2S, MMU_EXTRUDER_SENSOR) #define FILAMENT_PRESENT() (READ(FIL_RUNOUT1_PIN) != FIL_RUNOUT1_STATE) #endif @@ -188,7 +184,7 @@ void MMU2::mmu_loop() { case -2: if (rx_ok()) { - sscanf(rx_buffer, "%uok\n", &version); + sscanf(rx_buffer, "%huok\n", &version); DEBUG_ECHOLNPAIR("MMU => ", version, "\nMMU <= 'S2'"); @@ -199,7 +195,7 @@ void MMU2::mmu_loop() { case -3: if (rx_ok()) { - sscanf(rx_buffer, "%uok\n", &buildnr); + sscanf(rx_buffer, "%huok\n", &buildnr); DEBUG_ECHOLNPAIR("MMU => ", buildnr); @@ -242,7 +238,7 @@ void MMU2::mmu_loop() { enabled = true; state = 1; - TERN_(PRUSA_MMU2_S_MODE, mmu2s_triggered = false); + TERN_(HAS_PRUSA_MMU2S, mmu2s_triggered = false); } break; @@ -307,7 +303,7 @@ void MMU2::mmu_loop() { state = 2; // wait for response } - TERN_(PRUSA_MMU2_S_MODE, check_filament()); + TERN_(HAS_PRUSA_MMU2S, check_filament()); break; case 2: // response to command P0 @@ -324,7 +320,7 @@ void MMU2::mmu_loop() { else if (ELAPSED(millis(), prev_request + MMU_P0_TIMEOUT)) // Resend request after timeout (3s) state = 1; - TERN_(PRUSA_MMU2_S_MODE, check_filament()); + TERN_(HAS_PRUSA_MMU2S, check_filament()); break; case 3: // response to mmu commands @@ -340,9 +336,9 @@ void MMU2::mmu_loop() { #endif if (rx_ok()) { - // Response to C0 mmu command in PRUSA_MMU2_S_MODE + // Response to C0 mmu command in MMU2S model bool can_reset = true; - #if ENABLED(PRUSA_MMU2_S_MODE) + #if HAS_PRUSA_MMU2S if (!mmu2s_triggered && last_cmd == MMU_CMD_C0) { can_reset = false; // MMU ok received but filament sensor not triggered, retrying... @@ -367,7 +363,7 @@ void MMU2::mmu_loop() { } state = 1; } - TERN_(PRUSA_MMU2_S_MODE, check_filament()); + TERN_(HAS_PRUSA_MMU2S, check_filament()); break; } } @@ -487,7 +483,7 @@ static void mmu2_not_responding() { BUZZ(100, 659); } -#if ENABLED(PRUSA_MMU2_S_MODE) +#if HAS_PRUSA_MMU2S bool MMU2::load_to_gears() { command(MMU_CMD_C0); @@ -541,33 +537,38 @@ static void mmu2_not_responding() { * Tc Load to nozzle after filament was prepared by Tx and extruder nozzle is already heated. */ void MMU2::tool_change(const char* special) { - - if (!enabled) return; - - #if ENABLED(MMU2_MENUS) + if (!enabled) return; set_runout_valid(false); switch (*special) { case '?': { - uint8_t index = mmu2_choose_filament(); - while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100); - load_filament_to_nozzle(index); + #if ENABLED(MMU2_MENUS) + const uint8_t index = mmu2_choose_filament(); + while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100); + load_filament_to_nozzle(index); + #else + BUZZ(400, 40); + #endif } break; case 'x': { - planner.synchronize(); - uint8_t index = mmu2_choose_filament(); - DISABLE_AXIS_E0(); - command(MMU_CMD_T0 + index); - manage_response(true, true); - - if (load_to_gears()) { - mmu_loop(); - ENABLE_AXIS_E0(); - extruder = index; - active_extruder = 0; - } + #if ENABLED(MMU2_MENUS) + planner.synchronize(); + const uint8_t index = mmu2_choose_filament(); + DISABLE_AXIS_E0(); + command(MMU_CMD_T0 + index); + manage_response(true, true); + + if (load_to_gears()) { + mmu_loop(); + ENABLE_AXIS_E0(); + extruder = index; + active_extruder = 0; + } + #else + BUZZ(400, 40); + #endif } break; case 'c': { @@ -577,8 +578,6 @@ static void mmu2_not_responding() { } set_runout_valid(true); - - #endif // MMU2_MENUS } #elif ENABLED(MMU_EXTRUDER_SENSOR) @@ -628,20 +627,23 @@ static void mmu2_not_responding() { void MMU2::tool_change(const char* special) { if (!enabled) return; - #if ENABLED(MMU2_MENUS) - - set_runout_valid(false); + set_runout_valid(false); - switch (*special) { - case '?': { - DEBUG_ECHOLNPGM("case ?\n"); + switch (*special) { + case '?': { + DEBUG_ECHOLNPGM("case ?\n"); + #if ENABLED(MMU2_MENUS) uint8_t index = mmu2_choose_filament(); while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100); load_filament_to_nozzle(index); - } break; + #else + BUZZ(400, 40); + #endif + } break; - case 'x': { - DEBUG_ECHOLNPGM("case x\n"); + case 'x': { + DEBUG_ECHOLNPGM("case x\n"); + #if ENABLED(MMU2_MENUS) planner.synchronize(); uint8_t index = mmu2_choose_filament(); DISABLE_AXIS_E0(); @@ -654,18 +656,19 @@ static void mmu2_not_responding() { ENABLE_AXIS_E0(); extruder = index; active_extruder = 0; - } break; - - case 'c': { - DEBUG_ECHOLNPGM("case c\n"); - while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100); - execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence)); - } break; - } + #else + BUZZ(400, 40); + #endif + } break; - set_runout_valid(true); + case 'c': { + DEBUG_ECHOLNPGM("case c\n"); + while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100); + execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence)); + } break; + } - #endif // MMU2_MENUS + set_runout_valid(true); } void MMU2::mmu_continue_loading() { @@ -682,68 +685,74 @@ static void mmu2_not_responding() { mmu_idl_sens = 0; } -#elif DISABLED(MMU_EXTRUDER_SENSOR) && DISABLED(PRUSA_MMU2_S_MODE) +#else // !HAS_PRUSA_MMU2S && !MMU_EXTRUDER_SENSOR -/** - * Handle tool change - */ -void MMU2::tool_change(const uint8_t index) { - if (!enabled) return; - - set_runout_valid(false); + /** + * Handle tool change + */ + void MMU2::tool_change(const uint8_t index) { + if (!enabled) return; - if (index != extruder) { - DISABLE_AXIS_E0(); - ui.status_printf_P(0, GET_TEXT(MSG_MMU2_LOADING_FILAMENT), int(index + 1)); - command(MMU_CMD_T0 + index); - manage_response(true, true); - command(MMU_CMD_C0); - extruder = index; //filament change is finished - active_extruder = 0; - ENABLE_AXIS_E0(); - SERIAL_ECHO_START(); - SERIAL_ECHOLNPAIR(STR_ACTIVE_EXTRUDER, int(extruder)); - ui.reset_status(); - } + set_runout_valid(false); - set_runout_valid(true); -} + if (index != extruder) { + DISABLE_AXIS_E0(); + ui.status_printf_P(0, GET_TEXT(MSG_MMU2_LOADING_FILAMENT), int(index + 1)); + command(MMU_CMD_T0 + index); + manage_response(true, true); + command(MMU_CMD_C0); + extruder = index; //filament change is finished + active_extruder = 0; + ENABLE_AXIS_E0(); + SERIAL_ECHO_START(); + SERIAL_ECHOLNPAIR(STR_ACTIVE_EXTRUDER, int(extruder)); + ui.reset_status(); + } -/** - * Handle special T?/Tx/Tc commands - * - * T? Gcode to extrude shouldn't have to follow, load to extruder wheels is done automatically - * Tx Same as T?, except nozzle doesn't have to be preheated. Tc must be placed after extruder nozzle is preheated to finish filament load. - * Tc Load to nozzle after filament was prepared by Tx and extruder nozzle is already heated. - */ -void MMU2::tool_change(const char* special) { - if (!enabled) return; + set_runout_valid(true); + } - #if ENABLED(MMU2_MENUS) + /** + * Handle special T?/Tx/Tc commands + * + * T? Gcode to extrude shouldn't have to follow, load to extruder wheels is done automatically + * Tx Same as T?, except nozzle doesn't have to be preheated. Tc must be placed after extruder nozzle is preheated to finish filament load. + * Tc Load to nozzle after filament was prepared by Tx and extruder nozzle is already heated. + */ + void MMU2::tool_change(const char* special) { + if (!enabled) return; set_runout_valid(false); switch (*special) { case '?': { DEBUG_ECHOLNPGM("case ?\n"); - uint8_t index = mmu2_choose_filament(); - while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100); - load_filament_to_nozzle(index); + #if ENABLED(MMU2_MENUS) + uint8_t index = mmu2_choose_filament(); + while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100); + load_filament_to_nozzle(index); + #else + BUZZ(400, 40); + #endif } break; case 'x': { DEBUG_ECHOLNPGM("case x\n"); - planner.synchronize(); - uint8_t index = mmu2_choose_filament(); - DISABLE_AXIS_E0(); - command(MMU_CMD_T0 + index); - manage_response(true, true); - command(MMU_CMD_C0); - mmu_loop(); + #if ENABLED(MMU2_MENUS) + planner.synchronize(); + uint8_t index = mmu2_choose_filament(); + DISABLE_AXIS_E0(); + command(MMU_CMD_T0 + index); + manage_response(true, true); + command(MMU_CMD_C0); + mmu_loop(); - ENABLE_AXIS_E0(); - extruder = index; - active_extruder = 0; + ENABLE_AXIS_E0(); + extruder = index; + active_extruder = 0; + #else + BUZZ(400, 40); + #endif } break; case 'c': { @@ -754,11 +763,9 @@ void MMU2::tool_change(const char* special) { } set_runout_valid(true); - - #endif } -#endif // MMU_EXTRUDER_SENSOR +#endif // HAS_PRUSA_MMU2S /** * Set next command @@ -866,7 +873,7 @@ void MMU2::filament_runout() { planner.synchronize(); } -#if ENABLED(PRUSA_MMU2_S_MODE) +#if HAS_PRUSA_MMU2S void MMU2::check_filament() { const bool present = FILAMENT_PRESENT(); @@ -907,162 +914,159 @@ void MMU2::filament_runout() { DEBUG_ECHOLNPGM(" succeeded."); return true; } + #endif -#if BOTH(HAS_LCD_MENU, MMU2_MENUS) +// Load filament into MMU2 +void MMU2::load_filament(const uint8_t index) { + if (!enabled) return; + command(MMU_CMD_L0 + index); + manage_response(false, false); + BUZZ(200, 404); +} - // Load filament into MMU2 - void MMU2::load_filament(const uint8_t index) { - if (!enabled) return; - command(MMU_CMD_L0 + index); - manage_response(false, false); +/** + * Switch material and load to nozzle + */ +bool MMU2::load_filament_to_nozzle(const uint8_t index) { + + if (!enabled) return false; + + if (thermalManager.tooColdToExtrude(active_extruder)) { BUZZ(200, 404); + LCD_ALERTMESSAGEPGM(MSG_HOTEND_TOO_COLD); + return false; } - /** - * Switch material and load to nozzle - */ - bool MMU2::load_filament_to_nozzle(const uint8_t index) { + command(MMU_CMD_T0 + index); + manage_response(true, true); - if (!enabled) return false; + const bool success = load_to_gears(); + if (success) { + mmu_loop(); + extruder = index; + active_extruder = 0; + load_to_nozzle(); + BUZZ(200, 404); + } + return success; +} - if (thermalManager.tooColdToExtrude(active_extruder)) { - BUZZ(200, 404); - LCD_ALERTMESSAGEPGM(MSG_HOTEND_TOO_COLD); - return false; - } +/** + * Load filament to nozzle of multimaterial printer + * + * This function is used only only after T? (user select filament) and M600 (change filament). + * It is not used after T0 .. T4 command (select filament), in such case, gcode is responsible for loading + * filament to nozzle. + */ +void MMU2::load_to_nozzle() { + if (!enabled) return; + execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence)); +} - command(MMU_CMD_T0 + index); - manage_response(true, true); +bool MMU2::eject_filament(const uint8_t index, const bool recover) { - const bool success = load_to_gears(); - if (success) { - mmu_loop(); - extruder = index; - active_extruder = 0; - load_to_nozzle(); - BUZZ(200, 404); - } - return success; - } + if (!enabled) return false; - /** - * Load filament to nozzle of multimaterial printer - * - * This function is used only only after T? (user select filament) and M600 (change filament). - * It is not used after T0 .. T4 command (select filament), in such case, gcode is responsible for loading - * filament to nozzle. - */ - void MMU2::load_to_nozzle() { - if (!enabled) return; - execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence)); + if (thermalManager.tooColdToExtrude(active_extruder)) { + BUZZ(200, 404); + LCD_ALERTMESSAGEPGM(MSG_HOTEND_TOO_COLD); + return false; } - bool MMU2::eject_filament(const uint8_t index, const bool recover) { + LCD_MESSAGEPGM(MSG_MMU2_EJECTING_FILAMENT); - if (!enabled) return false; - - if (thermalManager.tooColdToExtrude(active_extruder)) { - BUZZ(200, 404); - LCD_ALERTMESSAGEPGM(MSG_HOTEND_TOO_COLD); - return false; - } + ENABLE_AXIS_E0(); + current_position.e -= MMU2_FILAMENTCHANGE_EJECT_FEED; + line_to_current_position(MMM_TO_MMS(2500)); + planner.synchronize(); + command(MMU_CMD_E0 + index); + manage_response(false, false); - LCD_MESSAGEPGM(MSG_MMU2_EJECTING_FILAMENT); + if (recover) { + LCD_MESSAGEPGM(MSG_MMU2_EJECT_RECOVER); + BUZZ(200, 404); + TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, PSTR("MMU2 Eject Recover"), CONTINUE_STR)); + TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired_P(PSTR("MMU2 Eject Recover"))); + wait_for_user_response(); + BUZZ(200, 404); + BUZZ(200, 404); - ENABLE_AXIS_E0(); - current_position.e -= MMU2_FILAMENTCHANGE_EJECT_FEED; - line_to_current_position(2500 / 60); - planner.synchronize(); - command(MMU_CMD_E0 + index); + command(MMU_CMD_R0); manage_response(false, false); + } - if (recover) { - LCD_MESSAGEPGM(MSG_MMU2_EJECT_RECOVER); - BUZZ(200, 404); - TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, PSTR("MMU2 Eject Recover"), CONTINUE_STR)); - TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired_P(PSTR("MMU2 Eject Recover"))); - wait_for_user_response(); - BUZZ(200, 404); - BUZZ(200, 404); - - command(MMU_CMD_R0); - manage_response(false, false); - } - - ui.reset_status(); + ui.reset_status(); - // no active tool - extruder = MMU2_NO_TOOL; + // no active tool + extruder = MMU2_NO_TOOL; - set_runout_valid(false); + set_runout_valid(false); - BUZZ(200, 404); + BUZZ(200, 404); - DISABLE_AXIS_E0(); + DISABLE_AXIS_E0(); - return true; - } + return true; +} - /** - * Unload from hotend and retract to MMU - */ - bool MMU2::unload() { +/** + * Unload from hotend and retract to MMU + */ +bool MMU2::unload() { - if (!enabled) return false; + if (!enabled) return false; - if (thermalManager.tooColdToExtrude(active_extruder)) { - BUZZ(200, 404); - LCD_ALERTMESSAGEPGM(MSG_HOTEND_TOO_COLD); - return false; - } - - filament_ramming(); + if (thermalManager.tooColdToExtrude(active_extruder)) { + BUZZ(200, 404); + LCD_ALERTMESSAGEPGM(MSG_HOTEND_TOO_COLD); + return false; + } - command(MMU_CMD_U0); - manage_response(false, true); + filament_ramming(); - BUZZ(200, 404); + command(MMU_CMD_U0); + manage_response(false, true); - // no active tool - extruder = MMU2_NO_TOOL; + BUZZ(200, 404); - set_runout_valid(false); + // no active tool + extruder = MMU2_NO_TOOL; - return true; - } + set_runout_valid(false); - /** - * Unload sequence to optimize shape of the tip of the unloaded filament - */ - void MMU2::filament_ramming() { - execute_extruder_sequence((const E_Step *)ramming_sequence, sizeof(ramming_sequence) / sizeof(E_Step)); - } + return true; +} - void MMU2::execute_extruder_sequence(const E_Step * sequence, int steps) { +/** + * Unload sequence to optimize shape of the tip of the unloaded filament + */ +void MMU2::filament_ramming() { + execute_extruder_sequence((const E_Step *)ramming_sequence, sizeof(ramming_sequence) / sizeof(E_Step)); +} - planner.synchronize(); - ENABLE_AXIS_E0(); +void MMU2::execute_extruder_sequence(const E_Step * sequence, int steps) { - const E_Step* step = sequence; + planner.synchronize(); + ENABLE_AXIS_E0(); - LOOP_L_N(i, steps) { - const float es = pgm_read_float(&(step->extrude)); - const feedRate_t fr_mm_m = pgm_read_float(&(step->feedRate)); + const E_Step* step = sequence; - DEBUG_ECHO_START(); - DEBUG_ECHOLNPAIR("E step ", es, "/", fr_mm_m); + LOOP_L_N(i, steps) { + const float es = pgm_read_float(&(step->extrude)); + const feedRate_t fr_mm_m = pgm_read_float(&(step->feedRate)); - current_position.e += es; - line_to_current_position(MMM_TO_MMS(fr_mm_m)); - planner.synchronize(); + DEBUG_ECHO_START(); + DEBUG_ECHOLNPAIR("E step ", es, "/", fr_mm_m); - step++; - } + current_position.e += es; + line_to_current_position(MMM_TO_MMS(fr_mm_m)); + planner.synchronize(); - DISABLE_AXIS_E0(); + step++; } -#endif // HAS_LCD_MENU && MMU2_MENUS + DISABLE_AXIS_E0(); +} -#endif // PRUSA_MMU2 +#endif // HAS_PRUSA_MMU2 diff --git a/Marlin/src/feature/mmu2/mmu2.h b/Marlin/src/feature/mmu/mmu2.h similarity index 84% rename from Marlin/src/feature/mmu2/mmu2.h rename to Marlin/src/feature/mmu/mmu2.h index 678f65d0720d..09ff3b668366 100644 --- a/Marlin/src/feature/mmu2/mmu2.h +++ b/Marlin/src/feature/mmu/mmu2.h @@ -49,13 +49,11 @@ class MMU2 { static uint8_t get_current_tool(); static void set_filament_type(const uint8_t index, const uint8_t type); - #if BOTH(HAS_LCD_MENU, MMU2_MENUS) - static bool unload(); - static void load_filament(uint8_t); - static void load_all(); - static bool load_filament_to_nozzle(const uint8_t index); - static bool eject_filament(const uint8_t index, const bool recover); - #endif + static bool unload(); + static void load_filament(uint8_t); + static void load_all(); + static bool load_filament_to_nozzle(const uint8_t index); + static bool eject_filament(const uint8_t index, const bool recover); private: static bool rx_str_P(const char* str); @@ -72,15 +70,13 @@ class MMU2 { static bool get_response(); static void manage_response(const bool move_axes, const bool turn_off_nozzle); - #if BOTH(HAS_LCD_MENU, MMU2_MENUS) - static void load_to_nozzle(); - static void filament_ramming(); - static void execute_extruder_sequence(const E_Step * sequence, int steps); - #endif + static void load_to_nozzle(); + static void filament_ramming(); + static void execute_extruder_sequence(const E_Step * sequence, int steps); static void filament_runout(); - #if ENABLED(PRUSA_MMU2_S_MODE) + #if HAS_PRUSA_MMU2S static bool mmu2s_triggered; static void check_filament(); static bool can_load(); diff --git a/Marlin/src/gcode/config/M220.cpp b/Marlin/src/gcode/config/M220.cpp index 1bec6a778204..37fe7d3a5f28 100644 --- a/Marlin/src/gcode/config/M220.cpp +++ b/Marlin/src/gcode/config/M220.cpp @@ -31,13 +31,13 @@ * * Report the current speed percentage factor if no parameter is specified * - * With PRUSA_MMU2... + * For MMU2 and MMU2S devices... * B : Flag to back up the current factor * R : Flag to restore the last-saved factor */ void GcodeSuite::M220() { - #if ENABLED(PRUSA_MMU2) + #if HAS_PRUSA_MMU2 static int16_t backup_feedrate_percentage = 100; if (parser.seen('B')) backup_feedrate_percentage = feedrate_percentage; if (parser.seen('R')) feedrate_percentage = backup_feedrate_percentage; diff --git a/Marlin/src/gcode/control/T.cpp b/Marlin/src/gcode/control/T.cpp index d95e60ff8d70..592b2b3dcefb 100644 --- a/Marlin/src/gcode/control/T.cpp +++ b/Marlin/src/gcode/control/T.cpp @@ -27,8 +27,8 @@ #include "../../module/motion.h" #endif -#if ENABLED(PRUSA_MMU2) - #include "../../feature/mmu2/mmu2.h" +#if HAS_PRUSA_MMU2 + #include "../../feature/mmu/mmu2.h" #endif #define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE) @@ -40,7 +40,7 @@ * F[units/min] Set the movement feedrate * S1 Don't move the tool in XY after change * - * For PRUSA_MMU2: + * For PRUSA_MMU2(S) and SMUFF_EMU_MMU2(S) * T[n] Gcode to extrude at least 38.10 mm at feedrate 19.02 mm/s must follow immediately to load to extruder wheels. * T? Gcode to extrude shouldn't have to follow. Load to extruder wheels is done automatically. * Tx Same as T?, but nozzle doesn't have to be preheated. Tc requires a preheated nozzle to finish filament load. @@ -54,7 +54,7 @@ void GcodeSuite::T(const int8_t tool_index) { // Count this command as movement / activity reset_stepper_timeout(); - #if ENABLED(PRUSA_MMU2) + #if HAS_PRUSA_MMU2 if (parser.string_arg) { mmu2.tool_change(parser.string_arg); // Special commands T?/Tx/Tc return; diff --git a/Marlin/src/gcode/feature/pause/M701_M702.cpp b/Marlin/src/gcode/feature/pause/M701_M702.cpp index a193d83d40f6..a100d462da7e 100644 --- a/Marlin/src/gcode/feature/pause/M701_M702.cpp +++ b/Marlin/src/gcode/feature/pause/M701_M702.cpp @@ -38,8 +38,8 @@ #include "../../../lcd/marlinui.h" #endif -#if ENABLED(PRUSA_MMU2) - #include "../../../feature/mmu2/mmu2.h" +#if HAS_PRUSA_MMU2 + #include "../../../feature/mmu/mmu2.h" #endif #if ENABLED(MIXING_EXTRUDER) @@ -86,7 +86,7 @@ void GcodeSuite::M701() { // Show initial "wait for load" message TERN_(HAS_LCD_MENU, lcd_pause_show_message(PAUSE_MESSAGE_LOAD, PAUSE_MODE_LOAD_FILAMENT, target_extruder)); - #if HAS_MULTI_EXTRUDER && DISABLED(PRUSA_MMU2) + #if HAS_MULTI_EXTRUDER && (HAS_PRUSA_MMU1 || !HAS_MMU) // Change toolhead if specified uint8_t active_extruder_before_filament_change = active_extruder; if (active_extruder != target_extruder) @@ -98,7 +98,7 @@ void GcodeSuite::M701() { do_blocking_move_to_z(_MIN(current_position.z + park_point.z, Z_MAX_POS), feedRate_t(NOZZLE_PARK_Z_FEEDRATE)); // Load filament - #if ENABLED(PRUSA_MMU2) + #if HAS_PRUSA_MMU2 mmu2.load_filament_to_nozzle(target_extruder); #else constexpr float purge_length = ADVANCED_PAUSE_PURGE_LENGTH, @@ -121,7 +121,7 @@ void GcodeSuite::M701() { if (park_point.z > 0) do_blocking_move_to_z(_MAX(current_position.z - park_point.z, 0), feedRate_t(NOZZLE_PARK_Z_FEEDRATE)); - #if HAS_MULTI_EXTRUDER && DISABLED(PRUSA_MMU2) + #if HAS_MULTI_EXTRUDER && (HAS_PRUSA_MMU1 || !HAS_MMU) // Restore toolhead if it was changed if (active_extruder_before_filament_change != active_extruder) tool_change(active_extruder_before_filament_change, false); @@ -186,7 +186,7 @@ void GcodeSuite::M702() { // Show initial "wait for unload" message TERN_(HAS_LCD_MENU, lcd_pause_show_message(PAUSE_MESSAGE_UNLOAD, PAUSE_MODE_UNLOAD_FILAMENT, target_extruder)); - #if HAS_MULTI_EXTRUDER && DISABLED(PRUSA_MMU2) + #if HAS_MULTI_EXTRUDER && (HAS_PRUSA_MMU1 || !HAS_MMU) // Change toolhead if specified uint8_t active_extruder_before_filament_change = active_extruder; if (active_extruder != target_extruder) @@ -198,7 +198,7 @@ void GcodeSuite::M702() { do_blocking_move_to_z(_MIN(current_position.z + park_point.z, Z_MAX_POS), feedRate_t(NOZZLE_PARK_Z_FEEDRATE)); // Unload filament - #if ENABLED(PRUSA_MMU2) + #if HAS_PRUSA_MMU2 mmu2.unload(); #else #if BOTH(HAS_MULTI_EXTRUDER, FILAMENT_UNLOAD_ALL_EXTRUDERS) @@ -227,7 +227,7 @@ void GcodeSuite::M702() { if (park_point.z > 0) do_blocking_move_to_z(_MAX(current_position.z - park_point.z, 0), feedRate_t(NOZZLE_PARK_Z_FEEDRATE)); - #if HAS_MULTI_EXTRUDER && DISABLED(PRUSA_MMU2) + #if HAS_MULTI_EXTRUDER && (HAS_PRUSA_MMU1 || !HAS_MMU) // Restore toolhead if it was changed if (active_extruder_before_filament_change != active_extruder) tool_change(active_extruder_before_filament_change, false); diff --git a/Marlin/src/gcode/feature/prusa_MMU2/M403.cpp b/Marlin/src/gcode/feature/prusa_MMU2/M403.cpp index 91e35dbf657c..31d076337a44 100644 --- a/Marlin/src/gcode/feature/prusa_MMU2/M403.cpp +++ b/Marlin/src/gcode/feature/prusa_MMU2/M403.cpp @@ -22,10 +22,10 @@ #include "../../../inc/MarlinConfigPre.h" -#if ENABLED(PRUSA_MMU2) +#if HAS_PRUSA_MMU2 #include "../../gcode.h" -#include "../../../feature/mmu2/mmu2.h" +#include "../../../feature/mmu/mmu2.h" /** * M403: Set filament type for MMU2 @@ -46,4 +46,4 @@ void GcodeSuite::M403() { SERIAL_ECHO_MSG("M403 - bad arguments."); } -#endif // PRUSA_MMU2 +#endif // HAS_PRUSA_MMU2 diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp index c8818dca0308..2a899b73b0ba 100644 --- a/Marlin/src/gcode/gcode.cpp +++ b/Marlin/src/gcode/gcode.cpp @@ -703,7 +703,7 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { case 402: M402(); break; // M402: Stow probe #endif - #if ENABLED(PRUSA_MMU2) + #if HAS_PRUSA_MMU2 case 403: M403(); break; #endif diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h index 3fbb88829e09..1d74ac371960 100644 --- a/Marlin/src/gcode/gcode.h +++ b/Marlin/src/gcode/gcode.h @@ -181,7 +181,7 @@ * M217 - Set filament swap parameters: "M217 S P R". (Requires SINGLENOZZLE) * M218 - Set/get a tool offset: "M218 T X Y". (Requires 2 or more extruders) * M220 - Set Feedrate Percentage: "M220 S" (i.e., "FR" on the LCD) - * Use "M220 B" to back up the Feedrate Percentage and "M220 R" to restore it. (Requires PRUSA_MMU2) + * Use "M220 B" to back up the Feedrate Percentage and "M220 R" to restore it. (Requires an MMU_MODEL version 2 or 2S) * M221 - Set Flow Percentage: "M221 S" * M226 - Wait until a pin is in a given state: "M226 P S" (Requires DIRECT_PIN_CONTROL) * M240 - Trigger a camera to take a photograph. (Requires PHOTO_GCODE) @@ -735,7 +735,7 @@ class GcodeSuite { static void M402(); #endif - TERN_(PRUSA_MMU2, static void M403()); + TERN_(HAS_PRUSA_MMU2, static void M403()); #if ENABLED(FILAMENT_WIDTH_SENSOR) static void M404(); diff --git a/Marlin/src/gcode/parser.cpp b/Marlin/src/gcode/parser.cpp index 4bff045e304d..a513c4b59611 100644 --- a/Marlin/src/gcode/parser.cpp +++ b/Marlin/src/gcode/parser.cpp @@ -155,7 +155,7 @@ void GCodeParser::parse(char *p) { // Skip spaces to get the numeric part while (*p == ' ') p++; - #if ENABLED(PRUSA_MMU2) + #if HAS_PRUSA_MMU2 if (letter == 'T') { // check for special MMU2 T?/Tx/Tc commands if (*p == '?' || *p == 'x' || *p == 'c') { diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h index 945b6749f2e4..774e482d82d4 100644 --- a/Marlin/src/inc/Conditionals_LCD.h +++ b/Marlin/src/inc/Conditionals_LCD.h @@ -515,6 +515,36 @@ #endif #endif +/** + * Multi-Material-Unit supported models + */ +#define PRUSA_MMU1 1 +#define PRUSA_MMU2 2 +#define PRUSA_MMU2S 3 +#define SMUFF_EMU_MMU2 12 +#define SMUFF_EMU_MMU2S 13 + +#ifdef MMU_MODEL + #define HAS_MMU 1 + #if MMU_MODEL == PRUSA_MMU1 + #define HAS_PRUSA_MMU1 1 + #elif MMU_MODEL % 10 == PRUSA_MMU2 + #define HAS_PRUSA_MMU2 1 + #elif MMU_MODEL % 10 == PRUSA_MMU2S + #define HAS_PRUSA_MMU2 1 + #define HAS_PRUSA_MMU2S 1 + #endif + #if MMU_MODEL >= SMUFF_EMU_MMU2 + #define HAS_SMUFF 1 + #endif +#endif + +#undef PRUSA_MMU1 +#undef PRUSA_MMU2 +#undef PRUSA_MMU2S +#undef SMUFF_EMU_MMU2 +#undef SMUFF_EMU_MMU2S + /** * Extruders have some combination of stepper motors and hotends * so we separate these concepts into the defines: @@ -532,8 +562,6 @@ #undef SWITCHING_EXTRUDER #undef SWITCHING_NOZZLE #undef MIXING_EXTRUDER - #undef MK2_MULTIPLEXER - #undef PRUSA_MMU2 #undef HOTEND_IDLE_TIMEOUT #elif EXTRUDERS > 1 #define HAS_MULTI_EXTRUDER 1 @@ -559,17 +587,17 @@ #elif ENABLED(SWITCHING_TOOLHEAD) #define E_STEPPERS EXTRUDERS #define E_MANUAL EXTRUDERS -#elif ENABLED(PRUSA_MMU2) +#elif HAS_PRUSA_MMU2 #define E_STEPPERS 1 #endif -// No inactive extruders with MK2_MULTIPLEXER or SWITCHING_NOZZLE -#if EITHER(MK2_MULTIPLEXER, SWITCHING_NOZZLE) +// No inactive extruders with SWITCHING_NOZZLE or Průša MMU1 +#if ENABLED(SWITCHING_NOZZLE) || HAS_PRUSA_MMU1 #undef DISABLE_INACTIVE_EXTRUDER #endif -// Průša MK2 Multiplexer and MMU 2.0 force SINGLENOZZLE -#if EITHER(MK2_MULTIPLEXER, PRUSA_MMU2) +// Průša MMU1, MMU 2.0, MMUS 2.0 and SMUFF force SINGLENOZZLE +#if HAS_MMU #define SINGLENOZZLE #endif diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 65504ab7952d..4215f225e3eb 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -804,7 +804,11 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #if !PIN_EXISTS(FIL_RUNOUT) #error "FILAMENT_RUNOUT_SENSOR requires FIL_RUNOUT_PIN." #elif NUM_RUNOUT_SENSORS > E_STEPPERS - #error "NUM_RUNOUT_SENSORS cannot exceed the number of E steppers." + #if HAS_PRUSA_MMU2 + #error "NUM_RUNOUT_SENSORS must be 1 with MMU2 / MMU2S." + #else + #error "NUM_RUNOUT_SENSORS cannot exceed the number of E steppers." + #endif #elif NUM_RUNOUT_SENSORS >= 2 && !PIN_EXISTS(FIL_RUNOUT2) #error "FIL_RUNOUT2_PIN is required with NUM_RUNOUT_SENSORS >= 2." #elif NUM_RUNOUT_SENSORS >= 3 && !PIN_EXISTS(FIL_RUNOUT3) @@ -867,6 +871,42 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #error "INDIVIDUAL_AXIS_HOMING_MENU is incompatible with DELTA kinematics." #endif +/** + * Sanity checking for all Průša MMU + */ +#ifdef SNMM + #error "SNMM is obsolete. Define MMU_MODEL as PRUSA_MMU1 instead." +#elif ENABLED(MK2_MULTIPLEXER) + #error "MK2_MULTIPLEXER is obsolete. Define MMU_MODEL as PRUSA_MMU1 instead." +#elif ENABLED(PRUSA_MMU2) + #error "PRUSA_MMU2 is obsolete. Define MMU_MODEL as PRUSA_MMU2 instead." +#elif ENABLED(PRUSA_MMU2_S_MODE) + #error "PRUSA_MMU2_S_MODE is obsolete. Define MMU_MODEL as PRUSA_MMU2S instead." +#endif + +/** + * Multi-Material-Unit 2 / SMUFF requirements + */ +#if HAS_PRUSA_MMU2 + #if EXTRUDERS != 5 + #undef SINGLENOZZLE + #error "PRUSA_MMU2(S) requires exactly 5 EXTRUDERS. Please update your Configuration." + #elif DISABLED(NOZZLE_PARK_FEATURE) + #error "PRUSA_MMU2(S) requires NOZZLE_PARK_FEATURE. Enable it to continue." + #elif HAS_PRUSA_MMU2S && DISABLED(FILAMENT_RUNOUT_SENSOR) + #error "PRUSA_MMU2S requires FILAMENT_RUNOUT_SENSOR. Enable it to continue." + #elif ENABLED(MMU_EXTRUDER_SENSOR) && DISABLED(FILAMENT_RUNOUT_SENSOR) + #error "MMU_EXTRUDER_SENSOR requires FILAMENT_RUNOUT_SENSOR. Enable it to continue." + #elif ENABLED(MMU_EXTRUDER_SENSOR) && !HAS_LCD_MENU + #error "MMU_EXTRUDER_SENSOR requires an LCD supporting MarlinUI to be enabled." + #elif DISABLED(ADVANCED_PAUSE_FEATURE) + static_assert(nullptr == strstr(MMU2_FILAMENT_RUNOUT_SCRIPT, "M600"), "ADVANCED_PAUSE_FEATURE is required to use M600 with PRUSA_MMU2(S) / SMUFF_EMU_MMU2(S)."); + #endif +#endif +#if HAS_SMUFF && EXTRUDERS > 12 + #error "Too many extruders for SMUFF_EMU_MMU2(S). (12 maximum)." +#endif + /** * Options only for EXTRUDERS > 1 */ @@ -902,17 +942,14 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS #error "TOOLCHANGE_ZRAISE required for EXTRUDERS > 1." #endif -#elif ENABLED(MK2_MULTIPLEXER) - #error "MK2_MULTIPLEXER requires 2 or more EXTRUDERS." +#elif HAS_PRUSA_MMU1 || HAS_SMUFF + + #error "Multi-Material-Unit requires 2 or more EXTRUDERS." + #elif ENABLED(SINGLENOZZLE) + #error "SINGLENOZZLE requires 2 or more EXTRUDERS." -#endif -/** - * Sanity checking for the Průša MK2 Multiplexer - */ -#ifdef SNMM - #error "SNMM is now MK2_MULTIPLEXER." #endif /** @@ -1870,48 +1907,46 @@ static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal /** * Test Extruder Stepper Pins */ -#if DISABLED(MK2_MULTIPLEXER) // MK2_MULTIPLEXER uses E0 stepper only - #if E_STEPPERS - #if !(PINS_EXIST(E0_STEP, E0_DIR) && HAS_E0_ENABLE) - #error "E0_STEP_PIN, E0_DIR_PIN, or E0_ENABLE_PIN not defined for this board." +#if E_STEPPERS + #if !(PINS_EXIST(E0_STEP, E0_DIR) && HAS_E0_ENABLE) + #error "E0_STEP_PIN, E0_DIR_PIN, or E0_ENABLE_PIN not defined for this board." + #endif + #if E_STEPPERS > 1 + #if !(PINS_EXIST(E1_STEP, E1_DIR) && HAS_E1_ENABLE) + #error "E1_STEP_PIN, E1_DIR_PIN, or E1_ENABLE_PIN not defined for this board." #endif - #if E_STEPPERS > 1 - #if !(PINS_EXIST(E1_STEP, E1_DIR) && HAS_E1_ENABLE) - #error "E1_STEP_PIN, E1_DIR_PIN, or E1_ENABLE_PIN not defined for this board." + #if E_STEPPERS > 2 + #if !(PINS_EXIST(E2_STEP, E2_DIR) && HAS_E2_ENABLE) + #error "E2_STEP_PIN, E2_DIR_PIN, or E2_ENABLE_PIN not defined for this board." #endif - #if E_STEPPERS > 2 - #if !(PINS_EXIST(E2_STEP, E2_DIR) && HAS_E2_ENABLE) - #error "E2_STEP_PIN, E2_DIR_PIN, or E2_ENABLE_PIN not defined for this board." + #if E_STEPPERS > 3 + #if !(PINS_EXIST(E3_STEP, E3_DIR) && HAS_E3_ENABLE) + #error "E3_STEP_PIN, E3_DIR_PIN, or E3_ENABLE_PIN not defined for this board." #endif - #if E_STEPPERS > 3 - #if !(PINS_EXIST(E3_STEP, E3_DIR) && HAS_E3_ENABLE) - #error "E3_STEP_PIN, E3_DIR_PIN, or E3_ENABLE_PIN not defined for this board." + #if E_STEPPERS > 4 + #if !(PINS_EXIST(E4_STEP, E4_DIR) && HAS_E4_ENABLE) + #error "E4_STEP_PIN, E4_DIR_PIN, or E4_ENABLE_PIN not defined for this board." #endif - #if E_STEPPERS > 4 - #if !(PINS_EXIST(E4_STEP, E4_DIR) && HAS_E4_ENABLE) - #error "E4_STEP_PIN, E4_DIR_PIN, or E4_ENABLE_PIN not defined for this board." + #if E_STEPPERS > 5 + #if !(PINS_EXIST(E5_STEP, E5_DIR) && HAS_E5_ENABLE) + #error "E5_STEP_PIN, E5_DIR_PIN, or E5_ENABLE_PIN not defined for this board." #endif - #if E_STEPPERS > 5 - #if !(PINS_EXIST(E5_STEP, E5_DIR) && HAS_E5_ENABLE) - #error "E5_STEP_PIN, E5_DIR_PIN, or E5_ENABLE_PIN not defined for this board." + #if E_STEPPERS > 6 + #if !(PINS_EXIST(E6_STEP, E6_DIR) && HAS_E6_ENABLE) + #error "E6_STEP_PIN, E6_DIR_PIN, or E6_ENABLE_PIN not defined for this board." #endif - #if E_STEPPERS > 6 - #if !(PINS_EXIST(E6_STEP, E6_DIR) && HAS_E6_ENABLE) - #error "E6_STEP_PIN, E6_DIR_PIN, or E6_ENABLE_PIN not defined for this board." + #if E_STEPPERS > 7 + #if !(PINS_EXIST(E7_STEP, E7_DIR) && HAS_E7_ENABLE) + #error "E7_STEP_PIN, E7_DIR_PIN, or E7_ENABLE_PIN not defined for this board." #endif - #if E_STEPPERS > 7 - #if !(PINS_EXIST(E7_STEP, E7_DIR) && HAS_E7_ENABLE) - #error "E7_STEP_PIN, E7_DIR_PIN, or E7_ENABLE_PIN not defined for this board." - #endif - #endif // E_STEPPERS > 7 - #endif // E_STEPPERS > 6 - #endif // E_STEPPERS > 5 - #endif // E_STEPPERS > 4 - #endif // E_STEPPERS > 3 - #endif // E_STEPPERS > 2 - #endif // E_STEPPERS > 1 - #endif // E_STEPPERS -#endif + #endif // E_STEPPERS > 7 + #endif // E_STEPPERS > 6 + #endif // E_STEPPERS > 5 + #endif // E_STEPPERS > 4 + #endif // E_STEPPERS > 3 + #endif // E_STEPPERS > 2 + #endif // E_STEPPERS > 1 +#endif // E_STEPPERS /** * Endstop Tests @@ -2977,23 +3012,6 @@ static_assert( _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2) #endif #endif -/** - * Průša MMU2 requirements - */ -#if ENABLED(PRUSA_MMU2) - #if EXTRUDERS != 5 - #error "PRUSA_MMU2 requires EXTRUDERS = 5." - #elif DISABLED(NOZZLE_PARK_FEATURE) - #error "PRUSA_MMU2 requires NOZZLE_PARK_FEATURE. Enable it to continue." - #elif EITHER(PRUSA_MMU2_S_MODE, MMU_EXTRUDER_SENSOR) && DISABLED(FILAMENT_RUNOUT_SENSOR) - #error "PRUSA_MMU2_S_MODE or MMU_EXTRUDER_SENSOR requires FILAMENT_RUNOUT_SENSOR. Enable it to continue." - #elif BOTH(PRUSA_MMU2_S_MODE, MMU_EXTRUDER_SENSOR) - #error "Enable only one of PRUSA_MMU2_S_MODE or MMU_EXTRUDER_SENSOR." - #elif DISABLED(ADVANCED_PAUSE_FEATURE) - static_assert(nullptr == strstr(MMU2_FILAMENT_RUNOUT_SCRIPT, "M600"), "ADVANCED_PAUSE_FEATURE is required to use M600 with PRUSA_MMU2."); - #endif -#endif - /** * Advanced PRINTCOUNTER settings */ diff --git a/Marlin/src/lcd/menu/menu_main.cpp b/Marlin/src/lcd/menu/menu_main.cpp index bb65ce61e260..cda11bfc57cc 100644 --- a/Marlin/src/lcd/menu/menu_main.cpp +++ b/Marlin/src/lcd/menu/menu_main.cpp @@ -46,7 +46,7 @@ #define MACHINE_CAN_PAUSE 1 #endif -#if ENABLED(PRUSA_MMU2) +#if ENABLED(MMU2_MENUS) #include "../../lcd/menu/menu_mmu2.h" #endif diff --git a/Marlin/src/lcd/menu/menu_mmu2.cpp b/Marlin/src/lcd/menu/menu_mmu2.cpp index 0a63d90c6370..8a34e7d296fb 100644 --- a/Marlin/src/lcd/menu/menu_mmu2.cpp +++ b/Marlin/src/lcd/menu/menu_mmu2.cpp @@ -24,13 +24,10 @@ #if BOTH(HAS_LCD_MENU, MMU2_MENUS) -#include "../../feature/mmu2/mmu2.h" +#include "../../feature/mmu/mmu2.h" #include "menu_mmu2.h" #include "menu_item.h" -uint8_t currentTool; -bool mmuMenuWait; - // // Load Filament // @@ -123,9 +120,12 @@ void menu_mmu2() { // T* Choose Filament // -inline void action_mmu2_choose(const uint8_t tool) { - currentTool = tool; - mmuMenuWait = false; +uint8_t feeder_index; +bool wait_for_mmu_menu; + +inline void action_mmu2_chosen(const uint8_t index) { + feeder_index = index; + wait_for_mmu_menu = false; } void menu_mmu2_choose_filament() { @@ -133,7 +133,7 @@ void menu_mmu2_choose_filament() { #if LCD_HEIGHT > 2 STATIC_ITEM(MSG_MMU2_CHOOSE_FILAMENT_HEADER, SS_DEFAULT|SS_INVERT); #endif - LOOP_L_N(i, 5) ACTION_ITEM_N(i, MSG_MMU2_FILAMENT_N, []{ action_mmu2_choose(MenuItemBase::itemIndex); }); + LOOP_L_N(i, 5) ACTION_ITEM_N(i, MSG_MMU2_FILAMENT_N, []{ action_mmu2_chosen(MenuItemBase::itemIndex); }); END_MENU(); } @@ -142,32 +142,32 @@ void menu_mmu2_choose_filament() { // void menu_mmu2_pause() { - currentTool = mmu2.get_current_tool(); + feeder_index = mmu2.get_current_tool(); START_MENU(); #if LCD_HEIGHT > 2 STATIC_ITEM(MSG_FILAMENT_CHANGE_HEADER, SS_DEFAULT|SS_INVERT); #endif - ACTION_ITEM(MSG_MMU2_RESUME, []{ mmuMenuWait = false; }); + ACTION_ITEM(MSG_MMU2_RESUME, []{ wait_for_mmu_menu = false; }); ACTION_ITEM(MSG_MMU2_UNLOAD_FILAMENT, []{ mmu2.unload(); }); - ACTION_ITEM(MSG_MMU2_LOAD_FILAMENT, []{ mmu2.load_filament(currentTool); }); - ACTION_ITEM(MSG_MMU2_LOAD_TO_NOZZLE, []{ mmu2.load_filament_to_nozzle(currentTool); }); + ACTION_ITEM(MSG_MMU2_LOAD_FILAMENT, []{ mmu2.load_filament(feeder_index); }); + ACTION_ITEM(MSG_MMU2_LOAD_TO_NOZZLE, []{ mmu2.load_filament_to_nozzle(feeder_index); }); END_MENU(); } void mmu2_M600() { ui.defer_status_screen(); ui.goto_screen(menu_mmu2_pause); - mmuMenuWait = true; - while (mmuMenuWait) idle(); + wait_for_mmu_menu = true; + while (wait_for_mmu_menu) idle(); } uint8_t mmu2_choose_filament() { ui.defer_status_screen(); ui.goto_screen(menu_mmu2_choose_filament); - mmuMenuWait = true; - while (mmuMenuWait) idle(); + wait_for_mmu_menu = true; + while (wait_for_mmu_menu) idle(); ui.return_to_status(); - return currentTool; + return feeder_index; } #endif // HAS_LCD_MENU && MMU2_MENUS diff --git a/Marlin/src/module/settings.cpp b/Marlin/src/module/settings.cpp index 21997b4740f6..6614aec35b8a 100644 --- a/Marlin/src/module/settings.cpp +++ b/Marlin/src/module/settings.cpp @@ -1068,46 +1068,30 @@ void MarlinSettings::postprocess() { #if AXIS_IS_TMC(Z4) tmc_stepper_current.Z4 = stepperZ4.getMilliamps(); #endif - #if MAX_EXTRUDERS - #if AXIS_IS_TMC(E0) - tmc_stepper_current.E0 = stepperE0.getMilliamps(); - #endif - #if MAX_EXTRUDERS > 1 - #if AXIS_IS_TMC(E1) - tmc_stepper_current.E1 = stepperE1.getMilliamps(); - #endif - #if MAX_EXTRUDERS > 2 - #if AXIS_IS_TMC(E2) - tmc_stepper_current.E2 = stepperE2.getMilliamps(); - #endif - #if MAX_EXTRUDERS > 3 - #if AXIS_IS_TMC(E3) - tmc_stepper_current.E3 = stepperE3.getMilliamps(); - #endif - #if MAX_EXTRUDERS > 4 - #if AXIS_IS_TMC(E4) - tmc_stepper_current.E4 = stepperE4.getMilliamps(); - #endif - #if MAX_EXTRUDERS > 5 - #if AXIS_IS_TMC(E5) - tmc_stepper_current.E5 = stepperE5.getMilliamps(); - #endif - #if MAX_EXTRUDERS > 6 - #if AXIS_IS_TMC(E6) - tmc_stepper_current.E6 = stepperE6.getMilliamps(); - #endif - #if MAX_EXTRUDERS > 7 - #if AXIS_IS_TMC(E7) - tmc_stepper_current.E7 = stepperE7.getMilliamps(); - #endif - #endif // MAX_EXTRUDERS > 7 - #endif // MAX_EXTRUDERS > 6 - #endif // MAX_EXTRUDERS > 5 - #endif // MAX_EXTRUDERS > 4 - #endif // MAX_EXTRUDERS > 3 - #endif // MAX_EXTRUDERS > 2 - #endif // MAX_EXTRUDERS > 1 - #endif // MAX_EXTRUDERS + #if AXIS_IS_TMC(E0) + tmc_stepper_current.E0 = stepperE0.getMilliamps(); + #endif + #if AXIS_IS_TMC(E1) + tmc_stepper_current.E1 = stepperE1.getMilliamps(); + #endif + #if AXIS_IS_TMC(E2) + tmc_stepper_current.E2 = stepperE2.getMilliamps(); + #endif + #if AXIS_IS_TMC(E3) + tmc_stepper_current.E3 = stepperE3.getMilliamps(); + #endif + #if AXIS_IS_TMC(E4) + tmc_stepper_current.E4 = stepperE4.getMilliamps(); + #endif + #if AXIS_IS_TMC(E5) + tmc_stepper_current.E5 = stepperE5.getMilliamps(); + #endif + #if AXIS_IS_TMC(E6) + tmc_stepper_current.E6 = stepperE6.getMilliamps(); + #endif + #if AXIS_IS_TMC(E7) + tmc_stepper_current.E7 = stepperE7.getMilliamps(); + #endif #endif EEPROM_WRITE(tmc_stepper_current); } @@ -1144,46 +1128,30 @@ void MarlinSettings::postprocess() { #if AXIS_HAS_STEALTHCHOP(Z4) tmc_hybrid_threshold.Z4 = stepperZ4.get_pwm_thrs(); #endif - #if MAX_EXTRUDERS - #if AXIS_HAS_STEALTHCHOP(E0) - tmc_hybrid_threshold.E0 = stepperE0.get_pwm_thrs(); - #endif - #if MAX_EXTRUDERS > 1 - #if AXIS_HAS_STEALTHCHOP(E1) - tmc_hybrid_threshold.E1 = stepperE1.get_pwm_thrs(); - #endif - #if MAX_EXTRUDERS > 2 - #if AXIS_HAS_STEALTHCHOP(E2) - tmc_hybrid_threshold.E2 = stepperE2.get_pwm_thrs(); - #endif - #if MAX_EXTRUDERS > 3 - #if AXIS_HAS_STEALTHCHOP(E3) - tmc_hybrid_threshold.E3 = stepperE3.get_pwm_thrs(); - #endif - #if MAX_EXTRUDERS > 4 - #if AXIS_HAS_STEALTHCHOP(E4) - tmc_hybrid_threshold.E4 = stepperE4.get_pwm_thrs(); - #endif - #if MAX_EXTRUDERS > 5 - #if AXIS_HAS_STEALTHCHOP(E5) - tmc_hybrid_threshold.E5 = stepperE5.get_pwm_thrs(); - #endif - #if MAX_EXTRUDERS > 6 - #if AXIS_HAS_STEALTHCHOP(E6) - tmc_hybrid_threshold.E6 = stepperE6.get_pwm_thrs(); - #endif - #if MAX_EXTRUDERS > 7 - #if AXIS_HAS_STEALTHCHOP(E7) - tmc_hybrid_threshold.E7 = stepperE7.get_pwm_thrs(); - #endif - #endif // MAX_EXTRUDERS > 7 - #endif // MAX_EXTRUDERS > 6 - #endif // MAX_EXTRUDERS > 5 - #endif // MAX_EXTRUDERS > 4 - #endif // MAX_EXTRUDERS > 3 - #endif // MAX_EXTRUDERS > 2 - #endif // MAX_EXTRUDERS > 1 - #endif // MAX_EXTRUDERS + #if AXIS_HAS_STEALTHCHOP(E0) + tmc_hybrid_threshold.E0 = stepperE0.get_pwm_thrs(); + #endif + #if AXIS_HAS_STEALTHCHOP(E1) + tmc_hybrid_threshold.E1 = stepperE1.get_pwm_thrs(); + #endif + #if AXIS_HAS_STEALTHCHOP(E2) + tmc_hybrid_threshold.E2 = stepperE2.get_pwm_thrs(); + #endif + #if AXIS_HAS_STEALTHCHOP(E3) + tmc_hybrid_threshold.E3 = stepperE3.get_pwm_thrs(); + #endif + #if AXIS_HAS_STEALTHCHOP(E4) + tmc_hybrid_threshold.E4 = stepperE4.get_pwm_thrs(); + #endif + #if AXIS_HAS_STEALTHCHOP(E5) + tmc_hybrid_threshold.E5 = stepperE5.get_pwm_thrs(); + #endif + #if AXIS_HAS_STEALTHCHOP(E6) + tmc_hybrid_threshold.E6 = stepperE6.get_pwm_thrs(); + #endif + #if AXIS_HAS_STEALTHCHOP(E7) + tmc_hybrid_threshold.E7 = stepperE7.get_pwm_thrs(); + #endif #else const tmc_hybrid_threshold_t tmc_hybrid_threshold = { .X = 100, .Y = 100, .Z = 3, @@ -1219,73 +1187,54 @@ void MarlinSettings::postprocess() { { _FIELD_TEST(tmc_stealth_enabled); - tmc_stealth_enabled_t tmc_stealth_enabled = { false, false, false, false, false, false, false, false, false, false, false, false, false }; - - #if HAS_STEALTHCHOP - #if AXIS_HAS_STEALTHCHOP(X) - tmc_stealth_enabled.X = stepperX.get_stored_stealthChop(); - #endif - #if AXIS_HAS_STEALTHCHOP(Y) - tmc_stealth_enabled.Y = stepperY.get_stored_stealthChop(); - #endif - #if AXIS_HAS_STEALTHCHOP(Z) - tmc_stealth_enabled.Z = stepperZ.get_stored_stealthChop(); - #endif - #if AXIS_HAS_STEALTHCHOP(X2) - tmc_stealth_enabled.X2 = stepperX2.get_stored_stealthChop(); - #endif - #if AXIS_HAS_STEALTHCHOP(Y2) - tmc_stealth_enabled.Y2 = stepperY2.get_stored_stealthChop(); - #endif - #if AXIS_HAS_STEALTHCHOP(Z2) - tmc_stealth_enabled.Z2 = stepperZ2.get_stored_stealthChop(); - #endif - #if AXIS_HAS_STEALTHCHOP(Z3) - tmc_stealth_enabled.Z3 = stepperZ3.get_stored_stealthChop(); - #endif - #if AXIS_HAS_STEALTHCHOP(Z4) - tmc_stealth_enabled.Z4 = stepperZ4.get_stored_stealthChop(); - #endif - #if MAX_EXTRUDERS - #if AXIS_HAS_STEALTHCHOP(E0) - tmc_stealth_enabled.E0 = stepperE0.get_stored_stealthChop(); - #endif - #if MAX_EXTRUDERS > 1 - #if AXIS_HAS_STEALTHCHOP(E1) - tmc_stealth_enabled.E1 = stepperE1.get_stored_stealthChop(); - #endif - #if MAX_EXTRUDERS > 2 - #if AXIS_HAS_STEALTHCHOP(E2) - tmc_stealth_enabled.E2 = stepperE2.get_stored_stealthChop(); - #endif - #if MAX_EXTRUDERS > 3 - #if AXIS_HAS_STEALTHCHOP(E3) - tmc_stealth_enabled.E3 = stepperE3.get_stored_stealthChop(); - #endif - #if MAX_EXTRUDERS > 4 - #if AXIS_HAS_STEALTHCHOP(E4) - tmc_stealth_enabled.E4 = stepperE4.get_stored_stealthChop(); - #endif - #if MAX_EXTRUDERS > 5 - #if AXIS_HAS_STEALTHCHOP(E5) - tmc_stealth_enabled.E5 = stepperE5.get_stored_stealthChop(); - #endif - #if MAX_EXTRUDERS > 6 - #if AXIS_HAS_STEALTHCHOP(E6) - tmc_stealth_enabled.E6 = stepperE6.get_stored_stealthChop(); - #endif - #if MAX_EXTRUDERS > 7 - #if AXIS_HAS_STEALTHCHOP(E7) - tmc_stealth_enabled.E7 = stepperE7.get_stored_stealthChop(); - #endif - #endif // MAX_EXTRUDERS > 7 - #endif // MAX_EXTRUDERS > 6 - #endif // MAX_EXTRUDERS > 5 - #endif // MAX_EXTRUDERS > 4 - #endif // MAX_EXTRUDERS > 3 - #endif // MAX_EXTRUDERS > 2 - #endif // MAX_EXTRUDERS > 1 - #endif // MAX_EXTRUDERS + tmc_stealth_enabled_t tmc_stealth_enabled = { false }; + #if AXIS_HAS_STEALTHCHOP(X) + tmc_stealth_enabled.X = stepperX.get_stored_stealthChop(); + #endif + #if AXIS_HAS_STEALTHCHOP(Y) + tmc_stealth_enabled.Y = stepperY.get_stored_stealthChop(); + #endif + #if AXIS_HAS_STEALTHCHOP(Z) + tmc_stealth_enabled.Z = stepperZ.get_stored_stealthChop(); + #endif + #if AXIS_HAS_STEALTHCHOP(X2) + tmc_stealth_enabled.X2 = stepperX2.get_stored_stealthChop(); + #endif + #if AXIS_HAS_STEALTHCHOP(Y2) + tmc_stealth_enabled.Y2 = stepperY2.get_stored_stealthChop(); + #endif + #if AXIS_HAS_STEALTHCHOP(Z2) + tmc_stealth_enabled.Z2 = stepperZ2.get_stored_stealthChop(); + #endif + #if AXIS_HAS_STEALTHCHOP(Z3) + tmc_stealth_enabled.Z3 = stepperZ3.get_stored_stealthChop(); + #endif + #if AXIS_HAS_STEALTHCHOP(Z4) + tmc_stealth_enabled.Z4 = stepperZ4.get_stored_stealthChop(); + #endif + #if AXIS_HAS_STEALTHCHOP(E0) + tmc_stealth_enabled.E0 = stepperE0.get_stored_stealthChop(); + #endif + #if AXIS_HAS_STEALTHCHOP(E1) + tmc_stealth_enabled.E1 = stepperE1.get_stored_stealthChop(); + #endif + #if AXIS_HAS_STEALTHCHOP(E2) + tmc_stealth_enabled.E2 = stepperE2.get_stored_stealthChop(); + #endif + #if AXIS_HAS_STEALTHCHOP(E3) + tmc_stealth_enabled.E3 = stepperE3.get_stored_stealthChop(); + #endif + #if AXIS_HAS_STEALTHCHOP(E4) + tmc_stealth_enabled.E4 = stepperE4.get_stored_stealthChop(); + #endif + #if AXIS_HAS_STEALTHCHOP(E5) + tmc_stealth_enabled.E5 = stepperE5.get_stored_stealthChop(); + #endif + #if AXIS_HAS_STEALTHCHOP(E6) + tmc_stealth_enabled.E6 = stepperE6.get_stored_stealthChop(); + #endif + #if AXIS_HAS_STEALTHCHOP(E7) + tmc_stealth_enabled.E7 = stepperE7.get_stored_stealthChop(); #endif EEPROM_WRITE(tmc_stealth_enabled); } diff --git a/Marlin/src/module/stepper/indirection.h b/Marlin/src/module/stepper/indirection.h index ec0d63a89d97..dfdd63b05ba2 100644 --- a/Marlin/src/module/stepper/indirection.h +++ b/Marlin/src/module/stepper/indirection.h @@ -417,12 +417,15 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset #define NORM_E_DIR(E) do{ E0_DIR_WRITE(E ? INVERT_E0_DIR : !INVERT_E0_DIR); }while(0) #define REV_E_DIR(E) do{ E0_DIR_WRITE(E ? !INVERT_E0_DIR : INVERT_E0_DIR); }while(0) #endif -#elif ENABLED(PRUSA_MMU2) + +#elif HAS_PRUSA_MMU2 + #define E_STEP_WRITE(E,V) E0_STEP_WRITE(V) #define NORM_E_DIR(E) E0_DIR_WRITE(!INVERT_E0_DIR) #define REV_E_DIR(E) E0_DIR_WRITE( INVERT_E0_DIR) -#elif ENABLED(MK2_MULTIPLEXER) // One multiplexed stepper driver, reversed on odd index +#elif HAS_PRUSA_MMU1 // One multiplexed stepper driver, reversed on odd index + #define E_STEP_WRITE(E,V) E0_STEP_WRITE(V) #define NORM_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 0) ? !INVERT_E0_DIR: INVERT_E0_DIR); }while(0) #define REV_E_DIR(E) do{ E0_DIR_WRITE(TEST(E, 0) ? INVERT_E0_DIR: !INVERT_E0_DIR); }while(0) diff --git a/Marlin/src/module/tool_change.cpp b/Marlin/src/module/tool_change.cpp index d77901f029d4..a98193191758 100644 --- a/Marlin/src/module/tool_change.cpp +++ b/Marlin/src/module/tool_change.cpp @@ -73,10 +73,6 @@ #include "../feature/solenoid.h" #endif -#if ENABLED(MK2_MULTIPLEXER) - #include "../feature/snmm.h" -#endif - #if ENABLED(MIXING_EXTRUDER) #include "../feature/mixing.h" #endif @@ -89,8 +85,10 @@ #include "../feature/fanmux.h" #endif -#if ENABLED(PRUSA_MMU2) - #include "../feature/mmu2/mmu2.h" +#if HAS_PRUSA_MMU1 + #include "../feature/mmu/mmu.h" +#elif HAS_PRUSA_MMU2 + #include "../feature/mmu/mmu2.h" #endif #if HAS_LCD_MENU @@ -863,7 +861,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { mixer.T(new_tool); #endif - #elif ENABLED(PRUSA_MMU2) + #elif HAS_PRUSA_MMU2 UNUSED(no_move); @@ -1171,8 +1169,6 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { do_blocking_move_to_z(destination.z, planner.settings.max_feedrate_mm_s[Z_AXIS]); #endif - TERN_(PRUSA_MMU2, mmu2.tool_change(new_tool)); - TERN_(SWITCHING_NOZZLE_TWO_SERVOS, lower_nozzle(new_tool)); } // (new_tool != old_tool) @@ -1184,7 +1180,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { enable_solenoid_on_active_extruder(); #endif - #if ENABLED(MK2_MULTIPLEXER) + #if HAS_PRUSA_MMU1 if (new_tool >= E_STEPPERS) return invalid_extruder_error(new_tool); select_multiplexed_stepper(new_tool); #endif diff --git a/Marlin/src/pins/lpc1768/pins_MKS_SBASE.h b/Marlin/src/pins/lpc1768/pins_MKS_SBASE.h index 2430958895ea..b993e3846087 100644 --- a/Marlin/src/pins/lpc1768/pins_MKS_SBASE.h +++ b/Marlin/src/pins/lpc1768/pins_MKS_SBASE.h @@ -131,9 +131,9 @@ #define PIN_P2_11 P2_11 // Interrupt Capable // -// Průša i3 MK2 Multi Material Multiplexer Support +// Průša i3 MMU1 (Multi Material Multiplexer) Support // -#if ENABLED(MK2_MULTIPLEXER) +#if HAS_PRUSA_MMU1 #define E_MUX0_PIN P1_23 // J8-3 #define E_MUX1_PIN P2_12 // J8-4 #define E_MUX2_PIN P2_11 // J8-5 diff --git a/Marlin/src/pins/pins.h b/Marlin/src/pins/pins.h index b9e12d823315..e9eee4f37126 100644 --- a/Marlin/src/pins/pins.h +++ b/Marlin/src/pins/pins.h @@ -35,7 +35,12 @@ * These numbers are the same in any pin mapping. */ -#define MAX_EXTRUDERS 8 +#if HAS_SMUFF + #define MAX_EXTRUDERS 12 +#else + #define MAX_EXTRUDERS 8 +#endif +#define MAX_E_STEPPERS 8 #if MB(RAMPS_13_EFB, RAMPS_14_EFB, RAMPS_PLUS_EFB, RAMPS_14_RE_ARM_EFB, RAMPS_SMART_EFB, RAMPS_DUO_EFB, RAMPS4DUE_EFB) #define IS_RAMPS_EFB diff --git a/Marlin/src/pins/pins_postprocess.h b/Marlin/src/pins/pins_postprocess.h index 788f2093c117..de70248d4d02 100644 --- a/Marlin/src/pins/pins_postprocess.h +++ b/Marlin/src/pins/pins_postprocess.h @@ -521,7 +521,7 @@ #define X2_STEP_PIN _EPIN(X2_E_INDEX, STEP) #define X2_DIR_PIN _EPIN(X2_E_INDEX, DIR) #define X2_ENABLE_PIN _EPIN(X2_E_INDEX, ENABLE) - #if X2_E_INDEX >= MAX_EXTRUDERS || !PIN_EXISTS(X2_STEP) + #if X2_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(X2_STEP) #error "No E stepper plug left for X2!" #endif #endif @@ -594,7 +594,7 @@ #define Y2_STEP_PIN _EPIN(Y2_E_INDEX, STEP) #define Y2_DIR_PIN _EPIN(Y2_E_INDEX, DIR) #define Y2_ENABLE_PIN _EPIN(Y2_E_INDEX, ENABLE) - #if Y2_E_INDEX >= MAX_EXTRUDERS || !PIN_EXISTS(Y2_STEP) + #if Y2_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(Y2_STEP) #error "No E stepper plug left for Y2!" #endif #endif @@ -662,7 +662,7 @@ #define Z2_STEP_PIN _EPIN(Z2_E_INDEX, STEP) #define Z2_DIR_PIN _EPIN(Z2_E_INDEX, DIR) #define Z2_ENABLE_PIN _EPIN(Z2_E_INDEX, ENABLE) - #if Z2_E_INDEX >= MAX_EXTRUDERS || !PIN_EXISTS(Z2_STEP) + #if Z2_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(Z2_STEP) #error "No E stepper plug left for Z2!" #endif #endif @@ -729,7 +729,7 @@ #define Z3_STEP_PIN _EPIN(Z3_E_INDEX, STEP) #define Z3_DIR_PIN _EPIN(Z3_E_INDEX, DIR) #define Z3_ENABLE_PIN _EPIN(Z3_E_INDEX, ENABLE) - #if Z3_E_INDEX >= MAX_EXTRUDERS || !PIN_EXISTS(Z3_STEP) + #if Z3_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(Z3_STEP) #error "No E stepper plug left for Z3!" #endif #endif @@ -796,7 +796,7 @@ #define Z4_STEP_PIN _EPIN(Z4_E_INDEX, STEP) #define Z4_DIR_PIN _EPIN(Z4_E_INDEX, DIR) #define Z4_ENABLE_PIN _EPIN(Z4_E_INDEX, ENABLE) - #if Z4_E_INDEX >= MAX_EXTRUDERS || !PIN_EXISTS(Z4_STEP) + #if Z4_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(Z4_STEP) #error "No E stepper plug left for Z4!" #endif #endif diff --git a/Marlin/src/pins/stm32f4/pins_BTT_GTR_V1_0.h b/Marlin/src/pins/stm32f4/pins_BTT_GTR_V1_0.h index eaf90da1aee4..eb1e886fa4fe 100644 --- a/Marlin/src/pins/stm32f4/pins_BTT_GTR_V1_0.h +++ b/Marlin/src/pins/stm32f4/pins_BTT_GTR_V1_0.h @@ -25,8 +25,8 @@ #error "Oops! Select an STM32F4 board in 'Tools > Board.'" #elif HOTENDS > 8 || E_STEPPERS > 8 #error "BIGTREE GTR V1.0 supports up to 8 hotends / E-steppers." -#elif HOTENDS > MAX_EXTRUDERS || E_STEPPERS > MAX_EXTRUDERS - #error "Marlin extruder/hotends limit! Increase MAX_EXTRUDERS to continue." +#elif HOTENDS > MAX_E_STEPPERS || E_STEPPERS > MAX_E_STEPPERS + #error "Marlin extruder/hotends limit! Increase MAX_E_STEPPERS to continue." #endif #define BOARD_INFO_NAME "BTT GTR V1.0" diff --git a/buildroot/tests/mega2560-tests b/buildroot/tests/mega2560-tests index 113ec9ed1bd0..294de2a767d1 100755 --- a/buildroot/tests/mega2560-tests +++ b/buildroot/tests/mega2560-tests @@ -66,28 +66,38 @@ exec_test $1 $2 "Azteeg X3 Pro | EXTRUDERS 5 | RRDFGSC | UBL | LIN_ADVANCE | Sle # restore_configs opt_set LCD_LANGUAGE zh_CN +opt_set MMU_MODEL PRUSA_MMU2S opt_set EXTRUDERS 5 opt_set NUM_SERVOS 1 opt_enable ZONESTAR_LCD Z_PROBE_SERVO_NR Z_SERVO_ANGLES DEACTIVATE_SERVOS_AFTER_MOVE BOOT_MARLIN_LOGO_ANIMATED \ AUTO_BED_LEVELING_3POINT DEBUG_LEVELING_FEATURE EEPROM_SETTINGS EEPROM_CHITCHAT M114_DETAIL \ NO_VOLUMETRICS EXTENDED_CAPABILITIES_REPORT AUTO_REPORT_TEMPERATURES AUTOTEMP G38_PROBE_TARGET JOYSTICK \ - PRUSA_MMU2 MMU2_MENUS PRUSA_MMU2_S_MODE DIRECT_STEPPING DETECT_BROKEN_ENDSTOP \ + MMU2_MENUS DIRECT_STEPPING DETECT_BROKEN_ENDSTOP \ FILAMENT_RUNOUT_SENSOR NOZZLE_PARK_FEATURE ADVANCED_PAUSE_FEATURE Z_SAFE_HOMING -exec_test $1 $2 "RAMPS | ZONESTAR + Chinese | MMU2 | Servo | 3-Point + Debug | G38 ..." "$3" +exec_test $1 $2 "RAMPS | ZONESTAR + Chinese | MMU2S | Servo | 3-Point + Debug | G38 ..." "$3" # # 5 runout sensors with distinct states # restore_configs +opt_set MOTHERBOARD BOARD_AZTEEG_X3_PRO opt_set EXTRUDERS 5 opt_set NUM_SERVOS 1 +opt_set TEMP_SENSOR_1 1 +opt_set TEMP_SENSOR_2 1 +opt_set TEMP_SENSOR_3 1 +opt_set TEMP_SENSOR_4 1 opt_enable ZONESTAR_LCD Z_PROBE_SERVO_NR Z_SERVO_ANGLES DEACTIVATE_SERVOS_AFTER_MOVE BOOT_MARLIN_LOGO_ANIMATED \ AUTO_BED_LEVELING_3POINT DEBUG_LEVELING_FEATURE EEPROM_SETTINGS EEPROM_CHITCHAT M114_DETAIL \ NO_VOLUMETRICS EXTENDED_CAPABILITIES_REPORT AUTO_REPORT_TEMPERATURES AUTOTEMP G38_PROBE_TARGET JOYSTICK \ - PRUSA_MMU2 MMU2_MENUS PRUSA_MMU2_S_MODE DIRECT_STEPPING DETECT_BROKEN_ENDSTOP \ + DIRECT_STEPPING DETECT_BROKEN_ENDSTOP \ FILAMENT_RUNOUT_SENSOR NOZZLE_PARK_FEATURE ADVANCED_PAUSE_FEATURE Z_SAFE_HOMING FIL_RUNOUT3_PULL -opt_set MIXING_STEPPERS 5 +opt_set NUM_RUNOUT_SENSORS 5 +opt_set FIL_RUNOUT2_PIN 44 +opt_set FIL_RUNOUT3_PIN 45 opt_set FIL_RUNOUT3_STATE HIGH +opt_set FIL_RUNOUT4_PIN 46 +opt_set FIL_RUNOUT5_PIN 47 exec_test $1 $2 "Multiple runout sensors (x5) | Distinct runout states" # diff --git a/platformio.ini b/platformio.ini index 1e0b84b6255a..862c42b01b79 100644 --- a/platformio.ini +++ b/platformio.ini @@ -93,7 +93,8 @@ default_src_filter = + - - + - - - - - - + - + - - - - - - @@ -101,7 +102,6 @@ default_src_filter = + - - + - - - - - - - - - - - - - @@ -304,7 +304,8 @@ PRINTER_EVENT_LEDS = src_filter=+ TEMP_STAT_LEDS = src_filter=+ MAX7219_DEBUG = src_filter=+ + MIXING_EXTRUDER = src_filter=+ + -PRUSA_MMU2 = src_filter=+ + +HAS_PRUSA_MMU1 = src_filter=+ +HAS_PRUSA_MMU2 = src_filter=+ + PASSWORD_FEATURE = src_filter=+ + ADVANCED_PAUSE_FEATURE = src_filter=+ + + AUTO_POWER_CONTROL = src_filter=+ @@ -312,8 +313,7 @@ HAS_POWER_MONITOR = src_filter=+ + + PROBE_TEMP_COMPENSATION = src_filter=+ + HAS_FILAMENT_SENSOR = src_filter=+ + -MK2_MULTIPLEXER = src_filter=+ -EXT_SOLENOID|MANUAL_SOLENOID_CONTROL = src_filter=+ + +(EXT|MANUAL)_SOLENOID.* = src_filter=+ + HAS_CUTTER = src_filter=+ + EXPERIMENTAL_I2CBUS = src_filter=+ + MECHANICAL_GANTRY_CAL.+ = src_filter=+