|
@ -90,7 +90,7 @@ bool MMU2::enabled, MMU2::ready, MMU2::mmu_print_saved; |
|
|
uint8_t MMU2::cmd, MMU2::cmd_arg, MMU2::last_cmd, MMU2::extruder; |
|
|
uint8_t MMU2::cmd, MMU2::cmd_arg, MMU2::last_cmd, MMU2::extruder; |
|
|
int8_t MMU2::state = 0; |
|
|
int8_t MMU2::state = 0; |
|
|
volatile int8_t MMU2::finda = 1; |
|
|
volatile int8_t MMU2::finda = 1; |
|
|
volatile bool MMU2::findaRunoutValid; |
|
|
volatile bool MMU2::finda_runout_valid; |
|
|
int16_t MMU2::version = -1, MMU2::buildnr = -1; |
|
|
int16_t MMU2::version = -1, MMU2::buildnr = -1; |
|
|
millis_t MMU2::last_request, MMU2::next_P0_request; |
|
|
millis_t MMU2::last_request, MMU2::next_P0_request; |
|
|
char MMU2::rx_buffer[16], MMU2::tx_buffer[16]; |
|
|
char MMU2::rx_buffer[16], MMU2::tx_buffer[16]; |
|
@ -103,7 +103,7 @@ char MMU2::rx_buffer[16], MMU2::tx_buffer[16]; |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
static constexpr E_Step ramming_sequence[] PROGMEM = { MMU2_RAMMING_SEQUENCE }; |
|
|
static constexpr E_Step ramming_sequence[] PROGMEM = { MMU2_RAMMING_SEQUENCE }; |
|
|
static constexpr E_Step loadToNozzle_sequence[] PROGMEM = { MMU2_LOAD_TO_NOZZLE_SEQUENCE }; |
|
|
static constexpr E_Step load_to_nozzle_sequence[] PROGMEM = { MMU2_LOAD_TO_NOZZLE_SEQUENCE }; |
|
|
|
|
|
|
|
|
#endif // MMU2_MENUS
|
|
|
#endif // MMU2_MENUS
|
|
|
|
|
|
|
|
@ -142,11 +142,11 @@ void MMU2::reset() { |
|
|
#endif |
|
|
#endif |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
uint8_t MMU2::getCurrentTool() { |
|
|
uint8_t MMU2::get_current_tool() { |
|
|
return extruder == MMU2_NO_TOOL ? -1 : extruder; |
|
|
return extruder == MMU2_NO_TOOL ? -1 : extruder; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void MMU2::mmuLoop() { |
|
|
void MMU2::mmu_loop() { |
|
|
|
|
|
|
|
|
switch (state) { |
|
|
switch (state) { |
|
|
|
|
|
|
|
@ -185,7 +185,7 @@ void MMU2::mmuLoop() { |
|
|
|
|
|
|
|
|
DEBUG_ECHOLNPAIR("MMU => ", buildnr); |
|
|
DEBUG_ECHOLNPAIR("MMU => ", buildnr); |
|
|
|
|
|
|
|
|
checkVersion(); |
|
|
check_version(); |
|
|
|
|
|
|
|
|
#if ENABLED(MMU2_MODE_12V) |
|
|
#if ENABLED(MMU2_MODE_12V) |
|
|
DEBUG_ECHOLNPGM("MMU <= 'M1'"); |
|
|
DEBUG_ECHOLNPGM("MMU <= 'M1'"); |
|
@ -207,7 +207,7 @@ void MMU2::mmuLoop() { |
|
|
if (rx_ok()) { |
|
|
if (rx_ok()) { |
|
|
DEBUG_ECHOLNPGM("MMU => ok"); |
|
|
DEBUG_ECHOLNPGM("MMU => ok"); |
|
|
|
|
|
|
|
|
checkVersion(); |
|
|
check_version(); |
|
|
|
|
|
|
|
|
DEBUG_ECHOLNPGM("MMU <= 'P0'"); |
|
|
DEBUG_ECHOLNPGM("MMU <= 'P0'"); |
|
|
|
|
|
|
|
@ -294,13 +294,13 @@ void MMU2::mmuLoop() { |
|
|
sscanf(rx_buffer, "%hhuok\n", &finda); |
|
|
sscanf(rx_buffer, "%hhuok\n", &finda); |
|
|
|
|
|
|
|
|
// This is super annoying. Only activate if necessary
|
|
|
// This is super annoying. Only activate if necessary
|
|
|
// if (findaRunoutValid) DEBUG_ECHOLNPAIR_F("MMU <= 'P0'\nMMU => ", finda, 6);
|
|
|
// if (finda_runout_valid) DEBUG_ECHOLNPAIR_F("MMU <= 'P0'\nMMU => ", finda, 6);
|
|
|
|
|
|
|
|
|
state = 1; |
|
|
state = 1; |
|
|
|
|
|
|
|
|
if (cmd == 0) ready = true; |
|
|
if (cmd == 0) ready = true; |
|
|
|
|
|
|
|
|
if (!finda && findaRunoutValid) filamentRunout(); |
|
|
if (!finda && finda_runout_valid) filament_runout(); |
|
|
} |
|
|
} |
|
|
else if (ELAPSED(millis(), last_request + MMU_P0_TIMEOUT)) // Resend request after timeout (30s)
|
|
|
else if (ELAPSED(millis(), last_request + MMU_P0_TIMEOUT)) // Resend request after timeout (30s)
|
|
|
state = 1; |
|
|
state = 1; |
|
@ -434,7 +434,7 @@ bool MMU2::rx_ok() { |
|
|
/**
|
|
|
/**
|
|
|
* Check if MMU has compatible firmware |
|
|
* Check if MMU has compatible firmware |
|
|
*/ |
|
|
*/ |
|
|
void MMU2::checkVersion() { |
|
|
void MMU2::check_version() { |
|
|
if (buildnr < MMU_REQUIRED_FW_BUILDNR) { |
|
|
if (buildnr < MMU_REQUIRED_FW_BUILDNR) { |
|
|
SERIAL_ERROR_START(); |
|
|
SERIAL_ERROR_START(); |
|
|
SERIAL_ECHOPGM("MMU2 firmware version invalid. Required version >= "); |
|
|
SERIAL_ECHOPGM("MMU2 firmware version invalid. Required version >= "); |
|
@ -447,7 +447,7 @@ void MMU2::checkVersion() { |
|
|
/**
|
|
|
/**
|
|
|
* Handle tool change |
|
|
* Handle tool change |
|
|
*/ |
|
|
*/ |
|
|
void MMU2::toolChange(uint8_t index) { |
|
|
void MMU2::tool_change(uint8_t index) { |
|
|
|
|
|
|
|
|
if (!enabled) return; |
|
|
if (!enabled) return; |
|
|
|
|
|
|
|
@ -461,7 +461,7 @@ void MMU2::toolChange(uint8_t index) { |
|
|
|
|
|
|
|
|
command(MMU_CMD_T0 + index); |
|
|
command(MMU_CMD_T0 + index); |
|
|
|
|
|
|
|
|
manageResponse(true, true); |
|
|
manage_response(true, true); |
|
|
KEEPALIVE_STATE(IN_HANDLER); |
|
|
KEEPALIVE_STATE(IN_HANDLER); |
|
|
|
|
|
|
|
|
command(MMU_CMD_C0); |
|
|
command(MMU_CMD_C0); |
|
@ -490,7 +490,7 @@ void MMU2::toolChange(uint8_t index) { |
|
|
* Tc Load to nozzle after filament was prepared by Tx and extruder nozzle is already heated. |
|
|
* Tc Load to nozzle after filament was prepared by Tx and extruder nozzle is already heated. |
|
|
* |
|
|
* |
|
|
*/ |
|
|
*/ |
|
|
void MMU2::toolChange(const char* special) { |
|
|
void MMU2::tool_change(const char* special) { |
|
|
|
|
|
|
|
|
if (!enabled) return; |
|
|
if (!enabled) return; |
|
|
|
|
|
|
|
@ -501,19 +501,19 @@ void MMU2::toolChange(const char* special) { |
|
|
|
|
|
|
|
|
switch (*special) { |
|
|
switch (*special) { |
|
|
case '?': { |
|
|
case '?': { |
|
|
uint8_t index = mmu2_chooseFilament(); |
|
|
uint8_t index = mmu2_choose_filament(); |
|
|
while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100); |
|
|
while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100); |
|
|
loadFilamentToNozzle(index); |
|
|
load_filament_to_nozzle(index); |
|
|
} break; |
|
|
} break; |
|
|
|
|
|
|
|
|
case 'x': { |
|
|
case 'x': { |
|
|
planner.synchronize(); |
|
|
planner.synchronize(); |
|
|
uint8_t index = mmu2_chooseFilament(); |
|
|
uint8_t index = mmu2_choose_filament(); |
|
|
disable_E0(); |
|
|
disable_E0(); |
|
|
command(MMU_CMD_T0 + index); |
|
|
command(MMU_CMD_T0 + index); |
|
|
manageResponse(true, true); |
|
|
manage_response(true, true); |
|
|
command(MMU_CMD_C0); |
|
|
command(MMU_CMD_C0); |
|
|
mmuLoop(); |
|
|
mmu_loop(); |
|
|
|
|
|
|
|
|
enable_E0(); |
|
|
enable_E0(); |
|
|
extruder = index; |
|
|
extruder = index; |
|
@ -522,7 +522,7 @@ void MMU2::toolChange(const char* special) { |
|
|
|
|
|
|
|
|
case 'c': { |
|
|
case 'c': { |
|
|
while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100); |
|
|
while (!thermalManager.wait_for_hotend(active_extruder, false)) safe_delay(100); |
|
|
executeExtruderSequence((const E_Step *)loadToNozzle_sequence, COUNT(loadToNozzle_sequence)); |
|
|
execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence)); |
|
|
} break; |
|
|
} break; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -547,7 +547,7 @@ void MMU2::command(const uint8_t mmu_cmd) { |
|
|
/**
|
|
|
/**
|
|
|
* Wait for response from MMU |
|
|
* Wait for response from MMU |
|
|
*/ |
|
|
*/ |
|
|
bool MMU2::getResponse(void) { |
|
|
bool MMU2::get_response(void) { |
|
|
while (cmd != MMU_CMD_NONE) idle(); |
|
|
while (cmd != MMU_CMD_NONE) idle(); |
|
|
|
|
|
|
|
|
while (!ready) { |
|
|
while (!ready) { |
|
@ -565,7 +565,7 @@ bool MMU2::getResponse(void) { |
|
|
/**
|
|
|
/**
|
|
|
* Wait for response and deal with timeout if nexcessary |
|
|
* Wait for response and deal with timeout if nexcessary |
|
|
*/ |
|
|
*/ |
|
|
void MMU2::manageResponse(bool move_axes, bool turn_off_nozzle) { |
|
|
void MMU2::manage_response(bool move_axes, bool turn_off_nozzle) { |
|
|
|
|
|
|
|
|
bool response = false; |
|
|
bool response = false; |
|
|
mmu_print_saved = false; |
|
|
mmu_print_saved = false; |
|
@ -575,7 +575,7 @@ void MMU2::manageResponse(bool move_axes, bool turn_off_nozzle) { |
|
|
|
|
|
|
|
|
while (!response) { |
|
|
while (!response) { |
|
|
|
|
|
|
|
|
response = getResponse(); //wait for "ok" from mmu
|
|
|
response = get_response(); //wait for "ok" from mmu
|
|
|
|
|
|
|
|
|
if (!response) { //no "ok" was received in reserved time frame, user will fix the issue on mmu unit
|
|
|
if (!response) { //no "ok" was received in reserved time frame, user will fix the issue on mmu unit
|
|
|
if (!mmu_print_saved) { //first occurence, we are saving current position, park print head in certain position and disable nozzle heater
|
|
|
if (!mmu_print_saved) { //first occurence, we are saving current position, park print head in certain position and disable nozzle heater
|
|
@ -636,7 +636,7 @@ void MMU2::manageResponse(bool move_axes, bool turn_off_nozzle) { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void MMU2::setFilamentType(uint8_t index, uint8_t filamentType) { |
|
|
void MMU2::set_filament_type(uint8_t index, uint8_t filamentType) { |
|
|
if (!enabled) return; |
|
|
if (!enabled) return; |
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(IN_HANDLER); |
|
|
KEEPALIVE_STATE(IN_HANDLER); |
|
@ -644,12 +644,12 @@ void MMU2::setFilamentType(uint8_t index, uint8_t filamentType) { |
|
|
cmd_arg = filamentType; |
|
|
cmd_arg = filamentType; |
|
|
command(MMU_CMD_F0 + index); |
|
|
command(MMU_CMD_F0 + index); |
|
|
|
|
|
|
|
|
manageResponse(true, true); |
|
|
manage_response(true, true); |
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(NOT_BUSY); |
|
|
KEEPALIVE_STATE(NOT_BUSY); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void MMU2::filamentRunout() { |
|
|
void MMU2::filament_runout() { |
|
|
enqueue_and_echo_commands_P(PSTR(MMU2_FILAMENT_RUNOUT_SCRIPT)); |
|
|
enqueue_and_echo_commands_P(PSTR(MMU2_FILAMENT_RUNOUT_SCRIPT)); |
|
|
planner.synchronize(); |
|
|
planner.synchronize(); |
|
|
} |
|
|
} |
|
@ -657,10 +657,10 @@ void MMU2::filamentRunout() { |
|
|
#if HAS_LCD_MENU && ENABLED(MMU2_MENUS) |
|
|
#if HAS_LCD_MENU && ENABLED(MMU2_MENUS) |
|
|
|
|
|
|
|
|
// Load filament into MMU2
|
|
|
// Load filament into MMU2
|
|
|
void MMU2::loadFilament(uint8_t index) { |
|
|
void MMU2::load_filament(uint8_t index) { |
|
|
if (!enabled) return; |
|
|
if (!enabled) return; |
|
|
command(MMU_CMD_L0 + index); |
|
|
command(MMU_CMD_L0 + index); |
|
|
manageResponse(false, false); |
|
|
manage_response(false, false); |
|
|
BUZZ(200, 404); |
|
|
BUZZ(200, 404); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -669,7 +669,7 @@ void MMU2::filamentRunout() { |
|
|
* Switch material and load to nozzle |
|
|
* Switch material and load to nozzle |
|
|
* |
|
|
* |
|
|
*/ |
|
|
*/ |
|
|
bool MMU2::loadFilamentToNozzle(uint8_t index) { |
|
|
bool MMU2::load_filament_to_nozzle(uint8_t index) { |
|
|
|
|
|
|
|
|
if (!enabled) return false; |
|
|
if (!enabled) return false; |
|
|
|
|
|
|
|
@ -682,14 +682,14 @@ void MMU2::filamentRunout() { |
|
|
KEEPALIVE_STATE(IN_HANDLER); |
|
|
KEEPALIVE_STATE(IN_HANDLER); |
|
|
|
|
|
|
|
|
command(MMU_CMD_T0 + index); |
|
|
command(MMU_CMD_T0 + index); |
|
|
manageResponse(true, true); |
|
|
manage_response(true, true); |
|
|
command(MMU_CMD_C0); |
|
|
command(MMU_CMD_C0); |
|
|
mmuLoop(); |
|
|
mmu_loop(); |
|
|
|
|
|
|
|
|
extruder = index; |
|
|
extruder = index; |
|
|
active_extruder = 0; |
|
|
active_extruder = 0; |
|
|
|
|
|
|
|
|
loadToNozzle(); |
|
|
load_to_nozzle(); |
|
|
|
|
|
|
|
|
BUZZ(200, 404); |
|
|
BUZZ(200, 404); |
|
|
|
|
|
|
|
@ -706,12 +706,12 @@ void MMU2::filamentRunout() { |
|
|
* It is not used after T0 .. T4 command (select filament), in such case, gcode is responsible for loading |
|
|
* It is not used after T0 .. T4 command (select filament), in such case, gcode is responsible for loading |
|
|
* filament to nozzle. |
|
|
* filament to nozzle. |
|
|
*/ |
|
|
*/ |
|
|
void MMU2::loadToNozzle() { |
|
|
void MMU2::load_to_nozzle() { |
|
|
if (!enabled) return; |
|
|
if (!enabled) return; |
|
|
executeExtruderSequence((const E_Step *)loadToNozzle_sequence, COUNT(loadToNozzle_sequence)); |
|
|
execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
bool MMU2::ejectFilament(uint8_t index, bool recover) { |
|
|
bool MMU2::eject_filament(uint8_t index, bool recover) { |
|
|
|
|
|
|
|
|
if (!enabled) return false; |
|
|
if (!enabled) return false; |
|
|
|
|
|
|
|
@ -731,7 +731,7 @@ void MMU2::filamentRunout() { |
|
|
planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 2500 / 60, active_extruder); |
|
|
planner.buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 2500 / 60, active_extruder); |
|
|
planner.synchronize(); |
|
|
planner.synchronize(); |
|
|
command(MMU_CMD_E0 + index); |
|
|
command(MMU_CMD_E0 + index); |
|
|
manageResponse(false, false); |
|
|
manage_response(false, false); |
|
|
|
|
|
|
|
|
if (recover) { |
|
|
if (recover) { |
|
|
LCD_MESSAGEPGM(MSG_MMU2_EJECT_RECOVER); |
|
|
LCD_MESSAGEPGM(MSG_MMU2_EJECT_RECOVER); |
|
@ -745,7 +745,7 @@ void MMU2::filamentRunout() { |
|
|
BUZZ(200, 404); |
|
|
BUZZ(200, 404); |
|
|
|
|
|
|
|
|
command(MMU_CMD_R0); |
|
|
command(MMU_CMD_R0); |
|
|
manageResponse(false, false); |
|
|
manage_response(false, false); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
ui.reset_status(); |
|
|
ui.reset_status(); |
|
@ -783,10 +783,10 @@ void MMU2::filamentRunout() { |
|
|
|
|
|
|
|
|
KEEPALIVE_STATE(IN_HANDLER); |
|
|
KEEPALIVE_STATE(IN_HANDLER); |
|
|
|
|
|
|
|
|
filamentRamming(); |
|
|
filament_ramming(); |
|
|
|
|
|
|
|
|
command(MMU_CMD_U0); |
|
|
command(MMU_CMD_U0); |
|
|
manageResponse(false, true); |
|
|
manage_response(false, true); |
|
|
|
|
|
|
|
|
BUZZ(200, 404); |
|
|
BUZZ(200, 404); |
|
|
|
|
|
|
|
@ -803,11 +803,11 @@ void MMU2::filamentRunout() { |
|
|
/**
|
|
|
/**
|
|
|
* Unload sequence to optimize shape of the tip of the unloaded filament |
|
|
* Unload sequence to optimize shape of the tip of the unloaded filament |
|
|
*/ |
|
|
*/ |
|
|
void MMU2::filamentRamming() { |
|
|
void MMU2::filament_ramming() { |
|
|
executeExtruderSequence((const E_Step *)ramming_sequence, sizeof(ramming_sequence) / sizeof(E_Step)); |
|
|
execute_extruder_sequence((const E_Step *)ramming_sequence, sizeof(ramming_sequence) / sizeof(E_Step)); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void MMU2::executeExtruderSequence(const E_Step * sequence, int steps) { |
|
|
void MMU2::execute_extruder_sequence(const E_Step * sequence, int steps) { |
|
|
|
|
|
|
|
|
planner.synchronize(); |
|
|
planner.synchronize(); |
|
|
enable_E0(); |
|
|
enable_E0(); |
|
|