Browse Source

Merge branch 'MK3' into MK3_dev

Marek Bel 6 years ago
parent
commit
e5c0e26601

+ 1 - 0
.gitignore

@@ -12,3 +12,4 @@ Firmware/Doc
 /Firmware/Firmware - Shortcut.lnk
 /Firmware/variants/1_75mm_MK3-MMU-EINSy10a-E3Dv6full.h.bak
 /Firmware/Marlin_main.cpp~RF12cfae7.TMP
+/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h.bak

+ 2 - 2
Firmware/Configuration.h

@@ -7,8 +7,8 @@
 #define STR(x) STR_HELPER(x)
 
 // Firmware version
-#define FW_VERSION "3.4.0-RC1"
-#define FW_COMMIT_NR   1170
+#define FW_VERSION "3.4.0-RC2"
+#define FW_COMMIT_NR   1267
 // FW_VERSION_UNKNOWN means this is an unofficial build.
 // The firmware should only be checked into github with this symbol.
 #define FW_DEV_VERSION FW_VERSION_UNKNOWN

+ 1 - 1
Firmware/Marlin.h

@@ -349,6 +349,7 @@ extern bool sortAlpha;
 
 extern char dir_names[3][9];
 
+extern int8_t lcd_change_fil_state;
 // save/restore printing
 extern bool saved_printing;
 
@@ -397,7 +398,6 @@ uint8_t check_printer_version();
 float temp_compensation_pinda_thermistor_offset(float temperature_pinda);
 #endif //PINDA_THERMISTOR
 
-void wait_for_heater(long codenum);
 void serialecho_temperatures();
 bool check_commands();
 

+ 195 - 160
Firmware/Marlin_main.cpp

@@ -544,8 +544,9 @@ static bool saved_extruder_relative_mode = false;
 //===========================================================================
 
 static void get_arc_coordinates();
-static bool setTargetedHotend(int code);
+static bool setTargetedHotend(int code, uint8_t &extruder);
 static void print_time_remaining_init();
+static void wait_for_heater(long codenum, uint8_t extruder);
 
 uint16_t gcode_in_progress = 0;
 uint16_t mcode_in_progress = 0;
@@ -1355,6 +1356,7 @@ void setup()
 	plan_init();  // Initialize planner;
 
 	factory_reset();
+     lcd_encoder_diff=0;
 
 #ifdef TMC2130
 	uint8_t silentMode = eeprom_read_byte((uint8_t*)EEPROM_SILENT);
@@ -3112,8 +3114,25 @@ static void gcode_M600(bool automatic, float x_position, float y_position, float
         lcd_update_enable(true);
     }
 
-    if (mmu_enabled) mmu_M600_load_filament(automatic);
-    else M600_load_filament();
+    if (mmu_enabled)
+    {
+        if (!automatic) {
+            if (saved_printing) mmu_eject_filament(mmu_extruder, false); //if M600 was invoked by filament senzor (FINDA) eject filament so user can easily remove it
+            mmu_M600_wait_and_beep();
+            if (saved_printing) {
+
+                lcd_clear();
+                lcd_set_cursor(0, 2);
+                lcd_puts_P(_T(MSG_PLEASE_WAIT));
+
+                mmu_command(MMU_CMD_R0);
+                manage_response(false, false);
+            }
+        }
+        mmu_M600_load_filament(automatic);
+    }
+    else
+        M600_load_filament();
 
     if (!automatic) M600_check_state();
 
@@ -3171,10 +3190,7 @@ void gcode_M701()
 		custom_message_type = CUSTOM_MSG_TYPE_F_LOAD;
 
 #ifdef FILAMENT_SENSOR
-		if (mmu_enabled == false)
-		{
-			fsensor_oq_meassure_start(40);
-		}
+		fsensor_oq_meassure_start(40);
 #endif //FILAMENT_SENSOR
 
 		lcd_setstatuspgm(_T(MSG_LOADING_FILAMENT));
@@ -5349,15 +5365,18 @@ Sigma_Exit:
 		break;
 
     case 104: // M104
