Browse Source

Merge pull request #1404 from PavelSindler/idler_sensor

Printer with idler sensor
mkbel 5 năm trước cách đây
mục cha
commit
b145074589

+ 33 - 5
Firmware/Marlin_main.cpp

@@ -129,6 +129,7 @@
 #include "sound.h"
 
 #include "cmdqueue.h"
+#include "io_atmega2560.h"
 
 // Macros for bit masks
 #define BIT(b) (1<<(b))
@@ -641,6 +642,8 @@ void failstats_reset_print()
 	eeprom_update_byte((uint8_t *)EEPROM_CRASH_COUNT_Y, 0);
 	eeprom_update_byte((uint8_t *)EEPROM_FERROR_COUNT, 0);
 	eeprom_update_byte((uint8_t *)EEPROM_POWER_COUNT, 0);
+	eeprom_update_byte((uint8_t *)EEPROM_MMU_FAIL, 0);
+	eeprom_update_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL, 0);
 }
 
 
@@ -687,6 +690,12 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 			eeprom_update_word((uint16_t *)EEPROM_FERROR_COUNT_TOT, 0);
 			eeprom_update_word((uint16_t *)EEPROM_POWER_COUNT_TOT, 0);
 
+			eeprom_update_word((uint16_t *)EEPROM_MMU_FAIL_TOT, 0);
+			eeprom_update_word((uint16_t *)EEPROM_MMU_LOAD_FAIL_TOT, 0);
+			eeprom_update_byte((uint8_t *)EEPROM_MMU_FAIL, 0);
+			eeprom_update_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL, 0);
+
+
 			lcd_menu_statistics();
             
 			break;
@@ -713,6 +722,11 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
             eeprom_update_word((uint16_t *)EEPROM_FERROR_COUNT_TOT, 0);
             eeprom_update_word((uint16_t *)EEPROM_POWER_COUNT_TOT, 0);
 
+			eeprom_update_word((uint16_t *)EEPROM_MMU_FAIL_TOT, 0);
+			eeprom_update_word((uint16_t *)EEPROM_MMU_LOAD_FAIL_TOT, 0);
+			eeprom_update_byte((uint8_t *)EEPROM_MMU_FAIL, 0);
+			eeprom_update_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL, 0);
+
 #ifdef FILAMENT_SENSOR
 			fsensor_enable();
             fsensor_autoload_set(true);
@@ -1387,6 +1401,12 @@ void setup()
 	if (eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT, 0);
 	if (eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT, 0);
 	if (eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_FERROR_COUNT_TOT, 0);
