SMUFF (MMU2 clone) support (#19912)
This commit is contained in:
@ -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
|
@ -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
|
||||
};
|
||||
|
||||
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
|
||||
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 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;
|
||||
}
|
||||
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;
|
||||
#else
|
||||
BUZZ(400, 40);
|
||||
#endif
|
||||
} 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
set_runout_valid(true);
|
||||
|
||||
#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;
|
||||
/**
|
||||
* Handle tool change
|
||||
*/
|
||||
void MMU2::tool_change(const uint8_t index) {
|
||||
if (!enabled) return;
|
||||
|
||||
set_runout_valid(false);
|
||||
set_runout_valid(false);
|
||||
|
||||
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();
|
||||
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(true);
|
||||
}
|
||||
|
||||
set_runout_valid(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
#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);
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
command(MMU_CMD_T0 + index);
|
||||
manage_response(true, true);
|
||||
|
||||
const bool success = load_to_gears();
|
||||
if (success) {
|
||||
mmu_loop();
|
||||
extruder = index;
|
||||
active_extruder = 0;
|
||||
load_to_nozzle();
|
||||
BUZZ(200, 404);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
|
||||
bool MMU2::eject_filament(const uint8_t index, const bool recover) {
|
||||
|
||||
if (!enabled) return false;
|
||||
|
||||
if (thermalManager.tooColdToExtrude(active_extruder)) {
|
||||
BUZZ(200, 404);
|
||||
LCD_ALERTMESSAGEPGM(MSG_HOTEND_TOO_COLD);
|
||||
return false;
|
||||
}
|
||||
|
||||
LCD_MESSAGEPGM(MSG_MMU2_EJECTING_FILAMENT);
|
||||
|
||||
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);
|
||||
|
||||
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();
|
||||
|
||||
// no active tool
|
||||
extruder = MMU2_NO_TOOL;
|
||||
|
||||
set_runout_valid(false);
|
||||
|
||||
BUZZ(200, 404);
|
||||
|
||||
DISABLE_AXIS_E0();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unload from hotend and retract to MMU
|
||||
*/
|
||||
bool MMU2::unload() {
|
||||
|
||||
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) {
|
||||
filament_ramming();
|
||||
|
||||
if (!enabled) return false;
|
||||
command(MMU_CMD_U0);
|
||||
manage_response(false, true);
|
||||
|
||||
if (thermalManager.tooColdToExtrude(active_extruder)) {
|
||||
BUZZ(200, 404);
|
||||
LCD_ALERTMESSAGEPGM(MSG_HOTEND_TOO_COLD);
|
||||
return false;
|
||||
}
|
||||
BUZZ(200, 404);
|
||||
|
||||
command(MMU_CMD_T0 + index);
|
||||
manage_response(true, true);
|
||||
// no active tool
|
||||
extruder = MMU2_NO_TOOL;
|
||||
|
||||
const bool success = load_to_gears();
|
||||
if (success) {
|
||||
mmu_loop();
|
||||
extruder = index;
|
||||
active_extruder = 0;
|
||||
load_to_nozzle();
|
||||
BUZZ(200, 404);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
set_runout_valid(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));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MMU2::eject_filament(const uint8_t index, const bool recover) {
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
|
||||
if (!enabled) return false;
|
||||
void MMU2::execute_extruder_sequence(const E_Step * sequence, int steps) {
|
||||
|
||||
if (thermalManager.tooColdToExtrude(active_extruder)) {
|
||||
BUZZ(200, 404);
|
||||
LCD_ALERTMESSAGEPGM(MSG_HOTEND_TOO_COLD);
|
||||
return false;
|
||||
}
|
||||
planner.synchronize();
|
||||
ENABLE_AXIS_E0();
|
||||
|
||||
LCD_MESSAGEPGM(MSG_MMU2_EJECTING_FILAMENT);
|
||||
const E_Step* step = sequence;
|
||||
|
||||
ENABLE_AXIS_E0();
|
||||
current_position.e -= MMU2_FILAMENTCHANGE_EJECT_FEED;
|
||||
line_to_current_position(2500 / 60);
|
||||
LOOP_L_N(i, steps) {
|
||||
const float es = pgm_read_float(&(step->extrude));
|
||||
const feedRate_t fr_mm_m = pgm_read_float(&(step->feedRate));
|
||||
|
||||
DEBUG_ECHO_START();
|
||||
DEBUG_ECHOLNPAIR("E step ", es, "/", fr_mm_m);
|
||||
|
||||
current_position.e += es;
|
||||
line_to_current_position(MMM_TO_MMS(fr_mm_m));
|
||||
planner.synchronize();
|
||||
command(MMU_CMD_E0 + index);
|
||||
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();
|
||||
|
||||
// no active tool
|
||||
extruder = MMU2_NO_TOOL;
|
||||
|
||||
set_runout_valid(false);
|
||||
|
||||
BUZZ(200, 404);
|
||||
|
||||
DISABLE_AXIS_E0();
|
||||
|
||||
return true;
|
||||
step++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unload from hotend and retract to MMU
|
||||
*/
|
||||
bool MMU2::unload() {
|
||||
DISABLE_AXIS_E0();
|
||||
}
|
||||
|
||||
if (!enabled) return false;
|
||||
|
||||
if (thermalManager.tooColdToExtrude(active_extruder)) {
|
||||
BUZZ(200, 404);
|
||||
LCD_ALERTMESSAGEPGM(MSG_HOTEND_TOO_COLD);
|
||||
return false;
|
||||
}
|
||||
|
||||
filament_ramming();
|
||||
|
||||
command(MMU_CMD_U0);
|
||||
manage_response(false, true);
|
||||
|
||||
BUZZ(200, 404);
|
||||
|
||||
// no active tool
|
||||
extruder = MMU2_NO_TOOL;
|
||||
|
||||
set_runout_valid(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
|
||||
void MMU2::execute_extruder_sequence(const E_Step * sequence, int steps) {
|
||||
|
||||
planner.synchronize();
|
||||
ENABLE_AXIS_E0();
|
||||
|
||||
const E_Step* step = sequence;
|
||||
|
||||
LOOP_L_N(i, steps) {
|
||||
const float es = pgm_read_float(&(step->extrude));
|
||||
const feedRate_t fr_mm_m = pgm_read_float(&(step->feedRate));
|
||||
|
||||
DEBUG_ECHO_START();
|
||||
DEBUG_ECHOLNPAIR("E step ", es, "/", fr_mm_m);
|
||||
|
||||
current_position.e += es;
|
||||
line_to_current_position(MMM_TO_MMS(fr_mm_m));
|
||||
planner.synchronize();
|
||||
|
||||
step++;
|
||||
}
|
||||
|
||||
DISABLE_AXIS_E0();
|
||||
}
|
||||
|
||||
#endif // HAS_LCD_MENU && MMU2_MENUS
|
||||
|
||||
#endif // PRUSA_MMU2
|
||||
#endif // HAS_PRUSA_MMU2
|
@ -49,13 +49,11 @@ public:
|
||||
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 @@ private:
|
||||
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();
|
Reference in New Issue
Block a user