Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added initial version of MMU2S feature #17523

Merged
merged 25 commits into from
Apr 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -3267,6 +3267,25 @@
{ 10.0, 700 }, \
{ -10.0, 400 }, \
{ -50.0, 2000 }
#endif

// Using a sensor like the MMU2S
//#define PRUSA_MMU2_S_MODE
#if ENABLED(PRUSA_MMU2_S_MODE)
#define MMU2_C0_RETRY 5 // Number of retries (total time = timeout*retries)

#define MMU2_CAN_LOAD_FEEDRATE 800 // (mm/m)
#define MMU2_CAN_LOAD_SEQUENCE \
{ 0.1, MMU2_CAN_LOAD_FEEDRATE }, \
{ 60.0, MMU2_CAN_LOAD_FEEDRATE }, \
{ -52.0, MMU2_CAN_LOAD_FEEDRATE }

#define MMU2_CAN_LOAD_RETRACT 6.0 // (mm) Keep under the distance between Load Sequence values
#define MMU2_CAN_LOAD_DEVIATION 0.8 // (mm) Acceptable deviation

#define MMU2_CAN_LOAD_INCREMENT 0.2 // (mm) To reuse within MMU2 module
#define MMU2_CAN_LOAD_INCREMENT_SEQUENCE \
{ -MMU2_CAN_LOAD_INCREMENT, MMU2_CAN_LOAD_FEEDRATE }

#endif

Expand Down
128 changes: 97 additions & 31 deletions Marlin/src/feature/mmu2/mmu2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ MMU2 mmu2;
#define mmuSerial MMU2_SERIAL

bool MMU2::enabled, MMU2::ready, MMU2::mmu_print_saved;
#if ENABLED(PRUSA_MMU2_S_MODE)
bool MMU2::mmu2s_triggered;
#endif
uint8_t MMU2::cmd, MMU2::cmd_arg, MMU2::last_cmd, MMU2::extruder;
int8_t MMU2::state = 0;
volatile int8_t MMU2::finda = 1;
Expand All @@ -106,8 +109,14 @@ char MMU2::rx_buffer[MMU_RX_SIZE], MMU2::tx_buffer[MMU_TX_SIZE];
feedRate_t feedRate; //!< feed rate in mm/s
};

static constexpr E_Step ramming_sequence[] PROGMEM = { MMU2_RAMMING_SEQUENCE };
static constexpr E_Step load_to_nozzle_sequence[] PROGMEM = { MMU2_LOAD_TO_NOZZLE_SEQUENCE };
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

Expand Down Expand Up @@ -228,6 +237,7 @@ void MMU2::mmu_loop() {

enabled = true;
state = 1;
TERN_(PRUSA_MMU2_S_MODE, mmu2s_triggered = false);
}
break;

Expand Down Expand Up @@ -291,6 +301,8 @@ void MMU2::mmu_loop() {
tx_str_P(PSTR("P0\n"));
state = 2; // wait for response
}

TERN_(PRUSA_MMU2_S_MODE, check_filament());
break;

case 2: // response to command P0
Expand All @@ -309,6 +321,7 @@ void MMU2::mmu_loop() {
else if (ELAPSED(millis(), last_request + MMU_P0_TIMEOUT)) // Resend request after timeout (3s)
state = 1;

TERN_(PRUSA_MMU2_S_MODE, check_filament());
break;

case 3: // response to mmu commands
Expand All @@ -327,6 +340,7 @@ void MMU2::mmu_loop() {
}
state = 1;
}
TERN_(PRUSA_MMU2_S_MODE, check_filament());
break;
}
}
Expand Down Expand Up @@ -437,6 +451,33 @@ void MMU2::check_version() {
}
}

static bool mmu2_not_responding() {
LCD_MESSAGEPGM(MSG_MMU2_NOT_RESPONDING);
BUZZ(100, 659);
BUZZ(200, 698);
BUZZ(100, 659);
BUZZ(300, 440);
BUZZ(100, 659);
}

#if ENABLED(PRUSA_MMU2_S_MODE)