+
+	if (eeprom_read_word((uint16_t*)EEPROM_MMU_FAIL_TOT) == 0xffff) eeprom_update_word((uint16_t *)EEPROM_MMU_FAIL_TOT, 0);
+	if (eeprom_read_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT) == 0xffff) eeprom_update_word((uint16_t *)EEPROM_MMU_LOAD_FAIL_TOT, 0);
+	if (eeprom_read_byte((uint8_t*)EEPROM_MMU_FAIL) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_MMU_FAIL, 0);
+	if (eeprom_read_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL, 0);
+
 #ifdef SNMM
 	if (eeprom_read_dword((uint32_t*)EEPROM_BOWDEN_LENGTH) == 0x0ffffffff) { //bowden length used for SNMM
 	  int _z = BOWDEN_LENGTH;
@@ -6892,16 +6912,20 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 		if (mmu_enabled)
 		{
 			tmp_extruder = choose_menu_P(_T(MSG_CHOOSE_FILAMENT), _T(MSG_FILAMENT));
+			if ((tmp_extruder == mmu_extruder) && mmu_fil_loaded) {
+				printf_P(PSTR("Duplicit T-code ignored.\n"));
+				return; //dont execute the same T-code twice in a row
+			}
 			st_synchronize();
 			mmu_command(MMU_CMD_T0 + tmp_extruder);
-			manage_response(true, true);
+			manage_response(true, true, MMU_TCODE_MOVE);
 		}
 	  }
 	  else if (*(strchr_pointer + index) == 'c') { //load to from bondtech gears to nozzle (nozzle should be preheated)
 	  	if (mmu_enabled) 
 		{
 			st_synchronize();
-			mmu_command(MMU_CMD_C0);
+			mmu_continue_loading();
 			mmu_extruder = tmp_extruder; //filament change is finished
 			mmu_load_to_nozzle();
 		}
@@ -6926,11 +6950,15 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 
           if (mmu_enabled)
           {
+              if ((tmp_extruder == mmu_extruder) && mmu_fil_loaded) {
+                  printf_P(PSTR("Duplicit T-code ignored.\n"));
+                  return; //dont execute the same T-code twice in a row
+              }
               mmu_command(MMU_CMD_T0 + tmp_extruder);
 
-              manage_response(true, true);
-              mmu_command(MMU_CMD_C0);
-              mmu_extruder = tmp_extruder; //filament change is finished
+			  manage_response(true, true, MMU_TCODE_MOVE);
+			  mmu_continue_loading();
+			  mmu_extruder = tmp_extruder; //filament change is finished
 
               if (load_to_nozzle)// for single material usage with mmu
               {

+ 6 - 0
Firmware/eeprom.h

@@ -148,6 +148,12 @@
 
 #define EEPROM_FSENS_OQ_MEASS_ENABLED (EEPROM_AUTO_DEPLETE - 1) //bool
 
+#define EEPROM_MMU_FAIL_TOT (EEPROM_FSENS_OQ_MEASS_ENABLED - 2) //uint16_t
+#define EEPROM_MMU_FAIL (EEPROM_MMU_FAIL_TOT - 1) //uint8_t
+
+#define EEPROM_MMU_LOAD_FAIL_TOT (EEPROM_MMU_FAIL - 2) //uint16_t
+#define EEPROM_MMU_LOAD_FAIL (EEPROM_MMU_LOAD_FAIL_TOT - 1) //uint8_t
+
 // !!!!!
 // !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!!
 // !!!!!

+ 245 - 38
Firmware/mmu.cpp

@@ -13,6 +13,7 @@
 #include "sound.h"
 #include "printers.h"
 #include <avr/pgmspace.h>
+#include "io_atmega2560.h"
 
 #ifdef TMC2130
 #include "tmc2130.h"
@@ -22,25 +23,31 @@
 
 #define MMU_TODELAY 100
 #define MMU_TIMEOUT 10
-#define MMU_CMD_TIMEOUT 300000ul //5min timeout for mmu commands (except P0)
+#define MMU_CMD_TIMEOUT 45000ul //5min timeout for mmu commands (except P0)
 #define MMU_P0_TIMEOUT 3000ul //timeout for P0 command: 3seconds
+#define MMU_MAX_RESEND_ATTEMPTS 2
 
 #ifdef MMU_HWRESET
 #define MMU_RST_PIN 76
 #endif //MMU_HWRESET
 
 bool mmu_enabled = false;
-
 bool mmu_ready = false;
+bool mmu_fil_loaded = false; //if true: blocks execution of duplicit T-codes
 
 static int8_t mmu_state = 0;
 
 uint8_t mmu_cmd = 0;
 
-uint8_t mmu_extruder = 0;
+//idler ir sensor
+uint8_t mmu_idl_sens = 0;
+bool mmu_idler_sensor_detected = false; 
+bool mmu_loading_flag = false;
+
+uint8_t mmu_extruder = MMU_FILAMENT_UNKNOWN;
 
 //! This variable probably has no meaning and is planed to be removed
-uint8_t tmp_extruder = 0;
+uint8_t tmp_extruder = MMU_FILAMENT_UNKNOWN;
 
 int8_t mmu_finda = -1;
 
@@ -52,6 +59,7 @@ uint32_t mmu_last_request = 0;
 uint32_t mmu_last_response = 0;
 
 uint8_t mmu_last_cmd = 0;
+uint16_t mmu_power_failures = 0;
 
 
 //clear rx buffer
@@ -108,11 +116,31 @@ void mmu_init(void)
 	_delay_ms(10);                             //wait 10ms for sure
 	mmu_reset();                               //reset mmu (HW or SW), do not wait for response
 	mmu_state = -1;
+	PIN_INP(MMU_IDLER_SENSOR_PIN); //input mode
+	PIN_SET(MMU_IDLER_SENSOR_PIN); //pullup
+}
+
+//returns true if idler IR sensor was detected, otherwise returns false
+bool check_for_idler_sensor() 
+{
+	bool detected = false;
+	//if MMU_IDLER_SENSOR_PIN input is low and pat9125sensor is not present we detected idler sensor
+	if ((PIN_GET(MMU_IDLER_SENSOR_PIN) == 0) && fsensor_not_responding) 
+	{
+		  detected = true;
+		  //printf_P(PSTR("Idler IR sensor detected\n"));
+	}
+	else
+	{
+		  //printf_P(PSTR("Idler IR sensor not detected\n"));
+	}
+	return detected;
 }
 
 //mmu main loop - state machine processing
 void mmu_loop(void)
 {
+	static uint8_t mmu_attempt_nr = 0;
 	int filament = 0;
 //	printf_P(PSTR("MMU loop, state=%d\n"), mmu_state);
 	switch (mmu_state)
@@ -160,9 +188,9 @@ void mmu_loop(void)
 
 			if ((PRINTER_TYPE == PRINTER_MK3) || (PRINTER_TYPE == PRINTER_MK3_SNMM))
 			{
-#ifdef MMU_DEBUG
+#if defined MMU_DEBUG && defined MMU_FINDA_DEBUG
 				puts_P(PSTR("MMU <= 'P0'"));
-#endif //MMU_DEBUG
+#endif //MMU_DEBUG && MMU_FINDA_DEBUG
 				mmu_puts_P(PSTR("P0\n")); //send 'read finda' request
 				mmu_state = -4;
 			}
@@ -180,9 +208,9 @@ void mmu_loop(void)
 	case -5:
 		if (mmu_rx_ok() > 0)
 		{
-#ifdef MMU_DEBUG
+#if defined MMU_DEBUG && defined MMU_FINDA_DEBUG
 			puts_P(PSTR("MMU <= 'P0'"));
-#endif //MMU_DEBUG
+#endif //MMU_DEBUG && MMU_FINDA_DEBUG
 		    mmu_puts_P(PSTR("P0\n")); //send 'read finda' request
 			mmu_state = -4;
 		}
@@ -191,11 +219,13 @@ void mmu_loop(void)
 		if (mmu_rx_ok() > 0)
 		{
 			fscanf_P(uart2io, PSTR("%hhu"), &mmu_finda); //scan finda from buffer
-#ifdef MMU_DEBUG
+#if defined MMU_DEBUG && defined MMU_FINDA_DEBUG 
 			printf_P(PSTR("MMU => '%dok'\n"), mmu_finda);
-#endif //MMU_DEBUG
+#endif //MMU_DEBUG && MMU_FINDA_DEBUG
 			puts_P(PSTR("MMU - ENABLED"));
 			mmu_enabled = true;
+			//if we have filament loaded into the nozzle, we can decide if printer has idler sensor right now; otherwise we will will wait till start of T-code so it will be detected on beginning of second T-code
+			if(check_for_idler_sensor()) mmu_idler_sensor_detected = true;
 			mmu_state = 1;
 		}
 		return;
@@ -210,6 +240,8 @@ void mmu_loop(void)
 #endif //MMU_DEBUG
 				mmu_printf_P(PSTR("T%d\n"), filament);
 				mmu_state = 3; // wait for response
+				mmu_fil_loaded = true;
+				if(mmu_idler_sensor_detected) mmu_idl_sens = 1; //if idler sensor detected, use it for T-code
 			}
 			else if ((mmu_cmd >= MMU_CMD_L0) && (mmu_cmd <= MMU_CMD_L4))
 			{
@@ -227,6 +259,7 @@ void mmu_loop(void)
 #endif //MMU_DEBUG
 				mmu_puts_P(PSTR("C0\n")); //send 'continue loading'
 				mmu_state = 3;
+				if(mmu_idler_sensor_detected) mmu_idl_sens = 1; //if idler sensor detected use it for C0 code
 			}
 			else if (mmu_cmd == MMU_CMD_U0)
 			{
@@ -234,6 +267,7 @@ void mmu_loop(void)
 				printf_P(PSTR("MMU <= 'U0'\n"));
 #endif //MMU_DEBUG
 				mmu_puts_P(PSTR("U0\n")); //send 'unload current filament'
+				mmu_fil_loaded = false;
 				mmu_state = 3;
 			}
 			else if ((mmu_cmd >= MMU_CMD_E0) && (mmu_cmd <= MMU_CMD_E4))
@@ -243,6 +277,7 @@ void mmu_loop(void)
 				printf_P(PSTR("MMU <= 'E%d'\n"), filament);
 #endif //MMU_DEBUG
 				mmu_printf_P(PSTR("E%d\n"), filament); //send eject filament
+				mmu_fil_loaded = false;
 				mmu_state = 3; // wait for response
 			}
 			else if (mmu_cmd == MMU_CMD_R0)
@@ -253,14 +288,23 @@ void mmu_loop(void)
 				mmu_puts_P(PSTR("R0\n")); //send recover after eject
 				mmu_state = 3; // wait for response
 			}
