diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index a69cecf4a0..38c4ae4c94 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -150,6 +150,13 @@ // For Cyclops or any "multi-extruder" that shares a single nozzle. //#define SINGLENOZZLE +// Save and restore temperature and fan speed on tool-change. +// Set standby for the unselected tool with M104/106/109 T... +#if ENABLED(SINGLENOZZLE) + //#define SINGLENOZZLE_STANDBY_TEMP + //#define SINGLENOZZLE_STANDBY_FAN +#endif + /** * Průša MK2 Single Nozzle Multi-Material Multiplexer, and variants. * diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index fb82aed698..86a240e7db 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -1889,7 +1889,7 @@ // (May break filament if not retracted beforehand.) //#define TOOLCHANGE_FS_INIT_BEFORE_SWAP - // Prime on the first T command even if the same or no toolchange / swap + // Prime on the first T0 (If other, TOOLCHANGE_FS_INIT_BEFORE_SWAP applied) // Enable it (M217 V[0/1]) before printing, to avoid unwanted priming on host connect //#define TOOLCHANGE_FS_PRIME_FIRST_USED diff --git a/Marlin/src/gcode/temp/M104_M109.cpp b/Marlin/src/gcode/temp/M104_M109.cpp index eec97df9e6..bb453412d7 100644 --- a/Marlin/src/gcode/temp/M104_M109.cpp +++ b/Marlin/src/gcode/temp/M104_M109.cpp @@ -65,7 +65,7 @@ void GcodeSuite::M104() { if (parser.seenval('S')) { const int16_t temp = parser.value_celsius(); - #if ENABLED(SINGLENOZZLE) + #if ENABLED(SINGLENOZZLE_STANDBY_TEMP) singlenozzle_temp[target_extruder] = temp; if (target_extruder != active_extruder) return; #endif @@ -111,7 +111,7 @@ void GcodeSuite::M109() { set_temp = no_wait_for_cooling || parser.seenval('R'); if (set_temp) { const int16_t temp = parser.value_celsius(); - #if ENABLED(SINGLENOZZLE) + #if ENABLED(SINGLENOZZLE_STANDBY_TEMP) singlenozzle_temp[target_extruder] = temp; if (target_extruder != active_extruder) return; #endif diff --git a/Marlin/src/lcd/menu/menu_temperature.cpp b/Marlin/src/lcd/menu/menu_temperature.cpp index 9be20b52e2..5526848939 100644 --- a/Marlin/src/lcd/menu/menu_temperature.cpp +++ b/Marlin/src/lcd/menu/menu_temperature.cpp @@ -168,8 +168,9 @@ void menu_temperature() { EDIT_ITEM_FAST_N(int3, e, MSG_NOZZLE_N, &thermalManager.temp_hotend[e].target, 0, thermalManager.heater_maxtemp[e] - HOTEND_OVERSHOOT, []{ thermalManager.start_watching_hotend(MenuItemBase::itemIndex); }); #endif - #if ENABLED(SINGLENOZZLE) - EDIT_ITEM_FAST(uint16_3, MSG_NOZZLE_STANDBY, &singlenozzle_temp[active_extruder ? 0 : 1], 0, HEATER_0_MAXTEMP - HOTEND_OVERSHOOT); + #if ENABLED(SINGLENOZZLE_STANDBY_TEMP) + LOOP_S_L_N(e, 1, EXTRUDERS) + EDIT_ITEM_FAST_N(uint16_3, e, MSG_NOZZLE_STANDBY, &singlenozzle_temp[e], 0, thermalManager.heater_maxtemp[0] - HOTEND_OVERSHOOT); #endif // @@ -207,11 +208,11 @@ void menu_temperature() { }; #endif - #define SNFAN(N) (ENABLED(SINGLENOZZLE) && !HAS_FAN##N && EXTRUDERS > N) + #define SNFAN(N) (ENABLED(SINGLENOZZLE_STANDBY_FAN) && !HAS_FAN##N && EXTRUDERS > N) #if SNFAN(1) || SNFAN(2) || SNFAN(3) || SNFAN(4) || SNFAN(5) || SNFAN(6) || SNFAN(7) auto singlenozzle_item = [&](const uint8_t f) { MENU_ITEM_IF(1) { - editable.uint8 = thermalManager.fan_speed[f]; + editable.uint8 = singlenozzle_fan_speed[f]; EDIT_ITEM_FAST_N(percent, f, MSG_STORED_FAN_N, &editable.uint8, 0, 255, on_fan_update); } }; diff --git a/Marlin/src/lcd/menu/menu_tune.cpp b/Marlin/src/lcd/menu/menu_tune.cpp index cc5b6e4770..e510bae634 100644 --- a/Marlin/src/lcd/menu/menu_tune.cpp +++ b/Marlin/src/lcd/menu/menu_tune.cpp @@ -124,8 +124,9 @@ void menu_tune() { EDIT_ITEM_FAST_N(int3, e, MSG_NOZZLE_N, &thermalManager.temp_hotend[e].target, 0, thermalManager.heater_maxtemp[e] - HOTEND_OVERSHOOT, []{ thermalManager.start_watching_hotend(MenuItemBase::itemIndex); }); #endif - #if ENABLED(SINGLENOZZLE) - EDIT_ITEM_FAST(uint16_3, MSG_NOZZLE_STANDBY, &singlenozzle_temp[active_extruder ? 0 : 1], 0, HEATER_0_MAXTEMP - HOTEND_OVERSHOOT); + #if ENABLED(SINGLENOZZLE_STANDBY_TEMP) + LOOP_S_L_N(e, 1, EXTRUDERS) + EDIT_ITEM_FAST_N(uint16_3, e, MSG_NOZZLE_STANDBY, &singlenozzle_temp[e], 0, thermalManager.heater_maxtemp[0] - HOTEND_OVERSHOOT); #endif // @@ -156,11 +157,11 @@ void menu_tune() { }; #endif - #define SNFAN(N) (ENABLED(SINGLENOZZLE) && !HAS_FAN##N && EXTRUDERS > N) + #define SNFAN(N) (ENABLED(SINGLENOZZLE_STANDBY_FAN) && !HAS_FAN##N && EXTRUDERS > N) #if SNFAN(1) || SNFAN(2) || SNFAN(3) || SNFAN(4) || SNFAN(5) || SNFAN(6) || SNFAN(7) auto singlenozzle_item = [&](const uint8_t f) { MENU_ITEM_IF(1) { - editable.uint8 = thermalManager.fan_speed[f]; + editable.uint8 = singlenozzle_fan_speed[f]; EDIT_ITEM_FAST_N(percent, f, MSG_STORED_FAN_N, &editable.uint8, 0, 255, on_fan_update); } }; diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index ad9dffe4ea..4e675f075d 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -2861,6 +2861,17 @@ void Planner::set_max_jerk(const AxisEnum axis, float targetValue) { #if ENABLED(AUTOTEMP) +void Planner::autotemp_update() { + + #if ENABLED(AUTOTEMP_PROPORTIONAL) + const int16_t target = thermalManager.degTargetHotend(active_extruder); + autotemp_min = target + AUTOTEMP_MIN_P; + autotemp_max = target + AUTOTEMP_MAX_P; + #endif + autotemp_factor = TERN(AUTOTEMP_PROPORTIONAL, AUTOTEMP_FACTOR_P, 0); + autotemp_enabled = autotemp_factor != 0; +} + void Planner::autotemp_M104_M109() { #if ENABLED(AUTOTEMP_PROPORTIONAL) diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h index ebfb8dcb9e..7b029cba01 100644 --- a/Marlin/src/module/planner.h +++ b/Marlin/src/module/planner.h @@ -824,6 +824,7 @@ class Planner { static bool autotemp_enabled; static void getHighESpeed(); static void autotemp_M104_M109(); + static void autotemp_update(); #endif #if HAS_LINEAR_E_JERK diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index e55dcb074b..78f8a19cf6 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -193,7 +193,7 @@ const char str_t_thermal_runaway[] PROGMEM = STR_T_THERMAL_RUNAWAY, NOMORE(speed, 255U); - #if ENABLED(SINGLENOZZLE) + #if ENABLED(SINGLENOZZLE_STANDBY_FAN) if (target != active_extruder) { if (target < EXTRUDERS) singlenozzle_fan_speed[target] = speed; return; diff --git a/Marlin/src/module/tool_change.cpp b/Marlin/src/module/tool_change.cpp index 9908d37cda..c0f7909a3c 100644 --- a/Marlin/src/module/tool_change.cpp +++ b/Marlin/src/module/tool_change.cpp @@ -47,11 +47,12 @@ bool toolchange_extruder_ready[EXTRUDERS]; #endif -#if ENABLED(SINGLENOZZLE) +#if ENABLED(SINGLENOZZLE_STANDBY_TEMP) uint16_t singlenozzle_temp[EXTRUDERS]; - #if HAS_FAN - uint8_t singlenozzle_fan_speed[EXTRUDERS]; - #endif +#endif + +#if BOTH(HAS_FAN, SINGLENOZZLE_STANDBY_FAN) + uint8_t singlenozzle_fan_speed[EXTRUDERS]; #endif #if ENABLED(MAGNETIC_PARKING_EXTRUDER) || defined(EVENT_GCODE_AFTER_TOOLCHANGE) || (ENABLED(PARKING_EXTRUDER) && PARKING_EXTRUDER_SOLENOIDS_DELAY > 0) @@ -822,7 +823,7 @@ void tool_change_prime() { #if TOOLCHANGE_FS_FAN >= 0 && HAS_FAN const int16_t fansp = thermalManager.fan_speed[TOOLCHANGE_FS_FAN]; thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = toolchange_settings.fan_speed; - safe_delay(toolchange_settings.fan_time * 1000); + gcode.dwell(toolchange_settings.fan_time * 1000); thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = fansp; #endif @@ -934,7 +935,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { // Z raise before retraction #if ENABLED(TOOLCHANGE_ZRAISE_BEFORE_RETRACT) && DISABLED(SWITCHING_NOZZLE) - if (can_move_away && TERN1(toolchange_settings.enable_park)) { + if (can_move_away && TERN1(TOOLCHANGE_PARK, toolchange_settings.enable_park)) { // Do a small lift to avoid the workpiece in the move back (below) current_position.z += toolchange_settings.z_raise; #if HAS_SOFTWARE_ENDSTOPS @@ -956,8 +957,12 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { SERIAL_ECHO_MSG(STR_ERR_HOTEND_TOO_COLD); if (ENABLED(SINGLENOZZLE)) { active_extruder = new_tool; return; } } - else - unscaled_e_move(-toolchange_settings.swap_length, MMM_TO_MMS(toolchange_settings.retract_speed)); + else { + // If first new tool, toolchange without unloading the old not initialized 'Just prime/init the new' + if (first_tool_is_primed) + unscaled_e_move(-toolchange_settings.swap_length, MMM_TO_MMS(toolchange_settings.retract_speed)); + first_tool_is_primed = true; // The first new tool will be primed by toolchanging + } } #endif @@ -1059,15 +1064,16 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { const bool should_move = safe_to_move && !no_move && IsRunning(); if (should_move) { - #if ENABLED(SINGLENOZZLE) - #if HAS_FAN - singlenozzle_fan_speed[old_tool] = thermalManager.fan_speed[0]; - thermalManager.fan_speed[0] = singlenozzle_fan_speed[new_tool]; - #endif + #if BOTH(HAS_FAN, SINGLENOZZLE_STANDBY_FAN) + singlenozzle_fan_speed[old_tool] = thermalManager.fan_speed[0]; + thermalManager.fan_speed[0] = singlenozzle_fan_speed[new_tool]; + #endif + #if ENABLED(SINGLENOZZLE_STANDBY_TEMP) singlenozzle_temp[old_tool] = thermalManager.temp_hotend[0].target; if (singlenozzle_temp[new_tool] && singlenozzle_temp[new_tool] != singlenozzle_temp[old_tool]) { thermalManager.setTargetHotend(singlenozzle_temp[new_tool], 0); + TERN_(AUTOTEMP, planner.autotemp_update()); TERN_(HAS_DISPLAY, thermalManager.set_heating_message(0)); (void)thermalManager.wait_for_hotend(0, false); // Wait for heating or cooling } @@ -1101,7 +1107,7 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { #if TOOLCHANGE_FS_FAN >= 0 && HAS_FAN const int16_t fansp = thermalManager.fan_speed[TOOLCHANGE_FS_FAN]; thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = toolchange_settings.fan_speed; - safe_delay(toolchange_settings.fan_time * 1000); + gcode.dwell(toolchange_settings.fan_time * 1000); thermalManager.fan_speed[TOOLCHANGE_FS_FAN] = fansp; #endif } @@ -1245,10 +1251,9 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { // Migrate the temperature to the new hotend #if HAS_MULTI_HOTEND - thermalManager.setTargetHotend(thermalManager.degTargetHotend(active_extruder), migration_extruder); - #if HAS_DISPLAY - thermalManager.set_heating_message(0); - #endif + thermalManager.setTargetHotend(thermalManager.temp_hotend[active_extruder].target, migration_extruder); + TERN_(AUTOTEMP, planner.autotemp_update()); + TERN_(HAS_DISPLAY, thermalManager.set_heating_message(0)); thermalManager.wait_for_hotend(active_extruder); #endif diff --git a/Marlin/src/module/tool_change.h b/Marlin/src/module/tool_change.h index 7e73bd7bb2..4b004950ab 100644 --- a/Marlin/src/module/tool_change.h +++ b/Marlin/src/module/tool_change.h @@ -108,11 +108,12 @@ #endif -#if ENABLED(SINGLENOZZLE) +#if ENABLED(SINGLENOZZLE_STANDBY_TEMP) extern uint16_t singlenozzle_temp[EXTRUDERS]; - #if HAS_FAN - extern uint8_t singlenozzle_fan_speed[EXTRUDERS]; - #endif +#endif + +#if BOTH(HAS_FAN, SINGLENOZZLE_STANDBY_FAN) + extern uint8_t singlenozzle_fan_speed[EXTRUDERS]; #endif TERN_(ELECTROMAGNETIC_SWITCHING_TOOLHEAD, void est_init());