bool MMU2::load_to_gears() {
command(MMU_CMD_C0);
manage_response(true, true);
LOOP_L_N(i, MMU2_C0_RETRY) { // Keep loading until filament reaches gears
Copy link
Contributor

@GMagician GMagician Apr 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't here missing a check_filament call? before loop?
otherwise isn't the if () break; to be put after check_filament call?

if (mmu2s_triggered) break;
command(MMU_CMD_C0);
manage_response(true, true);
check_filament();
}
const bool success = mmu2s_triggered && can_load();
if (!success) mmu2_not_responding();
return success;
}

#endif

/**
* Handle tool change
*/
Expand All @@ -452,18 +493,15 @@ void MMU2::tool_change(uint8_t index) {
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));

if (load_to_gears()) {
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();
}

Expand Down Expand Up @@ -500,12 +538,13 @@ void MMU2::tool_change(const char* special) {
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;
if (load_to_gears()) {
mmu_loop();
ENABLE_AXIS_E0();
extruder = index;
active_extruder = 0;
}
} break;

case 'c': {
Expand Down Expand Up @@ -579,12 +618,7 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) {

if (turn_off_nozzle) thermalManager.setTargetHotend(0, active_extruder);

LCD_MESSAGEPGM(MSG_MMU2_NOT_RESPONDING);
BUZZ(100, 659);
BUZZ(200, 698);
BUZZ(100, 659);
BUZZ(300, 440);
BUZZ(100, 659);
mmu2_not_responding();
}
}
else if (mmu_print_saved) {
Expand Down Expand Up @@ -632,6 +666,39 @@ void MMU2::filament_runout() {
planner.synchronize();
}

#if ENABLED(PRUSA_MMU2_S_MODE)
void MMU2::check_filament() {
const bool runout = READ(FIL_RUNOUT_PIN) ^ (FIL_RUNOUT_INVERTING);
if (runout && !mmu2s_triggered) {
DEBUG_ECHOLNPGM("MMU <= 'A'");
tx_str_P(PSTR("A\n"));
}
mmu2s_triggered = runout;
}

bool MMU2::can_load() {
execute_extruder_sequence((const E_Step *)can_load_sequence, COUNT(can_load_sequence));

int filament_detected_count = 0;
const int steps = MMU2_CAN_LOAD_RETRACT / MMU2_CAN_LOAD_INCREMENT;
DEBUG_ECHOLNPGM("MMU can_load:");
LOOP_L_N(i, steps) {
execute_extruder_sequence((const E_Step *)can_load_increment_sequence, COUNT(can_load_increment_sequence));
check_filament(); // Don't trust the idle function
DEBUG_CHAR(mmu2s_triggered ? 'O' : 'o');
if (mmu2s_triggered) ++filament_detected_count;
}

if (filament_detected_count <= steps - (MMU2_CAN_LOAD_DEVIATION / MMU2_CAN_LOAD_INCREMENT)) {
DEBUG_ECHOLNPGM(" failed.");
return false;
}

DEBUG_ECHOLNPGM(" succeeded.");
return true;
}
#endif

#if BOTH(HAS_LCD_MENU, MMU2_MENUS)

// Load filament into MMU2
Expand All @@ -656,20 +723,19 @@ void MMU2::filament_runout() {
LCD_ALERTMESSAGEPGM(MSG_HOTEND_TOO_COLD);
return false;
}
else {
command(MMU_CMD_T0 + index);
manage_response(true, true);
command(MMU_CMD_C0);
mmu_loop();

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 true;
}
return success;
}