+			else if (mmu_cmd == MMU_CMD_S3)
+			{
+#ifdef MMU_DEBUG
+				printf_P(PSTR("MMU <= 'S3'\n"));
+#endif //MMU_DEBUG
+				mmu_puts_P(PSTR("S3\n")); //send power failures request
+				mmu_state = 4; // power failures response
+			}
 			mmu_last_cmd = mmu_cmd;
 			mmu_cmd = 0;
 		}
 		else if ((mmu_last_response + 300) < millis()) //request every 300ms
 		{
-#ifdef MMU_DEBUG
+			if(check_for_idler_sensor()) mmu_idler_sensor_detected = true;
+#if defined MMU_DEBUG && defined MMU_FINDA_DEBUG
 			puts_P(PSTR("MMU <= 'P0'"));
-#endif //MMU_DEBUG
+#endif //MMU_DEBUG && MMU_FINDA_DEBUG
 		    mmu_puts_P(PSTR("P0\n")); //send 'read finda' request
 			mmu_state = 2;
 		}
@@ -269,9 +313,9 @@ void mmu_loop(void)
 		if (mmu_rx_ok() > 0)
 		{
 			fscanf_P(uart2io, PSTR("%hhu"), &mmu_finda); //scan finda from buffer
-#ifdef MMU_DEBUG
+#if defined MMU_DEBUG && MMU_FINDA_DEBUG
 			printf_P(PSTR("MMU => '%dok'\n"), mmu_finda);
-#endif //MMU_DEBUG
+#endif //MMU_DEBUG && MMU_FINDA_DEBUG
 			//printf_P(PSTR("Eact: %d\n"), int(e_active()));
 			if (!mmu_finda && CHECK_FINDA && fsensor_enabled) {
 				fsensor_stop_and_save_print();
@@ -289,11 +333,28 @@ void mmu_loop(void)
 		}
 		return;
 	case 3: //response to mmu commands
+		if (mmu_idler_sensor_detected) {
+			if (mmu_idl_sens)
+			{
+				if (PIN_GET(MMU_IDLER_SENSOR_PIN) == 0 && mmu_loading_flag)
+				{
+#ifdef MMU_DEBUG
+					printf_P(PSTR("MMU <= 'A'\n"));
+#endif //MMU_DEBUG  
+					mmu_puts_P(PSTR("A\n")); //send 'abort' request
+					mmu_idl_sens = 0;
+					//printf_P(PSTR("MMU IDLER_SENSOR = 0 - ABORT\n"));
+				}
+				//else
+					//printf_P(PSTR("MMU IDLER_SENSOR = 1 - WAIT\n"));
+			}
+		}
 		if (mmu_rx_ok() > 0)
 		{
 #ifdef MMU_DEBUG
 			printf_P(PSTR("MMU => 'ok'\n"));
 #endif //MMU_DEBUG
+			mmu_attempt_nr = 0;
 			mmu_last_cmd = 0;
 			mmu_ready = true;
 			mmu_state = 1;
@@ -302,15 +363,36 @@ void mmu_loop(void)
 		{ //resend request after timeout (5 min)
 			if (mmu_last_cmd)
 			{
+				if (mmu_attempt_nr++ < MMU_MAX_RESEND_ATTEMPTS) {
 #ifdef MMU_DEBUG
-				printf_P(PSTR("MMU retry\n"));
+					printf_P(PSTR("MMU retry attempt nr. %d\n"), mmu_attempt_nr - 1);
 #endif //MMU_DEBUG
-				mmu_cmd = mmu_last_cmd;
-//				mmu_last_cmd = 0; //resend just once
+					mmu_cmd = mmu_last_cmd;
+				}
+				else {
+					mmu_cmd = 0;
+					mmu_last_cmd = 0; //check
+					mmu_attempt_nr = 0;
+				}
 			}
 			mmu_state = 1;
 		}
 		return;
+	case 4:
+		if (mmu_rx_ok() > 0)
+		{
+			fscanf_P(uart2io, PSTR("%d"), &mmu_power_failures); //scan power failures
+#ifdef MMU_DEBUG
+			printf_P(PSTR("MMU => 'ok'\n"));
+#endif //MMU_DEBUG
+			mmu_last_cmd = 0;
+			mmu_ready = true;
+			mmu_state = 1;
+		}
+		else if ((mmu_last_request + MMU_CMD_TIMEOUT) < millis())
+		{ //resend request after timeout (5 min)
+			mmu_state = 1;
+		}
 	}
 }
 
@@ -350,22 +432,85 @@ void mmu_command(uint8_t cmd)
 	mmu_ready = false;
 }
 