-      if(setTargetedHotend(104)){
-        break;
-      }
-      if (code_seen('S'))
-      {
-          setTargetHotendSafe(code_value(), tmp_extruder);
-      }
-      setWatch();
-      break;
+    {
+          uint8_t extruder;
+          if(setTargetedHotend(104,extruder)){
+            break;
+          }
+          if (code_seen('S'))
+          {
+              setTargetHotendSafe(code_value(), extruder);
+          }
+          setWatch();
+          break;
+    }
     case 112: //  M112 -Emergency Stop
       kill(_n(""), 3);
       break;
@@ -5365,14 +5384,16 @@ Sigma_Exit:
       if (code_seen('S')) setTargetBed(code_value());
       break;
     case 105 : // M105
-      if(setTargetedHotend(105)){
+    {
+      uint8_t extruder;
+      if(setTargetedHotend(105, extruder)){
         break;
         }
       #if defined(TEMP_0_PIN) && TEMP_0_PIN > -1
         SERIAL_PROTOCOLPGM("ok T:");
-        SERIAL_PROTOCOL_F(degHotend(tmp_extruder),1);
+        SERIAL_PROTOCOL_F(degHotend(extruder),1);
         SERIAL_PROTOCOLPGM(" /");
-        SERIAL_PROTOCOL_F(degTargetHotend(tmp_extruder),1);
+        SERIAL_PROTOCOL_F(degTargetHotend(extruder),1);
         #if defined(TEMP_BED_PIN) && TEMP_BED_PIN > -1
           SERIAL_PROTOCOLPGM(" B:");
           SERIAL_PROTOCOL_F(degBed(),1);
@@ -5397,7 +5418,7 @@ Sigma_Exit:
         SERIAL_PROTOCOL((EXTRUDER_WATTS * getHeaterPower(tmp_extruder))/127);
         SERIAL_PROTOCOLPGM("W");
       #else
-        SERIAL_PROTOCOL(getHeaterPower(tmp_extruder));
+        SERIAL_PROTOCOL(getHeaterPower(extruder));
       #endif
 
         SERIAL_PROTOCOLPGM(" B@:");
@@ -5455,9 +5476,11 @@ Sigma_Exit:
 		KEEPALIVE_STATE(NOT_BUSY);
       return;
       break;
+    }
     case 109:
     {// M109 - Wait for extruder heater to reach target.
-      if(setTargetedHotend(109)){
+      uint8_t extruder;
+      if(setTargetedHotend(109, extruder)){
         break;
       }
       LCD_MESSAGERPGM(_T(MSG_HEATING));
@@ -5468,10 +5491,10 @@ Sigma_Exit:
         autotemp_enabled=false;
       #endif
       if (code_seen('S')) {
-          setTargetHotendSafe(code_value(), tmp_extruder);
+          setTargetHotendSafe(code_value(), extruder);
               CooldownNoWait = true;
             } else if (code_seen('R')) {
-                setTargetHotendSafe(code_value(), tmp_extruder);
+                setTargetHotendSafe(code_value(), extruder);
         CooldownNoWait = false;
       }
       #ifdef AUTOTEMP
@@ -5488,13 +5511,13 @@ Sigma_Exit:
       codenum = millis();
 
       /* See if we are heating up or cooling down */
-      target_direction = isHeatingHotend(tmp_extruder); // true if heating, false if cooling
+      target_direction = isHeatingHotend(extruder); // true if heating, false if cooling
 	  
 	  KEEPALIVE_STATE(NOT_BUSY);
 
       cancel_heatup = false;
 
-	  wait_for_heater(codenum); //loops until target temperature is reached
+	  wait_for_heater(codenum, extruder); //loops until target temperature is reached
 
         LCD_MESSAGERPGM(_T(MSG_HEATING_COMPLETE));
 		KEEPALIVE_STATE(IN_HANDLER);
@@ -6020,25 +6043,26 @@ Sigma_Exit:
     #if EXTRUDERS > 1
     case 218: // M218 - set hotend offset (in mm), T<extruder_number> X<offset_on_X> Y<offset_on_Y>
     {
-      if(setTargetedHotend(218)){
+      uint8_t extruder;
+      if(setTargetedHotend(218, extruder)){
         break;
       }
       if(code_seen('X'))
       {
-        extruder_offset[X_AXIS][tmp_extruder] = code_value();
+        extruder_offset[X_AXIS][extruder] = code_value();
       }
       if(code_seen('Y'))
       {
-        extruder_offset[Y_AXIS][tmp_extruder] = code_value();
+        extruder_offset[Y_AXIS][extruder] = code_value();
       }
       SERIAL_ECHO_START;
       SERIAL_ECHORPGM(MSG_HOTEND_OFFSET);
-      for(tmp_extruder = 0; tmp_extruder < EXTRUDERS; tmp_extruder++)
+      for(extruder = 0; extruder < EXTRUDERS; extruder++)
       {
          SERIAL_ECHO(" ");
-         SERIAL_ECHO(extruder_offset[X_AXIS][tmp_extruder]);
+         SERIAL_ECHO(extruder_offset[X_AXIS][extruder]);
          SERIAL_ECHO(",");
-         SERIAL_ECHO(extruder_offset[Y_AXIS][tmp_extruder]);
+         SERIAL_ECHO(extruder_offset[Y_AXIS][extruder]);
       }
       SERIAL_ECHOLN("");
     }break;
@@ -6058,10 +6082,11 @@ Sigma_Exit:
         int tmp_code = code_value();
         if (code_seen('T'))
         {
-          if(setTargetedHotend(221)){
+          uint8_t extruder;
+          if(setTargetedHotend(221, extruder)){
             break;
           }
-          extruder_multiply[tmp_extruder] = tmp_code;
+          extruder_multiply[extruder] = tmp_code;
         }
         else
         {
@@ -6789,132 +6814,132 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 
   else if(code_seen('T'))
   {
-	  int index;
-	  st_synchronize();
-	  for (index = 1; *(strchr_pointer + index) == ' ' || *(strchr_pointer + index) == '\t'; index++);
-	   
-	  if ((*(strchr_pointer + index) < '0' || *(strchr_pointer + index) > '9') && *(strchr_pointer + index) != '?') {
-		  SERIAL_ECHOLNPGM("Invalid T code.");
-	  }
-	  else {
-		  if (*(strchr_pointer + index) == '?') {
-			  tmp_extruder = choose_extruder_menu();
-		  }
-		  else {
-			  tmp_extruder = code_value();
-		  }
-		  snmm_filaments_used |= (1 << tmp_extruder); //for stop print
+      int index;
+      st_synchronize();
+      for (index = 1; *(strchr_pointer + index) == ' ' || *(strchr_pointer + index) == '\t'; index++);
 
-if (mmu_enabled)
-{
-		  //printf_P(PSTR("T code: %d \n"), tmp_extruder);
-		  //mmu_printf_P(PSTR("T%d\n"), tmp_extruder);
-		  mmu_command(MMU_CMD_T0 + tmp_extruder);
+      if ((*(strchr_pointer + index) < '0' || *(strchr_pointer + index) > '4') && *(strchr_pointer + index) != '?') {
+          SERIAL_ECHOLNPGM("Invalid T code.");
+      }
+      else {
+          if (*(strchr_pointer + index) == '?') {
+              tmp_extruder = choose_extruder_menu();
+          }
+          else {
+              tmp_extruder = code_value();
+          }
+          snmm_filaments_used |= (1 << tmp_extruder); //for stop print
 
-		  manage_response(true, true);
-		  mmu_command(MMU_CMD_C0);
-    	  mmu_extruder = tmp_extruder; //filament change is finished
+          if (mmu_enabled)
+          {
+              mmu_command(MMU_CMD_T0 + tmp_extruder);
 
-		  if (*(strchr_pointer + index) == '?')// for single material usage with mmu
-			  mmu_load_to_nozzle();
-}
-else
-{
+              manage_response(true, true);
+              mmu_command(MMU_CMD_C0);
+              mmu_extruder = tmp_extruder; //filament change is finished
+
+              if (*(strchr_pointer + index) == '?')// for single material usage with mmu
+              {
+                  mmu_load_to_nozzle();
+              }
+          }
+          else
+          {
 #ifdef SNMM
 
-	#ifdef LIN_ADVANCE
-          if (mmu_extruder != tmp_extruder)
-            clear_current_adv_vars(); //Check if the selected extruder is not the active one and reset LIN_ADVANCE variables if so.
-	#endif
-          
-		  mmu_extruder = tmp_extruder;
+#ifdef LIN_ADVANCE
+              if (mmu_extruder != tmp_extruder)
+                  clear_current_adv_vars(); //Check if the selected extruder is not the active one and reset LIN_ADVANCE variables if so.
+#endif
 
-		  
-		  delay(100);
-
-		  disable_e0();
-		  disable_e1();
-		  disable_e2();
-
-		  pinMode(E_MUX0_PIN, OUTPUT);
-		  pinMode(E_MUX1_PIN, OUTPUT);
-
-		  delay(100);
-		  SERIAL_ECHO_START;
-		  SERIAL_ECHO("T:");
-		  SERIAL_ECHOLN((int)tmp_extruder);
-		  switch (tmp_extruder) {
-		  case 1:
-			  WRITE(E_MUX0_PIN, HIGH);
-			  WRITE(E_MUX1_PIN, LOW);
-
-			  break;
-		  case 2:
-			  WRITE(E_MUX0_PIN, LOW);
-			  WRITE(E_MUX1_PIN, HIGH);
-
-			  break;
-		  case 3:
-			  WRITE(E_MUX0_PIN, HIGH);
-			  WRITE(E_MUX1_PIN, HIGH);
-
-			  break;
-		  default:
-			  WRITE(E_MUX0_PIN, LOW);
-			  WRITE(E_MUX1_PIN, LOW);
-
-			  break;
-		  }
-		  delay(100);
+              mmu_extruder = tmp_extruder;
+
+
+              delay(100);
+
+              disable_e0();
+              disable_e1();
+              disable_e2();
+
+              pinMode(E_MUX0_PIN, OUTPUT);
+              pinMode(E_MUX1_PIN, OUTPUT);
+
+              delay(100);
+              SERIAL_ECHO_START;
+              SERIAL_ECHO("T:");
+              SERIAL_ECHOLN((int)tmp_extruder);
+              switch (tmp_extruder) {
+              case 1:
+                  WRITE(E_MUX0_PIN, HIGH);
+                  WRITE(E_MUX1_PIN, LOW);
+
+                  break;
+              case 2:
+                  WRITE(E_MUX0_PIN, LOW);
+                  WRITE(E_MUX1_PIN, HIGH);
+
+                  break;
+              case 3:
+                  WRITE(E_MUX0_PIN, HIGH);
+                  WRITE(E_MUX1_PIN, HIGH);
+
+                  break;
+              default:
+                  WRITE(E_MUX0_PIN, LOW);
+                  WRITE(E_MUX1_PIN, LOW);
+
+                  break;
+              }
+              delay(100);
 
 #else //SNMM
-		  if (tmp_extruder >= EXTRUDERS) {
-			  SERIAL_ECHO_START;
-			  SERIAL_ECHOPGM("T");
-			  SERIAL_PROTOCOLLN((int)tmp_extruder);
-			  SERIAL_ECHOLNRPGM(_n("Invalid extruder"));////MSG_INVALID_EXTRUDER c=0 r=0
-		  }
-		  else {
-			#if EXTRUDERS > 1
-		      boolean make_move = false;
-			#endif
-			  if (code_seen('F')) {
-			#if EXTRUDERS > 1
-				  make_move = true;
-			#endif
-				  next_feedrate = code_value();
-				  if (next_feedrate > 0.0) {
-					  feedrate = next_feedrate;
-				  }
-			  }
-			#if EXTRUDERS > 1
-			  if (tmp_extruder != active_extruder) {
-				  // Save current position to return to after applying extruder offset
-				  memcpy(destination, current_position, sizeof(destination));
-				  // Offset extruder (only by XY)
-				  int i;
-				  for (i = 0; i < 2; i++) {
-					  current_position[i] = current_position[i] -
-						  extruder_offset[i][active_extruder] +
-						  extruder_offset[i][tmp_extruder];
-				  }
-				  // Set the new active extruder and position
-				  active_extruder = tmp_extruder;
-				  plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
-				  // Move to the old position if 'F' was in the parameters
-				  if (make_move && Stopped == false) {
-					  prepare_move();
-				  }
-			  }
-			#endif
-			  SERIAL_ECHO_START;
-			  SERIAL_ECHORPGM(_n("Active Extruder: "));////MSG_ACTIVE_EXTRUDER c=0 r=0
-			  SERIAL_PROTOCOLLN((int)active_extruder);
-		  }
+              if (tmp_extruder >= EXTRUDERS) {
+                  SERIAL_ECHO_START;
+                  SERIAL_ECHOPGM("T");
+                  SERIAL_PROTOCOLLN((int)tmp_extruder);
+                  SERIAL_ECHOLNRPGM(_n("Invalid extruder"));////MSG_INVALID_EXTRUDER c=0 r=0
+              }
+              else {
+#if EXTRUDERS > 1
+                  boolean make_move = false;
+#endif
+                  if (code_seen('F')) {
+#if EXTRUDERS > 1
+                      make_move = true;
+#endif
+                      next_feedrate = code_value();
+                      if (next_feedrate > 0.0) {
+                          feedrate = next_feedrate;
+                      }
+                  }
+#if EXTRUDERS > 1
+                  if (tmp_extruder != active_extruder) {
+                      // Save current position to return to after applying extruder offset
+                      memcpy(destination, current_position, sizeof(destination));
+                      // Offset extruder (only by XY)
+                      int i;
+                      for (i = 0; i < 2; i++) {
+                          current_position[i] = current_position[i] -
+                                  extruder_offset[i][active_extruder] +
+                                  extruder_offset[i][tmp_extruder];
+                      }
+                      // Set the new active extruder and position
+                      active_extruder = tmp_extruder;
+                      plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
+                      // Move to the old position if 'F' was in the parameters
+                      if (make_move && Stopped == false) {
+                          prepare_move();
+                      }
+                  }
+#endif
+                  SERIAL_ECHO_START;
+                  SERIAL_ECHORPGM(_n("Active Extruder: "));////MSG_ACTIVE_EXTRUDER c=0 r=0
+                  SERIAL_PROTOCOLLN((int)active_extruder);
+              }
 
 #endif //SNMM
-}
-	  }
+          }
+      }
   } // end if(code_seen('T')) (end of T codes)
 
   else if (code_seen('D')) // D codes (debug)
@@ -7567,11 +7592,21 @@ void setPwmFrequency(uint8_t pin, int val)
 }
 #endif //FAST_PWM_FAN
 
-bool setTargetedHotend(int code){
-  tmp_extruder = active_extruder;
+//! @brief Get and validate extruder number
+//!
+//! If it is not specified, active_extruder is returned in parameter extruder.
+//! @param [in] code M code number
+//! @param [out] extruder
+//! @return error
+//! @retval true Invalid extruder specified in T code
+//! @retval false Valid extruder specified in T code, or not specifiead
+
+bool setTargetedHotend(int code, uint8_t &extruder)
+{
+  extruder = active_extruder;
   if(code_seen('T')) {
-    tmp_extruder = code_value();
-    if(tmp_extruder >= EXTRUDERS) {
+      extruder = code_value();
+    if(extruder >= EXTRUDERS) {
       SERIAL_ECHO_START;
       switch(code){
         case 104:
@@ -7590,7 +7625,7 @@ bool setTargetedHotend(int code){
           SERIAL_ECHO(_i("M221 Invalid extruder "));////MSG_M221_INVALID_EXTRUDER c=0 r=0
           break;
       }
-      SERIAL_PROTOCOLLN((int)tmp_extruder);
+      SERIAL_PROTOCOLLN((int)extruder);
       return true;
     }
   }
@@ -7655,7 +7690,7 @@ void delay_keep_alive(unsigned int ms)
     }
 }
 
-void wait_for_heater(long codenum) {
+static void wait_for_heater(long codenum, uint8_t extruder) {
 
 #ifdef TEMP_RESIDENCY_TIME
 	long residencyStart;
@@ -7671,9 +7706,9 @@ void wait_for_heater(long codenum) {
 		{ //Print Temp Reading and remaining time every 1 second while heating up/cooling down
 			if (!farm_mode) {
 				SERIAL_PROTOCOLPGM("T:");
-				SERIAL_PROTOCOL_F(degHotend(tmp_extruder), 1);
+				SERIAL_PROTOCOL_F(degHotend(extruder), 1);
 				SERIAL_PROTOCOLPGM(" E:");
-				SERIAL_PROTOCOL((int)tmp_extruder);
+				SERIAL_PROTOCOL((int)extruder);
 
 #ifdef TEMP_RESIDENCY_TIME
 				SERIAL_PROTOCOLPGM(" W:");
@@ -7698,9 +7733,9 @@ void wait_for_heater(long codenum) {
 #ifdef TEMP_RESIDENCY_TIME
 			/* start/restart the TEMP_RESIDENCY_TIME timer whenever we reach target temp for the first time
 			or when current temp falls outside the hysteresis after target temp was reached */
-			if ((residencyStart == -1 && target_direction && (degHotend(tmp_extruder) >= (degTargetHotend(tmp_extruder) - TEMP_WINDOW))) ||
-				(residencyStart == -1 && !target_direction && (degHotend(tmp_extruder) <= (degTargetHotend(tmp_extruder) + TEMP_WINDOW))) ||
-				(residencyStart > -1 && labs(degHotend(tmp_extruder) - degTargetHotend(tmp_extruder)) > TEMP_HYSTERESIS))
+			if ((residencyStart == -1 && target_direction && (degHotend(extruder) >= (degTargetHotend(extruder) - TEMP_WINDOW))) ||
+				(residencyStart == -1 && !target_direction && (degHotend(extruder) <= (degTargetHotend(extruder) + TEMP_WINDOW))) ||
+				(residencyStart > -1 && labs(degHotend(extruder) - degTargetHotend(extruder)) > TEMP_HYSTERESIS))
 			{
 				residencyStart = millis();
 			}

+ 95 - 10
Firmware/mmu.cpp

@@ -22,7 +22,7 @@
 #define MMU_HWRESET
 #define MMU_RST_PIN 76
 
-#define MMU_REQUIRED_FW_BUILDNR 81
+#define MMU_REQUIRED_FW_BUILDNR 83
 
 bool mmu_enabled = false;
 
@@ -104,6 +104,7 @@ void mmu_init(void)
 //mmu main loop - state machine processing
 void mmu_loop(void)
 {
+	int filament = 0;
 //	printf_P(PSTR("MMU loop, state=%d\n"), mmu_state);
 	switch (mmu_state)
 	{
@@ -161,14 +162,14 @@ void mmu_loop(void)
 		{
 			if ((mmu_cmd >= MMU_CMD_T0) && (mmu_cmd <= MMU_CMD_T4))
 			{
-				int extruder = mmu_cmd - MMU_CMD_T0;
-				printf_P(PSTR("MMU <= 'T%d'\n"), extruder);
-				mmu_printf_P(PSTR("T%d\n"), extruder);
+				filament = mmu_cmd - MMU_CMD_T0;
+				printf_P(PSTR("MMU <= 'T%d'\n"), filament);
+				mmu_printf_P(PSTR("T%d\n"), filament);
 				mmu_state = 3; // wait for response
 			}
 			else if ((mmu_cmd >= MMU_CMD_L0) && (mmu_cmd <= MMU_CMD_L4))
 			{
-			    int filament = mmu_cmd - MMU_CMD_L0;
+			    filament = mmu_cmd - MMU_CMD_L0;
 			    printf_P(PSTR("MMU <= 'L%d'\n"), filament);
 			    mmu_printf_P(PSTR("L%d\n"), filament);
 			    mmu_state = 3; // wait for response
@@ -185,6 +186,19 @@ void mmu_loop(void)
 				mmu_puts_P(PSTR("U0\n")); //send 'unload current filament'
 				mmu_state = 3;
 			}
+			else if ((mmu_cmd >= MMU_CMD_E0) && (mmu_cmd <= MMU_CMD_E4))
+			{
+				int filament = mmu_cmd - MMU_CMD_E0;
+				printf_P(PSTR("MMU <= 'E%d'\n"), filament);
+				mmu_printf_P(PSTR("E%d\n"), filament); //send eject filament
+				mmu_state = 3; // wait for response
+			}
+			else if (mmu_cmd == MMU_CMD_R0)
+			{
+				printf_P(PSTR("MMU <= 'R0'\n"));
+				mmu_puts_P(PSTR("R0\n")); //send recover after eject
+				mmu_state = 3; // wait for response
+			}
 			mmu_cmd = 0;
 		}
 		else if ((mmu_last_response + 300) < millis()) //request every 300ms
@@ -215,7 +229,7 @@ void mmu_loop(void)
 			mmu_state = 1;
 		}
 		return;
-	case 3: //response to commands T0-T4
+	case 3: //response to mmu commands
 		if (mmu_rx_ok() > 0)
 		{
 			printf_P(PSTR("MMU => 'ok'\n"));
@@ -381,6 +395,12 @@ void manage_response(bool move_axes, bool turn_off_nozzle)
 	if (lcd_update_was_enabled) lcd_update_enable(true);
 }
 
+//! @brief 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 mmu_load_to_nozzle()
 {
 	st_synchronize();
@@ -449,15 +469,12 @@ void mmu_M600_load_filament(bool automatic)
 		  bool yes = false;
 		  tmp_extruder = mmu_extruder;
 		  if (!automatic) {
-			  mmu_M600_wait_and_beep();
 #ifdef MMU_M600_SWITCH_EXTRUDER
 			  yes = lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Do you want to switch extruder?"), false);
 			  if(yes) tmp_extruder = choose_extruder_menu();
 			  else tmp_extruder = mmu_extruder;
-#else 
-			  tmp_extruder = mmu_extruder; 
 #endif //MMU_M600_SWITCH_EXTRUDER
-      }
+		  }
 		  else {
 			  tmp_extruder = (tmp_extruder+1)%5;
 		  }
@@ -775,6 +792,31 @@ void extr_adj_4()
 #endif
 }
 
+void mmu_eject_fil_0()
+{
+	mmu_eject_filament(0, true);
+}
+
+void mmu_eject_fil_1()
+{
+	mmu_eject_filament(1, true);
+}
+
+void mmu_eject_fil_2()
+{
+	mmu_eject_filament(2, true);
+}
+
+void mmu_eject_fil_3()
+{
+	mmu_eject_filament(3, true);
+}
+
+void mmu_eject_fil_4()
+{
+	mmu_eject_filament(4, true);
+}
+
 void load_all()
 {
 #ifndef SNMM
@@ -905,3 +947,46 @@ void mmu_show_warning()
 	printf_P(PSTR("MMU2 firmware version invalid. Required version: build number %d or higher."), MMU_REQUIRED_FW_BUILDNR);
 	kill(_i("Please update firmware in your MMU2. Waiting for reset."));
 }
+
+void mmu_eject_filament(uint8_t filament, bool recover)
+{
+	if (filament < 5) 
+	{
+
+		if (degHotend0() > EXTRUDE_MINTEMP)
+		{
+			st_synchronize();
+			lcd_update_enable(false);
+			lcd_clear();
+			lcd_set_cursor(0, 1); lcd_puts_P(_i("Ejecting filament"));
+			current_position[E_AXIS] -= 80;
+			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();
+
+			lcd_update_enable(true);
+
+			mmu_command(MMU_CMD_E0 + filament);
+			manage_response(false, false);
+			if (recover)
+			{
+				lcd_show_fullscreen_message_and_wait_P(_i("Please remove filament and then press the knob."));
+				mmu_command(MMU_CMD_R0);
+				manage_response(false, false);
+			}
+		}
+		else
+		{
+			lcd_clear();
+			lcd_set_cursor(0, 0);
+			lcd_puts_P(_T(MSG_ERROR));
+			lcd_set_cursor(0, 2);
+			lcd_puts_P(_T(MSG_PREHEAT_NOZZLE));
+			delay(2000);
+			lcd_clear();
+		}
+	}
+	else
+	{
+		puts_P(PSTR("Filament nr out of range!"));
+	}
+}

+ 13 - 1
Firmware/mmu.h

@@ -28,6 +28,13 @@ extern int16_t mmu_buildnr;
 #define MMU_CMD_L4   0x24
 #define MMU_CMD_C0   0x30
 #define MMU_CMD_U0   0x40
+#define MMU_CMD_E0   0x50
+#define MMU_CMD_E1   0x51
+#define MMU_CMD_E2   0x52
+#define MMU_CMD_E3   0x53
+#define MMU_CMD_E4   0x54
+#define MMU_CMD_R0   0x60
+
 
 extern int mmu_puts_P(const char* str);
 
@@ -82,4 +89,9 @@ extern void extr_unload_4();
 
 extern bool mmu_check_version();
 extern void mmu_show_warning();
-
+extern void mmu_eject_filament(uint8_t filament, bool recover);
+extern void mmu_eject_fil_0();
+extern void mmu_eject_fil_1();
+extern void mmu_eject_fil_2();
+extern void mmu_eject_fil_3();
+extern void mmu_eject_fil_4();

+ 41 - 2
Firmware/ultralcd.cpp

@@ -3551,6 +3551,27 @@ void lcd_diag_show_end_stops()
     lcd_return_to_status();
 }
 
+#ifdef TMC2130
+static void lcd_show_pinda_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)
+}
+
+static void menu_show_pinda_state()
+{
+lcd_timeoutToStatus.stop();
+lcd_show_pinda_state();
+if(LCD_CLICKED)
+     {
+     lcd_timeoutToStatus.start();
+     menu_back();
+     }
+}
+#endif // defined TMC2130
+
 
 
 void prusa_statistics(int _message, uint8_t _fil_nr) {
@@ -4379,6 +4400,7 @@ void lcd_wizard(int state) {
 			break;
 		case 5: //is filament loaded?
 				//start to preheat nozzle and bed to save some time later
+               lcd_commands_type = LCD_COMMAND_V2_CAL;
 			setTargetHotend(PLA_PREHEAT_HOTEND_TEMP, 0);
 			setTargetBed(PLA_PREHEAT_HPB_TEMP);
 			wizard_event = lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Is filament loaded?"), false);////MSG_WIZARD_FILAMENT_LOADED c=20 r=2
@@ -4416,6 +4438,7 @@ void lcd_wizard(int state) {
 #ifdef SNMM
 			change_extr(0);
 #endif
+               loading_flag = true;
 			gcode_M701();
 			state = 9;
 			break;
@@ -4784,7 +4807,9 @@ 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
-#ifndef TMC2130
+#ifdef TMC2130
+    MENU_ITEM_SUBMENU_P(_i("Show pinda state"), menu_show_pinda_state);
+#else
     MENU_ITEM_SUBMENU_P(_i("Show end stops"), menu_show_end_stops);////MSG_SHOW_END_STOPS c=17 r=1
 #endif
 #ifndef MK1BP
@@ -5171,6 +5196,19 @@ static void fil_load_menu()
 	MENU_END();
 }
 
+static void mmu_fil_eject_menu()
+{
+	MENU_BEGIN();
+	MENU_ITEM_BACK_P(_T(MSG_MAIN));
+	MENU_ITEM_FUNCTION_P(_i("Eject filament 1"), mmu_eject_fil_0);
+	MENU_ITEM_FUNCTION_P(_i("Eject filament 2"), mmu_eject_fil_1);
+	MENU_ITEM_FUNCTION_P(_i("Eject filament 3"), mmu_eject_fil_2);
+	MENU_ITEM_FUNCTION_P(_i("Eject filament 4"), mmu_eject_fil_3);
+	MENU_ITEM_FUNCTION_P(_i("Eject filament 5"), mmu_eject_fil_4);
+
+	MENU_END();
+}
+
 static void fil_unload_menu()
 {
 	MENU_BEGIN();
@@ -5552,7 +5590,7 @@ static void lcd_main_menu()
     
         
     }*/
-    
+ 
   if ( ( IS_SD_PRINTING || is_usb_printing || (lcd_commands_type == LCD_COMMAND_V2_CAL)) && (current_position[Z_AXIS] < Z_HEIGHT_HIDE_LIVE_ADJUST_MENU) && !homing_flag && !mesh_bed_leveling_flag)
   {
 	MENU_ITEM_SUBMENU_P(_T(MSG_BABYSTEP_Z), lcd_babystep_z);//8
@@ -5621,6 +5659,7 @@ static void lcd_main_menu()
 	if (mmu_enabled)
 	{
 		MENU_ITEM_SUBMENU_P(_T(MSG_LOAD_FILAMENT), fil_load_menu);
+		MENU_ITEM_SUBMENU_P(_i("Eject filament"), mmu_fil_eject_menu);
 		if (mmu_enabled)
 			MENU_ITEM_GCODE_P(_T(MSG_UNLOAD_FILAMENT), PSTR("M702 C"));
 		else

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

@@ -183,6 +183,7 @@
 #define CMD_DIAGNOSTICS //Show cmd queue length on printer display
 #endif /* DEBUG_BUILD */
 
+#define LINEARITY_CORRECTION
 #define TMC2130_LINEARITY_CORRECTION
 #define TMC2130_LINEARITY_CORRECTION_XYZ
 //#define TMC2130_VARIABLE_RESOLUTION