/**
Expand Down
10 changes: 10 additions & 0 deletions Marlin/src/feature/mmu2/mmu2.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,17 @@ class MMU2 {

static void filament_runout();

#if ENABLED(PRUSA_MMU2_S_MODE)
static bool mmu2s_triggered;
static void check_filament();
static bool can_load();
static bool load_to_gears();
#else
FORCE_INLINE static bool load_to_gears() { return true; }
#endif

static bool enabled, ready, mmu_print_saved;

static uint8_t cmd, cmd_arg, last_cmd, extruder;
static int8_t state;
static volatile int8_t finda;
Expand Down
2 changes: 2 additions & 0 deletions Marlin/src/inc/SanityCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -2740,6 +2740,8 @@ static_assert( _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2)
#error "PRUSA_MMU2 requires NOZZLE_PARK_FEATURE."
#elif EXTRUDERS != 5
#error "PRUSA_MMU2 requires EXTRUDERS = 5."
#elif ENABLED(PRUSA_MMU2_S_MODE) && DISABLED(FILAMENT_RUNOUT_SENSOR)
#error "PRUSA_MMU2_S_MODE requires FILAMENT_RUNOUT_SENSOR. Enable it to continue."
#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
Expand Down
18 changes: 9 additions & 9 deletions Marlin/src/lcd/language/language_en.h
Original file line number Diff line number Diff line change
Expand Up @@ -528,21 +528,21 @@ namespace Language_en {
PROGMEM Language_Str MSG_MMU2_MENU = _UxGT("MMU");
PROGMEM Language_Str MSG_KILL_MMU2_FIRMWARE = _UxGT("Update MMU Firmware!");
PROGMEM Language_Str MSG_MMU2_NOT_RESPONDING = _UxGT("MMU Needs Attention.");
PROGMEM Language_Str MSG_MMU2_RESUME = _UxGT("Resume Print");
PROGMEM Language_Str MSG_MMU2_RESUMING = _UxGT("Resuming...");
PROGMEM Language_Str MSG_MMU2_LOAD_FILAMENT = _UxGT("Load Filament");
PROGMEM Language_Str MSG_MMU2_LOAD_ALL = _UxGT("Load All");
PROGMEM Language_Str MSG_MMU2_LOAD_TO_NOZZLE = _UxGT("Load to Nozzle");
PROGMEM Language_Str MSG_MMU2_EJECT_FILAMENT = _UxGT("Eject Filament");
PROGMEM Language_Str MSG_MMU2_EJECT_FILAMENT_N = _UxGT("Eject Filament ~");
PROGMEM Language_Str MSG_MMU2_UNLOAD_FILAMENT = _UxGT("Unload Filament");
PROGMEM Language_Str MSG_MMU2_RESUME = _UxGT("MMU Resume");
PROGMEM Language_Str MSG_MMU2_RESUMING = _UxGT("MMU Resuming...");
PROGMEM Language_Str MSG_MMU2_LOAD_FILAMENT = _UxGT("MMU Load");
PROGMEM Language_Str MSG_MMU2_LOAD_ALL = _UxGT("MMU Load All");
PROGMEM Language_Str MSG_MMU2_LOAD_TO_NOZZLE = _UxGT("MMU Load to Nozzle");
PROGMEM Language_Str MSG_MMU2_EJECT_FILAMENT = _UxGT("MMU Eject");
PROGMEM Language_Str MSG_MMU2_EJECT_FILAMENT_N = _UxGT("MMU Eject ~");
PROGMEM Language_Str MSG_MMU2_UNLOAD_FILAMENT = _UxGT("MMU Unload");
PROGMEM Language_Str MSG_MMU2_LOADING_FILAMENT = _UxGT("Loading Fil. %i...");
PROGMEM Language_Str MSG_MMU2_EJECTING_FILAMENT = _UxGT("Ejecting Fil. ...");
PROGMEM Language_Str MSG_MMU2_UNLOADING_FILAMENT = _UxGT("Unloading Fil....");
PROGMEM Language_Str MSG_MMU2_ALL = _UxGT("All");
PROGMEM Language_Str MSG_MMU2_FILAMENT_N = _UxGT("Filament ~");
PROGMEM Language_Str MSG_MMU2_RESET = _UxGT("Reset MMU");
PROGMEM Language_Str MSG_MMU2_RESETTING = _UxGT("Resetting MMU...");
PROGMEM Language_Str MSG_MMU2_RESETTING = _UxGT("MMU Resetting...");
PROGMEM Language_Str MSG_MMU2_EJECT_RECOVER = _UxGT("Remove, click");

PROGMEM Language_Str MSG_MIX = _UxGT("Mix");
Expand Down
2 changes: 1 addition & 1 deletion buildroot/share/tests/mega2560-tests
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ 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 NOZZLE_PARK_FEATURE ADVANCED_PAUSE_FEATURE Z_SAFE_HOMING
PRUSA_MMU2 MMU2_MENUS PRUSA_MMU2_S_MODE FILAMENT_RUNOUT_SENSOR NOZZLE_PARK_FEATURE ADVANCED_PAUSE_FEATURE Z_SAFE_HOMING
exec_test $1 $2 "RAMPS | ZONESTAR_LCD | MMU2 | Servo Probe | ABL 3-Pt | Debug Leveling | EEPROM | G38 ..."

#
Expand Down