-bool mmu_get_response(void)
+void mmu_load_step() {
+		current_position[E_AXIS] = current_position[E_AXIS] + MMU_LOAD_FEEDRATE * 0.1;
+		plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
+		st_synchronize();
+}
+
+bool mmu_get_response(uint8_t move)
 {
-//	printf_P(PSTR("mmu_get_response - begin\n"));
+	mmu_loading_flag = false;
+	if (!mmu_idler_sensor_detected) move = MMU_NO_MOVE;
+
+	printf_P(PSTR("mmu_get_response - begin move:%d\n"), move);
 	KEEPALIVE_STATE(IN_PROCESS);
 	while (mmu_cmd != 0)
 	{
 //		mmu_loop();
 		delay_keep_alive(100);
 	}
+
 	while (!mmu_ready)
 	{
 //		mmu_loop();
-		if (mmu_state != 3)
+
+		if ((mmu_state != 3) && (mmu_last_cmd == 0))
 			break;
-		delay_keep_alive(100);
+
+		//Do load steps only if temperature is higher then min. temp for safe extrusion.
+		//Otherwise "cold extrusion prevented" would be send to serial line periodically
+		if (degHotend(active_extruder) < EXTRUDE_MINTEMP) {
+			disable_e0(); //turn off E-stepper to prevent overheating and alow filament pull-out if necessary
+			delay_keep_alive(100);
+			continue;
+		}
+
+		switch (move) {
+			case MMU_LOAD_MOVE: 
+				mmu_loading_flag = true;
+				mmu_load_step();
+				//don't rely on "ok" signal from mmu unit; if filament detected by idler sensor during loading stop loading movements to prevent infinite loading
+				if (PIN_GET(MMU_IDLER_SENSOR_PIN) == 0) move = MMU_NO_MOVE;
+				break;
+			case MMU_UNLOAD_MOVE:
+				if (PIN_GET(MMU_IDLER_SENSOR_PIN) == 0) //filament is still detected by idler sensor, printer helps with unlading 
+				{ 
+					printf_P(PSTR("Unload 1\n"));
+					current_position[E_AXIS] = current_position[E_AXIS] - MMU_LOAD_FEEDRATE * MMU_LOAD_TIME_MS*0.001;
+					plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
+					st_synchronize();
+				}
+				else //filament was unloaded from idler, no additional movements needed 
+				{ 
+					printf_P(PSTR("Unloading finished 1\n"));
+					disable_e0(); //turn off E-stepper to prevent overheating and alow filament pull-out if necessary
+					move = MMU_NO_MOVE;
+				}
+				break;
+			case MMU_TCODE_MOVE: //first do unload and then continue with infinite loading movements
+				if (PIN_GET(MMU_IDLER_SENSOR_PIN) == 0) //filament detected by idler sensor, we must unload first 
+				{ 
+					printf_P(PSTR("Unload 2\n"));
+					current_position[E_AXIS] = current_position[E_AXIS] - MMU_LOAD_FEEDRATE * MMU_LOAD_TIME_MS*0.001;
+					plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
+					st_synchronize();
+				}
+				else //delay to allow mmu unit to pull out filament from bondtech gears and then start with infinite loading 
+				{ 
+					printf_P(PSTR("Unloading finished 2\n"));
+					disable_e0(); //turn off E-stepper to prevent overheating and alow filament pull-out if necessary
+					delay_keep_alive(MMU_LOAD_TIME_MS);
+					move = MMU_LOAD_MOVE;
+				}
+				break;
+			case MMU_NO_MOVE:
+			default: 
+				delay_keep_alive(100);
+				break;
+		}
 	}
+	printf_P(PSTR("mmu_get_response() returning: %d\n"), mmu_ready);
 	bool ret = mmu_ready;
 	mmu_ready = false;
 //	printf_P(PSTR("mmu_get_response - end %d\n"), ret?1:0);
@@ -392,7 +537,7 @@ bool mmu_get_response(void)
 }
 
 
-void manage_response(bool move_axes, bool turn_off_nozzle)
+void manage_response(bool move_axes, bool turn_off_nozzle, uint8_t move)
 {
 	bool response = false;
 	mmu_print_saved = false;
@@ -402,11 +547,18 @@ void manage_response(bool move_axes, bool turn_off_nozzle)
 	float x_position_bckp = current_position[X_AXIS];
 	float y_position_bckp = current_position[Y_AXIS];	
 	uint8_t screen = 0; //used for showing multiscreen messages
+
 	while(!response)
 	{
-		  response = mmu_get_response(); //wait for "ok" from mmu
+		  response = mmu_get_response(move); //wait for "ok" from mmu
 		  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
+				  
+				  uint8_t mmu_fail = eeprom_read_byte((uint8_t*)EEPROM_MMU_FAIL);
+				  uint16_t mmu_fail_tot = eeprom_read_word((uint16_t*)EEPROM_MMU_FAIL_TOT);
+				  if(mmu_fail < 255) eeprom_update_byte((uint8_t*)EEPROM_MMU_FAIL, mmu_fail + 1);
+				  if(mmu_fail_tot < 65535) eeprom_update_word((uint16_t*)EEPROM_MMU_FAIL_TOT, mmu_fail_tot + 1);
+
 				  if (lcd_update_enabled) {
 					  lcd_update_was_enabled = true;
 					  lcd_update_enable(false);
@@ -436,6 +588,7 @@ void manage_response(bool move_axes, bool turn_off_nozzle)
 					  //set nozzle target temperature to 0
 					  setAllTargetHotends(0);
 				  }
+				  disable_e0(); //turn off E-stepper to prevent overheating and alow filament pull-out if necessary
 			  }
 
 			  //first three lines are used for printing multiscreen message; last line contains measured and target nozzle temperature
@@ -450,19 +603,21 @@ void manage_response(bool move_axes, bool turn_off_nozzle)
 			  }
 
 			  lcd_set_degree();
-			  lcd_set_cursor(0, 4); //line 4
-			  //Print the hotend temperature (9 chars total) and fill rest of the line with space
-			  int chars = lcd_printf_P(_N("%c%3d/%d%c"), LCD_STR_THERMOMETER[0],(int)(degHotend(active_extruder) + 0.5), (int)(degTargetHotend(active_extruder) + 0.5), LCD_STR_DEGREE[0]);
-			  lcd_space(9 - chars);
 
 
 			  //5 seconds delay
-			  for (uint8_t i = 0; i < 50; i++) {
+			  for (uint8_t i = 0; i < 5; i++) {
 				  if (lcd_clicked()) {
 					  setTargetHotend(hotend_temp_bckp, active_extruder);
+					 /// mmu_cmd = mmu_last_cmd;
 					  break;
-				  }
-				  delay_keep_alive(100);
+				  }		  
+
+				  //Print the hotend temperature (9 chars total) and fill rest of the line with space
+				  lcd_set_cursor(0, 4); //line 4
+				  int chars = lcd_printf_P(_N("%c%3d/%d%c"), LCD_STR_THERMOMETER[0],(int)(degHotend(active_extruder) + 0.5), (int)(degTargetHotend(active_extruder) + 0.5), LCD_STR_DEGREE[0]);
+				  lcd_space(9 - chars);
+				  delay_keep_alive(1000);
 			  }
 		  }
 		  else if (mmu_print_saved) {
@@ -519,7 +674,14 @@ void mmu_load_to_nozzle()
 	
 	bool saved_e_relative_mode = axis_relative_modes[E_AXIS];
 	if (!saved_e_relative_mode) axis_relative_modes[E_AXIS] = true;
-	current_position[E_AXIS] += 7.2f;
+	if (mmu_idler_sensor_detected)
+	{
+		current_position[E_AXIS] += 3.0f;
+	}
+	else
+	{
+		current_position[E_AXIS] += 7.2f;
+	}
     float feedrate = 562;
 	plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feedrate / 60, active_extruder);
     st_synchronize();
@@ -599,9 +761,10 @@ void mmu_M600_load_filament(bool automatic)
 //		  mmu_printf_P(PSTR("T%d\n"), tmp_extruder);
 		  mmu_command(MMU_CMD_T0 + tmp_extruder);
 
-		  manage_response(false, true);
-		  mmu_command(MMU_CMD_C0);
+		  manage_response(false, true, MMU_LOAD_MOVE);
+		  mmu_continue_loading();
     	  mmu_extruder = tmp_extruder; //filament change is finished
+		  
 		  mmu_load_to_nozzle();
 		  load_filament_final_feed();
 		  st_synchronize();
@@ -803,13 +966,14 @@ void extr_unload()
 		lcd_clear();
 		lcd_set_cursor(0, 1); lcd_puts_P(_T(MSG_UNLOADING_FILAMENT));
 		lcd_print(" ");
-		lcd_print(mmu_extruder + 1);
+		if (mmu_extruder == MMU_FILAMENT_UNKNOWN) lcd_print(" ");
+		else lcd_print(mmu_extruder + 1);
 
 		filament_ramming();
 
 		mmu_command(MMU_CMD_U0);
 		// get response
-		manage_response(false, true);
+		manage_response(false, true, MMU_UNLOAD_MOVE);
 
 		lcd_update_enable(true);
 #else //SNMM
@@ -1105,8 +1269,8 @@ void lcd_mmu_load_to_nozzle(uint8_t filament_nr)
 	lcd_print(" ");
 	lcd_print(tmp_extruder + 1);
 	mmu_command(MMU_CMD_T0 + tmp_extruder);
-	manage_response(true, true);
-	mmu_command(MMU_CMD_C0);
+	manage_response(true, true, MMU_TCODE_MOVE);
+	mmu_continue_loading();
 	mmu_extruder = tmp_extruder; //filament change is finished
 	mmu_load_to_nozzle();
 	load_filament_final_feed();
@@ -1142,7 +1306,7 @@ void mmu_eject_filament(uint8_t filament, bool recover)
                 plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 2500 / 60, active_extruder);
                 st_synchronize();
                 mmu_command(MMU_CMD_E0 + filament);
-                manage_response(false, false);
+                manage_response(false, false, MMU_UNLOAD_MOVE);
                 if (recover)
                 {
                     lcd_show_fullscreen_message_and_wait_P(_i("Please remove filament and then press the knob."));
@@ -1162,3 +1326,46 @@ void mmu_eject_filament(uint8_t filament, bool recover)
 		puts_P(PSTR("Filament nr out of range!"));
 	}
 }
+
+void mmu_continue_loading() 
+{
+
+	if (mmu_idler_sensor_detected) {
+		for (uint8_t i = 0; i < MMU_IDLER_SENSOR_ATTEMPTS_NR; i++) {
+			if (PIN_GET(MMU_IDLER_SENSOR_PIN) == 0) return;
+#ifdef MMU_DEBUG
+			printf_P(PSTR("Additional load attempt nr. %d\n"), i);
+#endif // MMU_DEBUG
+			mmu_command(MMU_CMD_C0);
+			manage_response(true, true, MMU_LOAD_MOVE);
+		}
+		if (PIN_GET(MMU_IDLER_SENSOR_PIN) != 0) {
+			uint8_t mmu_load_fail = eeprom_read_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL);
+			uint16_t mmu_load_fail_tot = eeprom_read_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT);
+			if(mmu_load_fail < 255) eeprom_update_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL, mmu_load_fail + 1);
+			if(mmu_load_fail_tot < 65535) eeprom_update_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT, mmu_load_fail_tot + 1);
+			char cmd[3];
+			//pause print, show error message and then repeat last T-code
+			stop_and_save_print_to_ram(0, 0);
+
+			//lift z
+			current_position[Z_AXIS] += Z_PAUSE_LIFT;
+			if (current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS;
+			plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 15, active_extruder);
+			st_synchronize();
+
+			//Move XY to side
+			current_position[X_AXIS] = X_PAUSE_POS;
+			current_position[Y_AXIS] = Y_PAUSE_POS;
+			plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 50, active_extruder);
+			st_synchronize();
+			//set nozzle target temperature to 0
+			setAllTargetHotends(0);
+			lcd_setstatuspgm(_i("MMU load failed     "));////MSG_RECOVERING_PRINT c=20 r=1
+			mmu_fil_loaded = false; //so we can retry same T-code again
+		}
+	}
+	else { //mmu_idler_sensor_detected == false
+		mmu_command(MMU_CMD_C0);
+	}
+}

+ 19 - 3
Firmware/mmu.h

@@ -4,16 +4,30 @@
 
 
 extern bool mmu_enabled;
+extern bool mmu_fil_loaded;
 
 extern uint8_t mmu_extruder;
 
 extern uint8_t tmp_extruder;
 
 extern int8_t mmu_finda;
+extern bool mmu_idler_sensor_detected;
+extern bool mmu_loading_flag;
 
 extern int16_t mmu_version;
 extern int16_t mmu_buildnr;
 
+extern uint16_t mmu_power_failures;
+
+#define MMU_FILAMENT_UNKNOWN 255
+
+#define MMU_NO_MOVE 0
+#define MMU_UNLOAD_MOVE 1
+#define MMU_LOAD_MOVE 2
+#define MMU_TCODE_MOVE 3
+
+#define MMU_LOAD_FEEDRATE 19.02f //mm/s
+#define MMU_LOAD_TIME_MS 2000 //should be fine tuned to load time for shortest allowed PTFE tubing and maximum loading speed
 
 #define MMU_CMD_NONE 0
 #define MMU_CMD_T0   0x10
@@ -34,7 +48,7 @@ extern int16_t mmu_buildnr;
 #define MMU_CMD_E3   0x53
 #define MMU_CMD_E4   0x54
 #define MMU_CMD_R0   0x60
-
+#define MMU_CMD_S3	 0x73
 
 extern int mmu_puts_P(const char* str);
 
@@ -42,6 +56,7 @@ extern int mmu_printf_P(const char* format, ...);
 
 extern int8_t mmu_rx_ok(void);
 
+extern bool check_for_idler_sensor();
 
 extern void mmu_init(void);
 
@@ -54,9 +69,9 @@ extern int8_t mmu_set_filament_type(uint8_t extruder, uint8_t filament);
 
 extern void mmu_command(uint8_t cmd);
 
-extern bool mmu_get_response(void);
+extern bool mmu_get_response(uint8_t move = 0);
 
-extern void manage_response(bool move_axes, bool turn_off_nozzle);
+extern void manage_response(bool move_axes, bool turn_off_nozzle, uint8_t move = 0);
 
 extern void mmu_load_to_nozzle();
 
@@ -103,3 +118,4 @@ extern void mmu_eject_fil_1();
 extern void mmu_eject_fil_2();
 extern void mmu_eject_fil_3();
 extern void mmu_eject_fil_4();
+extern void mmu_continue_loading();

+ 1 - 0
Firmware/pins_Einsy_1_0.h

@@ -121,6 +121,7 @@
 #define TACH_0                 79 // !!! changed from 81 (EINY03)
 #define TACH_1                 80 
 
+#define MMU_IDLER_SENSOR_PIN 62 //idler sensor @PK0 (digital pin 62/A8)
 
 // Support for an 8 bit logic analyzer, for example the Saleae.
 // Channels 0-2 are fast, they could generate 2.667Mhz waveform with a software loop.

+ 1 - 1
Firmware/pins_Rambo_1_0.h

@@ -102,7 +102,7 @@
 
 #define SDCARDDETECT           72
 
-
+#define MMU_IDLER_SENSOR_PIN 62 //idler sensor @PK0 (digital pin 62/A8)
 
 // Support for an 8 bit logic analyzer, for example the Saleae.
 // Channels 0-2 are fast, they could generate 2.667Mhz waveform with a software loop.

+ 1 - 1
Firmware/pins_Rambo_1_3.h

@@ -102,7 +102,7 @@
 
 #define SDCARDDETECT           15
 
-
+#define MMU_IDLER_SENSOR_PIN 62 //idler sensor @PK0 (digital pin 62/A8)
 
 // Support for an 8 bit logic analyzer, for example the Saleae.
 // Channels 0-2 are fast, they could generate 2.667Mhz waveform with a software loop.

+ 118 - 28
Firmware/ultralcd.cpp

@@ -38,7 +38,7 @@
 #include "mmu.h"
 
 #include "static_assert.h"
-
+#include "io_atmega2560.h"
 
 extern bool fans_check_enabled;
 
@@ -136,6 +136,11 @@ static void lcd_menu_extruder_info();
 static void lcd_menu_xyz_y_min();
 static void lcd_menu_xyz_skew();
 static void lcd_menu_xyz_offset();
+static void lcd_menu_fails_stats_mmu();
+static void lcd_menu_fails_stats_mmu_print();
+static void lcd_menu_fails_stats_mmu_total();
+static void lcd_menu_show_sensors_state();
+
 #if defined(TMC2130) || defined(FILAMENT_SENSOR)
 static void lcd_menu_fails_stats();
 #endif //TMC2130 or FILAMENT_SENSOR
@@ -195,6 +200,9 @@ static void menu_action_sddirectory(const char* filename);
 
 #define ENCODER_FEEDRATE_DEADZONE 10
 
+#define STATE_NA 255
+#define STATE_OFF 0
+#define STATE_ON 1
 
 /*
 #define MENU_ITEM(type, label, args...) do { \
@@ -537,10 +545,15 @@ void lcdui_print_percent_done(void)
 void lcdui_print_extruder(void)
 {
 	int chars = 0;
-	if (mmu_extruder == tmp_extruder)
-		chars = lcd_printf_P(_N(" F%u"), mmu_extruder+1);
+	if (mmu_extruder == tmp_extruder) {
+		if (mmu_extruder == MMU_FILAMENT_UNKNOWN) chars = lcd_printf_P(_N(" F?"));
+		else chars = lcd_printf_P(_N(" F%u"), mmu_extruder + 1);
+	}
 	else
-		chars = lcd_printf_P(_N(" %u>%u"), mmu_extruder+1, tmp_extruder+1);
+	{
+		if (mmu_extruder == MMU_FILAMENT_UNKNOWN) chars = lcd_printf_P(_N(" ?>%u"), tmp_extruder + 1);
+		else chars = lcd_printf_P(_N(" %u>%u"), mmu_extruder + 1, tmp_extruder + 1);
+	}
 	lcd_space(5 - chars);
 }
 
@@ -1914,6 +1927,48 @@ static void lcd_menu_extruder_info()
     menu_back_if_clicked();
 }
 
+static void lcd_menu_fails_stats_mmu()
+{
+	MENU_BEGIN();
+	MENU_ITEM_BACK_P(_T(MSG_MAIN));
+	MENU_ITEM_SUBMENU_P(_i("Last print"), lcd_menu_fails_stats_mmu_print);
+	MENU_ITEM_SUBMENU_P(_i("Total"), lcd_menu_fails_stats_mmu_total);
+	MENU_END();
+}
+
+static void lcd_menu_fails_stats_mmu_print()
+{
+//01234567890123456789
+//Last print failures
+// MMU fails  000
+// MMU load fails  000
+//
+//////////////////////
+	lcd_timeoutToStatus.stop(); //infinite timeout
+    uint8_t fails = eeprom_read_byte((uint8_t*)EEPROM_MMU_FAIL);
+    uint16_t load_fails = eeprom_read_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL);
+//	lcd_printf_P(PSTR(ESC_H(0,0) "Last print failures" ESC_H(1,1) "Power failures  %-3d" ESC_H(1,2) "Filam. runouts  %-3d" ESC_H(1,3) "Crash  X %-3d  Y %-3d"), power, filam, crashX, crashY);
+	lcd_printf_P(PSTR(ESC_H(0,0) "%S" ESC_H(1,1) "%S  %-3d" ESC_H(1,2) "%S  %-3d" ESC_H(1,3)), _i("Last print failures"), _i("MMU fails"), fails, _i("MMU load fails"), load_fails);
+	menu_back_if_clicked_fb();
+}
+
+static void lcd_menu_fails_stats_mmu_total()
+{
+//01234567890123456789
+//Last print failures
+// MMU fails  000
+// MMU load fails  000
+//
+//////////////////////
+	mmu_command(MMU_CMD_S3);
+	lcd_timeoutToStatus.stop(); //infinite timeout
+    uint8_t fails = eeprom_read_byte((uint8_t*)EEPROM_MMU_FAIL_TOT);
+    uint16_t load_fails = eeprom_read_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL_TOT);
+//	lcd_printf_P(PSTR(ESC_H(0,0) "Last print failures" ESC_H(1,1) "Power failures  %-3d" ESC_H(1,2) "Filam. runouts  %-3d" ESC_H(1,3) "Crash  X %-3d  Y %-3d"), power, filam, crashX, crashY);
+	lcd_printf_P(PSTR(ESC_H(0,0) "%S" ESC_H(1,1) "%S  %-3d" ESC_H(1,2) "%S  %-3d" ESC_H(1,3) "%S %-3d"), _i("Total failures"), _i("MMU fails"), fails, _i("MMU load fails"), load_fails, _i("MMU power fails"), mmu_power_failures);
+	menu_back_if_clicked_fb();
+}
+
 #if defined(TMC2130) && defined(FILAMENT_SENSOR)
 static void lcd_menu_fails_stats_total()
 {
@@ -1950,6 +2005,7 @@ static void lcd_menu_fails_stats_print()
 	lcd_printf_P(PSTR(ESC_H(0,0) "%S" ESC_H(1,1) "%S  %-3d" ESC_H(1,2) "%S  %-3d" ESC_H(1,3) "%S  X %-3d  Y %-3d"), _i("Last print failures"), _i("Power failures"), power, _i("Filam. runouts"), filam, _i("Crash"), crashX, crashY);
 	menu_back_if_clicked_fb();
 }
+
 /**
  * @brief Open fail statistics menu
  *
@@ -1965,6 +2021,7 @@ static void lcd_menu_fails_stats()
 	MENU_ITEM_SUBMENU_P(_i("Total"), lcd_menu_fails_stats_total);
 	MENU_END();
 }
+
 #elif defined(FILAMENT_SENSOR)
 /**
  * @brief Print last print and total filament run outs
@@ -2180,16 +2237,17 @@ static void lcd_support_menu()
   #ifndef MK1BP
   MENU_ITEM_BACK_P(STR_SEPARATOR);
   MENU_ITEM_SUBMENU_P(_i("XYZ cal. details"), lcd_menu_xyz_y_min);////MSG_XYZ_DETAILS c=19 r=1
-  MENU_ITEM_SUBMENU_P(_i("Extruder info"), lcd_menu_extruder_info);////MSG_INFO_EXTRUDER c=15 r=1
+  MENU_ITEM_SUBMENU_P(_i("Extruder info"), lcd_menu_extruder_info);////MSG_INFO_EXTRUDER c=18 r=1
+  MENU_ITEM_SUBMENU_P(_i("Show sensors"), lcd_menu_show_sensors_state);////MSG_INFO_SENSORS c=18 r=1
 
 #ifdef TMC2130
-  MENU_ITEM_SUBMENU_P(_i("Belt status"), lcd_menu_belt_status);////MSG_MENU_BELT_STATUS c=15 r=1
+  MENU_ITEM_SUBMENU_P(_i("Belt status"), lcd_menu_belt_status);////MSG_MENU_BELT_STATUS c=18 r=1
 #endif //TMC2130
     
-  MENU_ITEM_SUBMENU_P(_i("Temperatures"), lcd_menu_temperatures);////MSG_MENU_TEMPERATURES c=15 r=1
+  MENU_ITEM_SUBMENU_P(_i("Temperatures"), lcd_menu_temperatures);////MSG_MENU_TEMPERATURES c=18 r=1
 
 #if defined (VOLT_BED_PIN) || defined (VOLT_PWR_PIN)
-  MENU_ITEM_SUBMENU_P(_i("Voltages"), lcd_menu_voltages);////MSG_MENU_VOLTAGES c=15 r=1
+  MENU_ITEM_SUBMENU_P(_i("Voltages"), lcd_menu_voltages);////MSG_MENU_VOLTAGES c=18 r=1
 #endif //defined VOLT_BED_PIN || defined VOLT_PWR_PIN
 
 #ifdef DEBUG_BUILD
@@ -3571,28 +3629,60 @@ void lcd_diag_show_end_stops()
     lcd_return_to_status();
 }
 
-#ifdef TMC2130
-static void lcd_show_pinda_state()
+static void lcd_print_state(uint8_t state)
 {
-lcd_set_cursor(0, 0);
-lcd_puts_P((PSTR("P.I.N.D.A. state")));
-lcd_set_cursor(0, 2);
-lcd_puts_P(READ(Z_MIN_PIN)?(PSTR("Z1 (LED off)")):(PSTR("Z0 (LED on) "))); // !!! both strings must have same length (due to dynamic refreshing)
+	switch (state) {
+		case STATE_ON:
+			lcd_puts_P(_i("On "));
+		break;
+		case STATE_OFF:
+			lcd_puts_P(_i("Off"));
+		break;
+		default: 
+			lcd_puts_P(_i("N/A"));
+		break;
+	}
 }
 
-static void menu_show_pinda_state()
+static void lcd_show_sensors_state()
 {
-lcd_timeoutToStatus.stop();
-lcd_show_pinda_state();
-if(LCD_CLICKED)
-     {
-     lcd_timeoutToStatus.start();
-     menu_back();
-     }
-}
-#endif // defined TMC2130
+	//0: N/A; 1: OFF; 2: ON
+	uint8_t chars = 0;
+	uint8_t pinda_state = STATE_NA;
+	uint8_t finda_state = STATE_NA;
+	uint8_t idler_state = STATE_NA;
 
+	pinda_state = READ(Z_MIN_PIN);
+	if (mmu_enabled) {
+		finda_state = mmu_finda;
+	}
+	if (mmu_idler_sensor_detected) {
+		idler_state = !PIN_GET(MMU_IDLER_SENSOR_PIN);
+	}
+	lcd_puts_at_P(0, 0, _i("Sensor state"));
+	lcd_puts_at_P(1, 1, _i("PINDA:"));
+	lcd_set_cursor(LCD_WIDTH - 4, 1);
+	lcd_print_state(pinda_state);
+	
+	lcd_puts_at_P(1, 2, _i("FINDA:"));
+	lcd_set_cursor(LCD_WIDTH - 4, 2);
+	lcd_print_state(finda_state);
+	
+	lcd_puts_at_P(1, 3, _i("IR:"));
+	lcd_set_cursor(LCD_WIDTH - 4, 3);
+	lcd_print_state(idler_state);
+}
 
+static void lcd_menu_show_sensors_state()
+{
+	lcd_timeoutToStatus.stop();
+	lcd_show_sensors_state();
+	if(LCD_CLICKED)
+	{
+		lcd_timeoutToStatus.start();
+		menu_back();
+	}
+}
 
 void prusa_statistics(int _message, uint8_t _fil_nr) {
 #ifdef DEBUG_DISABLE_PRUSA_STATISTICS
@@ -4949,9 +5039,7 @@ static void lcd_calibration_menu()
 
     MENU_ITEM_SUBMENU_P(_i("Bed level correct"), lcd_adjust_bed);////MSG_BED_CORRECTION_MENU c=0 r=0
 	MENU_ITEM_SUBMENU_P(_i("PID calibration"), pid_extruder);////MSG_PID_EXTRUDER c=17 r=1
-#ifdef TMC2130
-    MENU_ITEM_SUBMENU_P(_i("Show pinda state"), menu_show_pinda_state);
-#else
+#ifndef TMC2130
     MENU_ITEM_SUBMENU_P(_i("Show end stops"), menu_show_end_stops);////MSG_SHOW_END_STOPS c=17 r=1
 #endif
 #ifndef MK1BP
@@ -5858,7 +5946,9 @@ static void lcd_main_menu()
 #if defined(TMC2130) || defined(FILAMENT_SENSOR)
   MENU_ITEM_SUBMENU_P(_i("Fail stats"), lcd_menu_fails_stats);
 #endif
-
+  if (mmu_enabled) {
+	  MENU_ITEM_SUBMENU_P(_i("Fail stats MMU"), lcd_menu_fails_stats_mmu);
+  }
   MENU_ITEM_SUBMENU_P(_i("Support"), lcd_support_menu);////MSG_SUPPORT c=0 r=0
 #ifdef LCD_TEST
     MENU_ITEM_SUBMENU_P(_i("W25x20CL init"), lcd_test_menu);////MSG_SUPPORT c=0 r=0

+ 2 - 0
Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h

@@ -432,4 +432,6 @@ THERMISTORS SETTINGS
 //#define SUPPORT_VERBOSITY
 #endif
 
+#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
+
 #endif //__CONFIGURATION_PRUSA_H

+ 2 - 0
Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h

@@ -432,4 +432,6 @@ THERMISTORS SETTINGS
 //#define SUPPORT_VERBOSITY
 #endif
 
+#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
+
 #endif //__CONFIGURATION_PRUSA_H

+ 2 - 0
Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h

@@ -487,4 +487,6 @@
 #define MMU_REQUIRED_FW_BUILDNR 132
 //#define MMU_DEBUG //print communication between MMU2 and printer on serial
 
+#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
+
 #endif //__CONFIGURATION_PRUSA_H

+ 2 - 0
Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h

@@ -488,4 +488,6 @@
 #define MMU_REQUIRED_FW_BUILDNR 132
 //#define MMU_DEBUG //print communication between MMU2 and printer on serial
 
+#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
+
 #endif //__CONFIGURATION_PRUSA_H

+ 3 - 1
Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h

@@ -613,6 +613,8 @@
 
 #define MMU_REQUIRED_FW_BUILDNR 83
 #define MMU_HWRESET
-//#define MMU_DEBUG //print communication between MMU2 and printer on serial
+#define MMU_DEBUG //print communication between MMU2 and printer on serial
+
+#define MMU_IDLER_SENSOR_ATTEMPTS_NR 21 //max. number of attempts to load filament if first load failed; value for max bowden length and case when loading fails right at the beginning
 
 #endif //__CONFIGURATION_PRUSA_H