Просмотр исходного кода

Merge remote-tracking branch 'upstream/MK25' into MK25

# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
Robert Pelnar 6 лет назад
Родитель
Сommit
a6f900fd3c

+ 2 - 29
Firmware/Configuration.h

@@ -8,7 +8,7 @@
 
 // Firmware version
 #define FW_VERSION "3.1.2-alpha"
-#define FW_COMMIT_NR   201
+#define FW_COMMIT_NR   255
 // 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
@@ -789,34 +789,7 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
 //
 //#define NUM_SERVOS 3 // Servo index starts with 0 for M280 command
 
-/**********************************************************************\
- * Support for a filament diameter sensor
- * Also allows adjustment of diameter at print time (vs  at slicing)
- * Single extruder only at this point (extruder 0)
- * 
- * Motherboards
- * 34 - RAMPS1.4 - uses Analog input 5 on the AUX2 connector 
- * 81 - Printrboard - Uses Analog input 2 on the Exp1 connector (version B,C,D,E)
- * 301 - Rambo  - uses Analog input 3
- * Note may require analog pins to be defined for different motherboards
- **********************************************************************/
-// Uncomment below to enable
-//#define FILAMENT_SENSOR
-
-#define FILAMENT_SENSOR_EXTRUDER_NUM	0  //The number of the extruder that has the filament sensor (0,1,2)
-#define MEASUREMENT_DELAY_CM			14  //measurement delay in cm.  This is the distance from filament sensor to middle of barrel
-
-#define DEFAULT_NOMINAL_FILAMENT_DIA  3.0  //Enter the diameter (in mm) of the filament generally used (3.0 mm or 1.75 mm) - this is then used in the slicer software.  Used for sensor reading validation
-#define MEASURED_UPPER_LIMIT          3.30  //upper limit factor used for sensor reading validation in mm
-#define MEASURED_LOWER_LIMIT          1.90  //lower limit factor for sensor reading validation in mm
-#define MAX_MEASUREMENT_DELAY			20  //delay buffer size in bytes (1 byte = 1cm)- limits maximum measurement delay allowable (must be larger than MEASUREMENT_DELAY_CM  and lower number saves RAM)
-
-//defines used in the code
-#define DEFAULT_MEASURED_FILAMENT_DIA  DEFAULT_NOMINAL_FILAMENT_DIA  //set measured to nominal initially 
-
-//When using an LCD, uncomment the line below to display the Filament sensor data on the last line instead of status.  Status will appear for 5 sec.
-//#define FILAMENT_LCD_DISPLAY
-
+#define DEFAULT_NOMINAL_FILAMENT_DIA  1.75  //Enter the diameter (in mm) of the filament generally used (3.0 mm or 1.75 mm). Used by the volumetric extrusion.
 
 // Calibration status of the machine, to be stored into the EEPROM,
 // (unsigned char*)EEPROM_CALIBRATION_STATUS

+ 2 - 2
Firmware/ConfigurationStore.cpp

@@ -378,8 +378,8 @@ bool Config_RetrieveSettings(uint16_t offset, uint8_t level)
 			EEPROM_READ_VAR(i, extruder_advance_k);
 			EEPROM_READ_VAR(i, advance_ed_ratio);
 		}
-		calculate_volumetric_multipliers();
 #endif //LIN_ADVANCE
+    calculate_extruder_multipliers();
 
 		// Call updatePID (similar to when we have processed M301)
 		updatePID();
@@ -472,7 +472,7 @@ void Config_ResetDefault()
 	filament_size[2] = DEFAULT_NOMINAL_FILAMENT_DIA;
 #endif
 #endif
-	calculate_volumetric_multipliers();
+	calculate_extruder_multipliers();
 
 SERIAL_ECHO_START;
 SERIAL_ECHOLNPGM("Hardcoded Default Settings Loaded");

+ 3 - 3
Firmware/Configuration_prusa.h

@@ -60,7 +60,7 @@ const bool Z_MIN_ENDSTOP_INVERTING = false; // set to true to invert the logic o
 #define X_MIN_POS 0
 #define Y_MAX_POS 210
 #define Y_MIN_POS -4
-#define Z_MAX_POS 200
+#define Z_MAX_POS 210
 #define Z_MIN_POS 0.15
 
 // Canceled home position
@@ -168,7 +168,7 @@ const bool Z_MIN_ENDSTOP_INVERTING = false; // set to true to invert the logic o
 #define EXTRUDER_AUTO_FAN_SPEED   255  // == full speed
 
 
-#define PAT9125
+#define PAT9125 //!< Filament sensor
 #define FANCHECK
 #define SAFETYTIMER
 
@@ -469,6 +469,6 @@ const bool Z_MIN_ENDSTOP_INVERTING = false; // set to true to invert the logic o
 
 #define M600_TIMEOUT 600  //seconds
 
-//#define SUPPORT_VERBOSITY
+#define SUPPORT_VERBOSITY
 
 #endif //__CONFIGURATION_PRUSA_H

+ 3 - 12
Firmware/Marlin.h

@@ -218,6 +218,7 @@ enum AxisEnum {X_AXIS=0, Y_AXIS=1, Z_AXIS=2, E_AXIS=3, X_HEAD=4, Y_HEAD=5};
 
 void FlushSerialRequestResend();
 void ClearToSend();
+void update_currents();
 
 void get_coordinates();
 void prepare_move();
@@ -283,17 +284,6 @@ extern void homeaxis(int axis);
 extern unsigned char fanSpeedSoftPwm;
 #endif
 
-
-#ifdef FILAMENT_SENSOR
-  extern float filament_width_nominal;  //holds the theoretical filament diameter ie., 3.00 or 1.75
-  extern bool filament_sensor;  //indicates that filament sensor readings should control extrusion
-  extern float filament_width_meas; //holds the filament diameter as accurately measured
-  extern signed char measurement_delay[];  //ring buffer to delay measurement
-  extern int delay_index1, delay_index2;  //index into ring buffer
-  extern float delay_dist; //delay distance counter
-  extern int meas_delay_cm; //delay distance
-#endif
-
 #ifdef FWRETRACT
 extern bool autoretract_enabled;
 extern bool retracted[EXTRUDERS];
@@ -358,7 +348,7 @@ extern bool sortAlpha;
 
 extern char dir_names[3][9];
 
-extern void calculate_volumetric_multipliers();
+extern void calculate_extruder_multipliers();
 
 // Similar to the default Arduino delay function, 
 // but it keeps the background tasks running.
@@ -446,6 +436,7 @@ void force_high_power_mode(bool start_high_power_section);
 
 // G-codes
 bool gcode_M45(bool onlyZ, int8_t verbosity_level);
+void gcode_M114();
 void gcode_M701();
 
 #define UVLO !(PINE & (1<<4))

+ 102 - 129
Firmware/Marlin_main.cpp

@@ -334,7 +334,7 @@ float filament_size[EXTRUDERS] = { DEFAULT_NOMINAL_FILAMENT_DIA
     #endif
   #endif
 };
-float volumetric_multiplier[EXTRUDERS] = {1.0
+float extruder_multiplier[EXTRUDERS] = {1.0
   #if EXTRUDERS > 1
     , 1.0
     #if EXTRUDERS > 2
@@ -411,18 +411,6 @@ bool cancel_heatup = false ;
   #define KEEPALIVE_STATE(n);
 #endif
 
-#ifdef FILAMENT_SENSOR
-  //Variables for Filament Sensor input 
-  float filament_width_nominal=DEFAULT_NOMINAL_FILAMENT_DIA;  //Set nominal filament width, can be changed with M404 
-  bool filament_sensor=false;  //M405 turns on filament_sensor control, M406 turns it off 
-  float filament_width_meas=DEFAULT_MEASURED_FILAMENT_DIA; //Stores the measured filament diameter 
-  signed char measurement_delay[MAX_MEASUREMENT_DELAY+1];  //ring buffer to delay measurement  store extruder factor after subtracting 100 
-  int delay_index1=0;  //index into ring buffer
-  int delay_index2=-1;  //index into ring buffer - set to -1 on startup to indicate ring buffer needs to be initialized
-  float delay_dist=0; //delay distance counter  
-  int meas_delay_cm = MEASUREMENT_DELAY_CM;  //distance delay setting
-#endif
-
 const char errormagic[] PROGMEM = "Error:";
 const char echomagic[] PROGMEM = "echo:";
 
@@ -693,6 +681,7 @@ void crashdet_cancel()
 	card.closefile();
 	tmc2130_sg_stop_on_crash = true;
 }
+#endif //TMC2130
 
 void failstats_reset_print()
 {
@@ -702,7 +691,6 @@ void failstats_reset_print()
 	eeprom_update_byte((uint8_t *)EEPROM_POWER_COUNT, 0);
 }
 
-#endif //TMC2130
 
 
 #ifdef MESH_BED_LEVELING
@@ -1971,11 +1959,7 @@ void refresh_cmd_timeout(void)
       destination[Y_AXIS]=current_position[Y_AXIS];
       destination[Z_AXIS]=current_position[Z_AXIS];
       destination[E_AXIS]=current_position[E_AXIS];
-      if (swapretract) {
-        current_position[E_AXIS]+=retract_length_swap/volumetric_multiplier[active_extruder];
-      } else {
-        current_position[E_AXIS]+=retract_length/volumetric_multiplier[active_extruder];
-      }
+      current_position[E_AXIS]+=(swapretract?retract_length_swap:retract_length)*float(extrudemultiply)*0.01f;
       plan_set_e_position(current_position[E_AXIS]);
       float oldFeedrate = feedrate;
       feedrate=retract_feedrate*60;
@@ -1992,12 +1976,7 @@ void refresh_cmd_timeout(void)
       destination[E_AXIS]=current_position[E_AXIS];
       current_position[Z_AXIS]+=retract_zlift;
       plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
-      //prepare_move();
-      if (swapretract) {
-        current_position[E_AXIS]-=(retract_length_swap+retract_recover_length_swap)/volumetric_multiplier[active_extruder]; 
-      } else {
-        current_position[E_AXIS]-=(retract_length+retract_recover_length)/volumetric_multiplier[active_extruder]; 
-      }
+      current_position[E_AXIS]-=(swapretract?(retract_length_swap+retract_recover_length_swap):(retract_length+retract_recover_length))*float(extrudemultiply)*0.01f;
       plan_set_e_position(current_position[E_AXIS]);
       float oldFeedrate = feedrate;
       feedrate=retract_recover_feedrate*60;
@@ -2249,8 +2228,12 @@ bool gcode_M45(bool onlyZ, int8_t verbosity_level)
 				current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
 				plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], homing_feedrate[Z_AXIS] / 40, active_extruder);
 				st_synchronize();
+				
 				if (result >= 0)
 				{
+					#ifdef HEATBED_V2
+					sample_z();
+					#else //HEATBED_V2
 					point_too_far_mask = 0;
 					// Second half: The fine adjustment.
 					// Let the planner use the uncorrected coordinates.
@@ -2265,8 +2248,10 @@ bool gcode_M45(bool onlyZ, int8_t verbosity_level)
 					current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
 					plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], homing_feedrate[Z_AXIS] / 40, active_extruder);
 					st_synchronize();
-					// if (result >= 0) babystep_apply();
+					// if (result >= 0) babystep_apply();					
+					#endif //HEATBED_V2
 				}
+				
 				lcd_bed_calibration_show_result(result, point_too_far_mask);
 				if (result >= 0)
 				{
@@ -2297,6 +2282,29 @@ bool gcode_M45(bool onlyZ, int8_t verbosity_level)
 	return final_result;
 }
 
+void gcode_M114()
+{
+	SERIAL_PROTOCOLPGM("X:");
+	SERIAL_PROTOCOL(current_position[X_AXIS]);
+	SERIAL_PROTOCOLPGM(" Y:");
+	SERIAL_PROTOCOL(current_position[Y_AXIS]);
+	SERIAL_PROTOCOLPGM(" Z:");
+	SERIAL_PROTOCOL(current_position[Z_AXIS]);
+	SERIAL_PROTOCOLPGM(" E:");
+	SERIAL_PROTOCOL(current_position[E_AXIS]);
+
+	SERIAL_PROTOCOLRPGM(MSG_COUNT_X);
+	SERIAL_PROTOCOL(float(st_get_position(X_AXIS)) / axis_steps_per_unit[X_AXIS]);
+	SERIAL_PROTOCOLPGM(" Y:");
+	SERIAL_PROTOCOL(float(st_get_position(Y_AXIS)) / axis_steps_per_unit[Y_AXIS]);
+	SERIAL_PROTOCOLPGM(" Z:");
+	SERIAL_PROTOCOL(float(st_get_position(Z_AXIS)) / axis_steps_per_unit[Z_AXIS]);
+	SERIAL_PROTOCOLPGM(" E:");
+	SERIAL_PROTOCOL(float(st_get_position(E_AXIS)) / axis_steps_per_unit[E_AXIS]);
+
+	SERIAL_PROTOCOLLN("");
+}
+
 void gcode_M701()
 {
 #ifdef SNMM
@@ -4073,10 +4081,8 @@ void process_commands()
       card.openFile(strchr_pointer + 4,true);
       break;
     case 24: //M24 - Start SD print
-#ifdef TMC2130
 	  if (!card.paused)
 		failstats_reset_print();
-#endif //TMC2130
       card.startFileprint();
       starttime=millis();
 	  break;
@@ -4929,25 +4935,7 @@ Sigma_Exit:
       lcd_setstatus(strchr_pointer + 5);
       break;*/
     case 114: // M114
-      SERIAL_PROTOCOLPGM("X:");
-      SERIAL_PROTOCOL(current_position[X_AXIS]);
-      SERIAL_PROTOCOLPGM(" Y:");
-      SERIAL_PROTOCOL(current_position[Y_AXIS]);
-      SERIAL_PROTOCOLPGM(" Z:");
-      SERIAL_PROTOCOL(current_position[Z_AXIS]);
-      SERIAL_PROTOCOLPGM(" E:");
-      SERIAL_PROTOCOL(current_position[E_AXIS]);
-
-      SERIAL_PROTOCOLRPGM(MSG_COUNT_X);
-      SERIAL_PROTOCOL(float(st_get_position(X_AXIS))/axis_steps_per_unit[X_AXIS]);
-      SERIAL_PROTOCOLPGM(" Y:");
-      SERIAL_PROTOCOL(float(st_get_position(Y_AXIS))/axis_steps_per_unit[Y_AXIS]);
-      SERIAL_PROTOCOLPGM(" Z:");
-      SERIAL_PROTOCOL(float(st_get_position(Z_AXIS))/axis_steps_per_unit[Z_AXIS]);
-      SERIAL_PROTOCOLPGM(" E:");
-      SERIAL_PROTOCOL(float(st_get_position(E_AXIS))/axis_steps_per_unit[E_AXIS]);
-
-      SERIAL_PROTOCOLLN("");
+		gcode_M114();
       break;
     case 120: // M120
       enable_endstops(false) ;
@@ -5066,7 +5054,7 @@ Sigma_Exit:
           //reserved for setting filament diameter via UFID or filament measuring device
           break;
         }
-		calculate_volumetric_multipliers();
+		calculate_extruder_multipliers();
       }
       break;
     case 201: // M201
@@ -5234,6 +5222,7 @@ Sigma_Exit:
           extrudemultiply = tmp_code ;
         }
       }
+      calculate_extruder_multipliers();
     }
     break;
 
@@ -5472,69 +5461,6 @@ Sigma_Exit:
     }
     break;
 
-#ifdef FILAMENT_SENSOR
-case 404:  //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or display nominal filament width 
-    {
-    #if (FILWIDTH_PIN > -1) 
-    if(code_seen('N')) filament_width_nominal=code_value();
-    else{
-    SERIAL_PROTOCOLPGM("Filament dia (nominal mm):"); 
-    SERIAL_PROTOCOLLN(filament_width_nominal); 
-    }
-    #endif
-    }
-    break; 
-    
-    case 405:  //M405 Turn on filament sensor for control 
-    {
-    
-    
-    if(code_seen('D')) meas_delay_cm=code_value();
-       
-       if(meas_delay_cm> MAX_MEASUREMENT_DELAY)
-       	meas_delay_cm = MAX_MEASUREMENT_DELAY;
-    
-       if(delay_index2 == -1)  //initialize the ring buffer if it has not been done since startup
-    	   {
-    	   int temp_ratio = widthFil_to_size_ratio(); 
-       	    
-       	    for (delay_index1=0; delay_index1<(MAX_MEASUREMENT_DELAY+1); ++delay_index1 ){
-       	              measurement_delay[delay_index1]=temp_ratio-100;  //subtract 100 to scale within a signed byte
-       	        }
-       	    delay_index1=0;
-       	    delay_index2=0;	
-    	   }
-    
-    filament_sensor = true ; 
-    
-    //SERIAL_PROTOCOLPGM("Filament dia (measured mm):"); 
-    //SERIAL_PROTOCOL(filament_width_meas); 
-    //SERIAL_PROTOCOLPGM("Extrusion ratio(%):"); 
-    //SERIAL_PROTOCOL(extrudemultiply); 
-    } 
-    break; 
-    
-    case 406:  //M406 Turn off filament sensor for control 
-    {      
-    filament_sensor = false ; 
-    } 
-    break; 
-  
-    case 407:   //M407 Display measured filament diameter 
-    { 
-     
-    
-    
-    SERIAL_PROTOCOLPGM("Filament dia (measured mm):"); 
-    SERIAL_PROTOCOLLN(filament_width_meas);   
-    } 
-    break; 
-    #endif
-    
-
-
-
-
     case 500: // M500 Store settings in EEPROM
     {
         Config_StoreSettings(EEPROM_OFFSET);
@@ -6523,14 +6449,65 @@ void ClearToSend()
         SERIAL_PROTOCOLLNRPGM(MSG_OK);
 }
 
+void update_currents() {
+	float current_high[3] = DEFAULT_PWM_MOTOR_CURRENT_LOUD;
+	float current_low[3] = DEFAULT_PWM_MOTOR_CURRENT;
+	float tmp_motor[3];
+	
+	//SERIAL_ECHOLNPGM("Currents updated: ");
+
+	if (destination[Z_AXIS] < Z_SILENT) {
+		//SERIAL_ECHOLNPGM("LOW");
+		for (uint8_t i = 0; i < 3; i++) {
+			digipot_current(i, current_low[i]);		
+			/*MYSERIAL.print(int(i));
+			SERIAL_ECHOPGM(": ");
+			MYSERIAL.println(current_low[i]);*/
+		}		
+	}
+	else if (destination[Z_AXIS] > Z_HIGH_POWER) {
+		//SERIAL_ECHOLNPGM("HIGH");
+		for (uint8_t i = 0; i < 3; i++) {
+			digipot_current(i, current_high[i]);
+			/*MYSERIAL.print(int(i));
+			SERIAL_ECHOPGM(": ");
+			MYSERIAL.println(current_high[i]);*/
+		}		
+	}
+	else {
+		for (uint8_t i = 0; i < 3; i++) {
+			float q = current_low[i] - Z_SILENT*((current_high[i] - current_low[i]) / (Z_HIGH_POWER - Z_SILENT));
+			tmp_motor[i] = ((current_high[i] - current_low[i]) / (Z_HIGH_POWER - Z_SILENT))*destination[Z_AXIS] + q;
+			digipot_current(i, tmp_motor[i]);			
+			/*MYSERIAL.print(int(i));
+			SERIAL_ECHOPGM(": ");
+			MYSERIAL.println(tmp_motor[i]);*/
+		}
+	}
+}
+
 void get_coordinates()
 {
   bool seen[4]={false,false,false,false};
   for(int8_t i=0; i < NUM_AXIS; i++) {
     if(code_seen(axis_codes[i]))
     {
-      destination[i] = (float)code_value() + (axis_relative_modes[i] || relative_mode)*current_position[i];
+      bool relative = axis_relative_modes[i] || relative_mode;
+      destination[i] = (float)code_value();
+      if (i == E_AXIS) {
+        float emult = extruder_multiplier[active_extruder];
+        if (emult != 1.) {
+          if (! relative) {
+            destination[i] -= current_position[i];
+            relative = true;
+          }
+          destination[i] *= emult;
+        }
+      }
+      if (relative)
+        destination[i] += current_position[i];
       seen[i]=true;
+	  if (i == Z_AXIS && SilentModeMenu == 2) update_currents();
     }
     else destination[i] = current_position[i]; //Are these else lines really needed?
   }
@@ -7061,27 +7038,23 @@ void save_statistics(unsigned long _total_filament_used, unsigned long _total_pr
 
 }
 
-float calculate_volumetric_multiplier(float diameter) {
-	float area = .0;
-	float radius = .0;
-
-	radius = diameter * .5;
-	if (! volumetric_enabled || radius == 0) {
-		area = 1;
-	}
-	else {
-		area = M_PI * pow(radius, 2);
-	}
-
-	return 1.0 / area;
+float calculate_extruder_multiplier(float diameter) {
+  float out = 1.f;
+  if (volumetric_enabled && diameter > 0.f) {
+    float area = M_PI * diameter * diameter * 0.25;
+    out = 1.f / area;
+  }
+  if (extrudemultiply != 100)
+    out *= float(extrudemultiply) * 0.01f;
+  return out;
 }
 
-void calculate_volumetric_multipliers() {
-	volumetric_multiplier[0] = calculate_volumetric_multiplier(filament_size[0]);
+void calculate_extruder_multipliers() {
+	extruder_multiplier[0] = calculate_extruder_multiplier(filament_size[0]);
 #if EXTRUDERS > 1
-	volumetric_multiplier[1] = calculate_volumetric_multiplier(filament_size[1]);
+	extruder_multiplier[1] = calculate_extruder_multiplier(filament_size[1]);
 #if EXTRUDERS > 2
-	volumetric_multiplier[2] = calculate_volumetric_multiplier(filament_size[2]);
+	extruder_multiplier[2] = calculate_extruder_multiplier(filament_size[2]);
 #endif
 #endif
 }

+ 7 - 2
Firmware/language_all.cpp

@@ -60,6 +60,11 @@ const char * const MSG_AUTO_HOME_LANG_TABLE[1] PROGMEM = {
 	MSG_AUTO_HOME_EN
 };
 
+const char MSG_AUTO_MODE_ON_EN[] PROGMEM = "Mode [auto power]";
+const char * const MSG_AUTO_MODE_ON_LANG_TABLE[1] PROGMEM = {
+	MSG_AUTO_MODE_ON_EN
+};
+
 const char MSG_A_RETRACT_EN[] PROGMEM = "A-retract";
 const char * const MSG_A_RETRACT_LANG_TABLE[1] PROGMEM = {
 	MSG_A_RETRACT_EN
@@ -1980,14 +1985,14 @@ const char * const MSG_SHOW_END_STOPS_LANG_TABLE[LANG_NUM] PROGMEM = {
 	MSG_SHOW_END_STOPS_CZ
 };
 
-const char MSG_SILENT_MODE_OFF_EN[] PROGMEM = "Mode     [Normal]";
+const char MSG_SILENT_MODE_OFF_EN[] PROGMEM = "Mode [high power]";
 const char MSG_SILENT_MODE_OFF_CZ[] PROGMEM = "Mod      [Normal]";
 const char * const MSG_SILENT_MODE_OFF_LANG_TABLE[LANG_NUM] PROGMEM = {
 	MSG_SILENT_MODE_OFF_EN,
 	MSG_SILENT_MODE_OFF_CZ
 };
 
-const char MSG_SILENT_MODE_ON_EN[] PROGMEM = "Mode    [Stealth]";
+const char MSG_SILENT_MODE_ON_EN[] PROGMEM = "Mode     [silent]";
 const char MSG_SILENT_MODE_ON_CZ[] PROGMEM = "Mod     [Stealth]";
 const char * const MSG_SILENT_MODE_ON_LANG_TABLE[LANG_NUM] PROGMEM = {
 	MSG_SILENT_MODE_ON_EN,

+ 2 - 0
Firmware/language_all.h

@@ -40,6 +40,8 @@ extern const char* const MSG_AUTOLOAD_FILAMENT_LANG_TABLE[LANG_NUM];
 #define MSG_AUTOLOAD_FILAMENT LANG_TABLE_SELECT(MSG_AUTOLOAD_FILAMENT_LANG_TABLE)
 extern const char* const MSG_AUTO_HOME_LANG_TABLE[1];
 #define MSG_AUTO_HOME LANG_TABLE_SELECT_EXPLICIT(MSG_AUTO_HOME_LANG_TABLE, 0)
+extern const char* const MSG_AUTO_MODE_ON_LANG_TABLE[1];
+#define MSG_AUTO_MODE_ON LANG_TABLE_SELECT_EXPLICIT(MSG_AUTO_MODE_ON_LANG_TABLE, 0)
 extern const char* const MSG_A_RETRACT_LANG_TABLE[1];
 #define MSG_A_RETRACT LANG_TABLE_SELECT_EXPLICIT(MSG_A_RETRACT_LANG_TABLE, 0)
 extern const char* const MSG_BABYSTEPPING_X_LANG_TABLE[1];

+ 3 - 2
Firmware/language_en.h

@@ -102,8 +102,9 @@
 #define(length=20) MSG_CHANGING_FILAMENT	"Changing filament!"
 
 
-#define MSG_SILENT_MODE_ON					"Mode    [Stealth]"
-#define MSG_SILENT_MODE_OFF					"Mode     [Normal]" 
+#define MSG_SILENT_MODE_ON					"Mode     [silent]"
+#define MSG_SILENT_MODE_OFF					"Mode [high power]" 
+#define MSG_AUTO_MODE_ON					"Mode [auto power]"
 #define(length=20) MSG_REBOOT				"Reboot the printer"
 #define(length=20) MSG_TAKE_EFFECT			" for take effect"											
 

+ 439 - 169
Firmware/mesh_bed_calibration.cpp

@@ -104,10 +104,17 @@ const float bed_ref_points[] PROGMEM = {
 
 static inline float sqr(float x) { return x * x; }
 
+#ifdef HEATBED_V2
+static inline bool point_on_1st_row(const uint8_t i)
+{
+	return false;
+}
+#else //HEATBED_V2
 static inline bool point_on_1st_row(const uint8_t i)
 {
-	return (i < 2);
+	return (i < 3);
 }
+#endif //HEATBED_V2
 
 // Weight of a point coordinate in a least squares optimization.
 // The first row of points may not be fully reachable
@@ -904,22 +911,29 @@ error:
 #define FIND_BED_INDUCTION_SENSOR_POINT_X_RADIUS (8.f)
 #define FIND_BED_INDUCTION_SENSOR_POINT_Y_RADIUS (4.f)
 #define FIND_BED_INDUCTION_SENSOR_POINT_XY_STEP  (1.f)
+#ifdef HEATBED_V2
+#define FIND_BED_INDUCTION_SENSOR_POINT_Z_STEP   (2.f)
+#define FIND_BED_INDUCTION_SENSOR_POINT_MAX_Z_ERROR  (0.03f)
+#else //HEATBED_V2
 #define FIND_BED_INDUCTION_SENSOR_POINT_Z_STEP   (0.2f)
+#endif //HEATBED_V2
+
+#ifdef HEATBED_V2
 inline bool find_bed_induction_sensor_point_xy(int verbosity_level)
 {
 	#ifdef SUPPORT_VERBOSITY
-	if(verbosity_level >= 10) MYSERIAL.println("find bed induction sensor point xy");
+	if (verbosity_level >= 10) MYSERIAL.println("find bed induction sensor point xy");
 	#endif // SUPPORT_VERBOSITY
 	float feedrate = homing_feedrate[X_AXIS] / 60.f;
-    bool found = false;
-
-    {
-        float x0 = current_position[X_AXIS] - FIND_BED_INDUCTION_SENSOR_POINT_X_RADIUS;
-        float x1 = current_position[X_AXIS] + FIND_BED_INDUCTION_SENSOR_POINT_X_RADIUS;
-        float y0 = current_position[Y_AXIS] - FIND_BED_INDUCTION_SENSOR_POINT_Y_RADIUS;
-        float y1 = current_position[Y_AXIS] + FIND_BED_INDUCTION_SENSOR_POINT_Y_RADIUS;
-        uint8_t nsteps_y;
-        uint8_t i;
+	bool found = false;
+
+	{
+		float x0 = current_position[X_AXIS] - FIND_BED_INDUCTION_SENSOR_POINT_X_RADIUS;
+		float x1 = current_position[X_AXIS] + FIND_BED_INDUCTION_SENSOR_POINT_X_RADIUS;
+		float y0 = current_position[Y_AXIS] - FIND_BED_INDUCTION_SENSOR_POINT_Y_RADIUS;
+		float y1 = current_position[Y_AXIS] + FIND_BED_INDUCTION_SENSOR_POINT_Y_RADIUS;
+		uint8_t nsteps_y;
+		uint8_t i;
 		if (x0 < X_MIN_POS) {
 			x0 = X_MIN_POS;
 			#ifdef SUPPORT_VERBOSITY
@@ -944,163 +958,412 @@ inline bool find_bed_induction_sensor_point_xy(int verbosity_level)
 			if (verbosity_level >= 20) SERIAL_ECHOLNPGM("Y searching radius higher than X_MAX. Clamping was done.");
 			#endif // SUPPORT_VERBOSITY
 		}
-        nsteps_y = int(ceil((y1 - y0) / FIND_BED_INDUCTION_SENSOR_POINT_XY_STEP));
+		nsteps_y = int(ceil((y1 - y0) / FIND_BED_INDUCTION_SENSOR_POINT_XY_STEP));
+
+		enable_endstops(false);
+		bool  dir_positive = true;
+		float z_error = 2 * FIND_BED_INDUCTION_SENSOR_POINT_Z_STEP;
+		float find_bed_induction_sensor_point_z_step = FIND_BED_INDUCTION_SENSOR_POINT_Z_STEP;
+		float initial_z_position = current_position[Z_AXIS];
+
+		//        go_xyz(current_position[X_AXIS], current_position[Y_AXIS], MESH_HOME_Z_SEARCH, homing_feedrate[Z_AXIS]/60);
+		go_xyz(x0, y0, current_position[Z_AXIS], feedrate);
+		// Continously lower the Z axis.
+		endstops_hit_on_purpose();
+		enable_z_endstop(true);
+		bool direction = false;
+		while (current_position[Z_AXIS] > -10.f && z_error > FIND_BED_INDUCTION_SENSOR_POINT_MAX_Z_ERROR) {
+			// Do nsteps_y zig-zag movements.
+
+			SERIAL_ECHOPGM("z_error: ");
+			MYSERIAL.println(z_error);
+			current_position[Y_AXIS] = direction ? y1 : y0;
+			initial_z_position = current_position[Z_AXIS];
+			for (i = 0; i < (nsteps_y - 1); (direction == false) ? (current_position[Y_AXIS] += (y1 - y0) / float(nsteps_y - 1)) : (current_position[Y_AXIS] -= (y1 - y0) / float(nsteps_y - 1)), ++i) {
+				// Run with a slightly decreasing Z axis, zig-zag movement. Stop at the Z end-stop.
+				current_position[Z_AXIS] -= find_bed_induction_sensor_point_z_step / float(nsteps_y - 1);
+				go_xyz(dir_positive ? x1 : x0, current_position[Y_AXIS], current_position[Z_AXIS], feedrate);
+				dir_positive = !dir_positive;
+				if (endstop_z_hit_on_purpose()) {
+					update_current_position_xyz();
+					z_error = initial_z_position - current_position[Z_AXIS] + find_bed_induction_sensor_point_z_step;
+					if (z_error > FIND_BED_INDUCTION_SENSOR_POINT_MAX_Z_ERROR) {
+						find_bed_induction_sensor_point_z_step = z_error / 2;
+						current_position[Z_AXIS] += z_error;
+						enable_z_endstop(false);
+						(direction == false) ? go_xyz(x0, y0, current_position[Z_AXIS], feedrate) : go_xyz(x0, y1, current_position[Z_AXIS], feedrate);
+						enable_z_endstop(true);
+					}
+					goto endloop;
+				}
+			}
+			for (i = 0; i < (nsteps_y - 1); (direction == false) ? (current_position[Y_AXIS] -= (y1 - y0) / float(nsteps_y - 1)) : (current_position[Y_AXIS] += (y1 - y0) / float(nsteps_y - 1)), ++i) {
+				// Run with a slightly decreasing Z axis, zig-zag movement. Stop at the Z end-stop.
+				current_position[Z_AXIS] -= find_bed_induction_sensor_point_z_step / float(nsteps_y - 1);
+				go_xyz(dir_positive ? x1 : x0, current_position[Y_AXIS], current_position[Z_AXIS], feedrate);
+				dir_positive = !dir_positive;
+				if (endstop_z_hit_on_purpose()) {
+					update_current_position_xyz();
+					z_error = initial_z_position - current_position[Z_AXIS];
+					if (z_error > FIND_BED_INDUCTION_SENSOR_POINT_MAX_Z_ERROR) {
+						find_bed_induction_sensor_point_z_step = z_error / 2;
+						current_position[Z_AXIS] += z_error;
+						enable_z_endstop(false);
+						direction = !direction;
+						(direction == false) ? go_xyz(x0, y0, current_position[Z_AXIS], feedrate) : go_xyz(x0, y1, current_position[Z_AXIS], feedrate);
+						enable_z_endstop(true);
+					}
+					goto endloop;
+				}
+			}
+		endloop:;
+		}
+		#ifdef SUPPORT_VERBOSITY
+		if (verbosity_level >= 20) {
+			SERIAL_ECHO("First hit");
+			SERIAL_ECHO("- X: ");
+			MYSERIAL.print(current_position[X_AXIS]);
+			SERIAL_ECHO("; Y: ");
+			MYSERIAL.print(current_position[Y_AXIS]);
+			SERIAL_ECHO("; Z: ");
+			MYSERIAL.println(current_position[Z_AXIS]);
+		}
+		#endif //SUPPORT_VERBOSITY
+		//lcd_show_fullscreen_message_and_wait_P(PSTR("First hit"));
+		//lcd_update_enable(true);
 
-        enable_endstops(false);
-        bool  dir_positive = true;
+		float init_x_position = current_position[X_AXIS];
+		float init_y_position = current_position[Y_AXIS];
 
-//        go_xyz(current_position[X_AXIS], current_position[Y_AXIS], MESH_HOME_Z_SEARCH, homing_feedrate[Z_AXIS]/60);
-        go_xyz(x0, y0, current_position[Z_AXIS], feedrate);
-        // Continously lower the Z axis.
-        endstops_hit_on_purpose();
-        enable_z_endstop(true);
-        while (current_position[Z_AXIS] > -10.f) {
-            // Do nsteps_y zig-zag movements.
-            current_position[Y_AXIS] = y0;
-            for (i = 0; i < (nsteps_y - 1); current_position[Y_AXIS] += (y1 - y0) / float(nsteps_y - 1), ++ i) {
-                // Run with a slightly decreasing Z axis, zig-zag movement. Stop at the Z end-stop.
-                current_position[Z_AXIS] -= FIND_BED_INDUCTION_SENSOR_POINT_Z_STEP / float(nsteps_y);
-                go_xyz(dir_positive ? x1 : x0, current_position[Y_AXIS], current_position[Z_AXIS], feedrate);
-                dir_positive = ! dir_positive;
-                if (endstop_z_hit_on_purpose())
-                    goto endloop;
-            }
-            for (i = 0; i < (nsteps_y - 1); current_position[Y_AXIS] -= (y1 - y0) / float(nsteps_y - 1), ++ i) {
-                // Run with a slightly decreasing Z axis, zig-zag movement. Stop at the Z end-stop.
-                current_position[Z_AXIS] -= FIND_BED_INDUCTION_SENSOR_POINT_Z_STEP / float(nsteps_y);
-                go_xyz(dir_positive ? x1 : x0, current_position[Y_AXIS], current_position[Z_AXIS], feedrate);
-                dir_positive = ! dir_positive;
-                if (endstop_z_hit_on_purpose())
-                    goto endloop;
-            }
-        }
-        endloop:
-//        SERIAL_ECHOLN("First hit");
+		// we have to let the planner know where we are right now as it is not where we said to go.
+		update_current_position_xyz();
+		enable_z_endstop(false);
+		
+		for (int8_t iter = 0; iter < 2; ++iter) {
+			/*SERIAL_ECHOPGM("iter: ");
+			MYSERIAL.println(iter);
+			SERIAL_ECHOPGM("1 - current_position[Z_AXIS]: ");
+			MYSERIAL.println(current_position[Z_AXIS]);*/
+
+			// Slightly lower the Z axis to get a reliable trigger.
+			current_position[Z_AXIS] -= 0.1f;
+			go_xyz(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], homing_feedrate[Z_AXIS] / (60 * 10));
+
+			SERIAL_ECHOPGM("2 - current_position[Z_AXIS]: ");
+			MYSERIAL.println(current_position[Z_AXIS]);
+			// Do nsteps_y zig-zag movements.
+			float a, b;
+			float avg[2] = { 0,0 };
+			invert_z_endstop(true);
+			for (int iteration = 0; iteration < 8; iteration++) {
+
+				found = false;				
+				enable_z_endstop(true);
+				go_xy(init_x_position + 16.0f, current_position[Y_AXIS], feedrate / 5);
+				update_current_position_xyz();
+				if (!endstop_z_hit_on_purpose()) {
+					//                SERIAL_ECHOLN("Search X span 0 - not found");
+					continue;
+				}
+				//            SERIAL_ECHOLN("Search X span 0 - found");
+				a = current_position[X_AXIS];
+				enable_z_endstop(false);
+				go_xy(init_x_position, current_position[Y_AXIS], feedrate / 5);
+				enable_z_endstop(true);
+				go_xy(init_x_position - 16.0f, current_position[Y_AXIS], feedrate / 5);
+				update_current_position_xyz();
+				if (!endstop_z_hit_on_purpose()) {
+					//                SERIAL_ECHOLN("Search X span 1 - not found");
+					continue;
+				}
+				//            SERIAL_ECHOLN("Search X span 1 - found");
+				b = current_position[X_AXIS];
+				// Go to the center.
+				enable_z_endstop(false);
+				current_position[X_AXIS] = 0.5f * (a + b);
+				go_xy(current_position[X_AXIS], init_y_position, feedrate / 5);
+				found = true;
+				
+				// Search in the Y direction along a cross.
+				found = false;
+				enable_z_endstop(true);
+				go_xy(current_position[X_AXIS], init_y_position + 16.0f, feedrate / 5);
+				update_current_position_xyz();
+				if (!endstop_z_hit_on_purpose()) {
+					//                SERIAL_ECHOLN("Search Y2 span 0 - not found");
+					continue;
+				}
+				//            SERIAL_ECHOLN("Search Y2 span 0 - found");
+				a = current_position[Y_AXIS];
+				enable_z_endstop(false);
+				go_xy(current_position[X_AXIS], init_y_position, feedrate / 5);
+				enable_z_endstop(true);
+				go_xy(current_position[X_AXIS], init_y_position - 16.0f, feedrate / 5);
+				update_current_position_xyz();
+				if (!endstop_z_hit_on_purpose()) {
+					//                SERIAL_ECHOLN("Search Y2 span 1 - not found");
+					continue;
+				}
+				//            SERIAL_ECHOLN("Search Y2 span 1 - found");
+				b = current_position[Y_AXIS];
+				// Go to the center.
+				enable_z_endstop(false);
+				current_position[Y_AXIS] = 0.5f * (a + b);
+				go_xy(current_position[X_AXIS], current_position[Y_AXIS], feedrate / 5);
 
-        // we have to let the planner know where we are right now as it is not where we said to go.
-        update_current_position_xyz();
+				#ifdef SUPPORT_VERBOSITY
+				if (verbosity_level >= 20) {
+					SERIAL_ECHOPGM("ITERATION: ");
+					MYSERIAL.println(iteration);
+					SERIAL_ECHOPGM("CURRENT POSITION X: ");
+					MYSERIAL.println(current_position[X_AXIS]);
+					SERIAL_ECHOPGM("CURRENT POSITION Y: ");
+					MYSERIAL.println(current_position[Y_AXIS]);
+				}
+				#endif //SUPPORT_VERBOSITY
 
-        // Search in this plane for the first hit. Zig-zag first in X, then in Y axis.
-        for (int8_t iter = 0; iter < 3; ++ iter) {
-            if (iter > 0) {
-                // Slightly lower the Z axis to get a reliable trigger.
-                current_position[Z_AXIS] -= 0.02f;
-                go_xyz(current_position[X_AXIS], current_position[Y_AXIS], MESH_HOME_Z_SEARCH, homing_feedrate[Z_AXIS]/60);
-            }
+				if (iteration > 0) {
+					// Average the last 7 measurements.
+					avg[X_AXIS] += current_position[X_AXIS];
+					avg[Y_AXIS] += current_position[Y_AXIS];
+				}
 
-            // Do nsteps_y zig-zag movements.
-            float a, b;
-            enable_endstops(false);
-            enable_z_endstop(false);
-            current_position[Y_AXIS] = y0;
-            go_xy(x0, current_position[Y_AXIS], feedrate);
-            enable_z_endstop(true);
-            found = false;
-            for (i = 0, dir_positive = true; i < (nsteps_y - 1); current_position[Y_AXIS] += (y1 - y0) / float(nsteps_y - 1), ++ i, dir_positive = ! dir_positive) {
-                go_xy(dir_positive ? x1 : x0, current_position[Y_AXIS], feedrate);
-                if (endstop_z_hit_on_purpose()) {
-                    found = true;
-                    break;
-                }
-            }
-            update_current_position_xyz();
-            if (! found) {
-//                SERIAL_ECHOLN("Search in Y - not found");
-                continue;
-            }
-//            SERIAL_ECHOLN("Search in Y - found");
-            a = current_position[Y_AXIS];
+				init_x_position = current_position[X_AXIS];
+				init_y_position = current_position[Y_AXIS];
 
-            enable_z_endstop(false);
-            current_position[Y_AXIS] = y1;
-            go_xy(x0, current_position[Y_AXIS], feedrate);
-            enable_z_endstop(true);
-            found = false;
-            for (i = 0, dir_positive = true; i < (nsteps_y - 1); current_position[Y_AXIS] -= (y1 - y0) / float(nsteps_y - 1), ++ i, dir_positive = ! dir_positive) {
-                go_xy(dir_positive ? x1 : x0, current_position[Y_AXIS], feedrate);
-                if (endstop_z_hit_on_purpose()) {
-                    found = true;
-                    break;
-                }
-            }
-            update_current_position_xyz();
-            if (! found) {
-//                SERIAL_ECHOLN("Search in Y2 - not found");
-                continue;
-            }
-//            SERIAL_ECHOLN("Search in Y2 - found");
-            b = current_position[Y_AXIS];
-            current_position[Y_AXIS] = 0.5f * (a + b);
+				found = true;
 
-            // Search in the X direction along a cross.
-            found = false;
-            enable_z_endstop(false);
-            go_xy(x0, current_position[Y_AXIS], feedrate);
-            enable_z_endstop(true);
-            go_xy(x1, current_position[Y_AXIS], feedrate);
-            update_current_position_xyz();
-            if (! endstop_z_hit_on_purpose()) {
-//                SERIAL_ECHOLN("Search X span 0 - not found");
-                continue;
-            }
-//            SERIAL_ECHOLN("Search X span 0 - found");
-            a = current_position[X_AXIS];
-            enable_z_endstop(false);
-            go_xy(x1, current_position[Y_AXIS], feedrate);
-            enable_z_endstop(true);
-            go_xy(x0, current_position[Y_AXIS], feedrate);
-            update_current_position_xyz();
-            if (! endstop_z_hit_on_purpose()) {
-//                SERIAL_ECHOLN("Search X span 1 - not found");
-                continue;
-            }
-//            SERIAL_ECHOLN("Search X span 1 - found");
-            b = current_position[X_AXIS];
-            // Go to the center.
-            enable_z_endstop(false);
-            current_position[X_AXIS] = 0.5f * (a + b);
-            go_xy(current_position[X_AXIS], current_position[Y_AXIS], feedrate);
-            found = true;
+			}
+			invert_z_endstop(false);
+			avg[X_AXIS] *= (1.f / 7.f);
+			avg[Y_AXIS] *= (1.f / 7.f);
+
+			current_position[X_AXIS] = avg[X_AXIS];
+			current_position[Y_AXIS] = avg[Y_AXIS];
+			#ifdef SUPPORT_VERBOSITY
+			if (verbosity_level >= 20) {
+				SERIAL_ECHOPGM("AVG CURRENT POSITION X: ");
+				MYSERIAL.println(current_position[X_AXIS]);
+				SERIAL_ECHOPGM("AVG CURRENT POSITION Y: ");
+				MYSERIAL.println(current_position[Y_AXIS]);
+			}
+			#endif // SUPPORT_VERBOSITY
+			go_xy(current_position[X_AXIS], current_position[Y_AXIS], feedrate);
+			#ifdef SUPPORT_VERBOSITY
+			if (verbosity_level >= 20) {
+				lcd_show_fullscreen_message_and_wait_P(PSTR("Final position"));
+				lcd_update_enable(true);
+			}
+			#endif //SUPPORT_VERBOSITY
+
+			break;
+		}
+	}
+	
+	enable_z_endstop(false);
+	invert_z_endstop(false);
+	return found;
+
+}
+#else //HEATBED_V2
+inline bool find_bed_induction_sensor_point_xy(int verbosity_level)
+{
+	#ifdef SUPPORT_VERBOSITY
+	if (verbosity_level >= 10) MYSERIAL.println("find bed induction sensor point xy");
+	#endif // SUPPORT_VERBOSITY
+	float feedrate = homing_feedrate[X_AXIS] / 60.f;
+	bool found = false;
+
+	{
+		float x0 = current_position[X_AXIS] - FIND_BED_INDUCTION_SENSOR_POINT_X_RADIUS;
+		float x1 = current_position[X_AXIS] + FIND_BED_INDUCTION_SENSOR_POINT_X_RADIUS;
+		float y0 = current_position[Y_AXIS] - FIND_BED_INDUCTION_SENSOR_POINT_Y_RADIUS;
+		float y1 = current_position[Y_AXIS] + FIND_BED_INDUCTION_SENSOR_POINT_Y_RADIUS;
+		uint8_t nsteps_y;
+		uint8_t i;
+		if (x0 < X_MIN_POS) {
+			x0 = X_MIN_POS;
+			#ifdef SUPPORT_VERBOSITY
+			if (verbosity_level >= 20) SERIAL_ECHOLNPGM("X searching radius lower than X_MIN. Clamping was done.");
+			#endif // SUPPORT_VERBOSITY
+		}
+		if (x1 > X_MAX_POS) {
+			x1 = X_MAX_POS;
+			#ifdef SUPPORT_VERBOSITY
+			if (verbosity_level >= 20) SERIAL_ECHOLNPGM("X searching radius higher than X_MAX. Clamping was done.");
+			#endif // SUPPORT_VERBOSITY
+		}
+		if (y0 < Y_MIN_POS_FOR_BED_CALIBRATION) {
+			y0 = Y_MIN_POS_FOR_BED_CALIBRATION;
+			#ifdef SUPPORT_VERBOSITY
+			if (verbosity_level >= 20) SERIAL_ECHOLNPGM("Y searching radius lower than Y_MIN. Clamping was done.");
+			#endif // SUPPORT_VERBOSITY
+		}
+		if (y1 > Y_MAX_POS) {
+			y1 = Y_MAX_POS;
+			#ifdef SUPPORT_VERBOSITY
+			if (verbosity_level >= 20) SERIAL_ECHOLNPGM("Y searching radius higher than X_MAX. Clamping was done.");
+			#endif // SUPPORT_VERBOSITY
+		}
+		nsteps_y = int(ceil((y1 - y0) / FIND_BED_INDUCTION_SENSOR_POINT_XY_STEP));
+
+		enable_endstops(false);
+		bool  dir_positive = true;
+
+		//        go_xyz(current_position[X_AXIS], current_position[Y_AXIS], MESH_HOME_Z_SEARCH, homing_feedrate[Z_AXIS]/60);
+		go_xyz(x0, y0, current_position[Z_AXIS], feedrate);
+		// Continously lower the Z axis.
+		endstops_hit_on_purpose();
+		enable_z_endstop(true);
+		while (current_position[Z_AXIS] > -10.f) {
+			// Do nsteps_y zig-zag movements.
+			current_position[Y_AXIS] = y0;
+			for (i = 0; i < nsteps_y; current_position[Y_AXIS] += (y1 - y0) / float(nsteps_y - 1), ++i) {
+				// Run with a slightly decreasing Z axis, zig-zag movement. Stop at the Z end-stop.
+				current_position[Z_AXIS] -= FIND_BED_INDUCTION_SENSOR_POINT_Z_STEP / float(nsteps_y);
+				go_xyz(dir_positive ? x1 : x0, current_position[Y_AXIS], current_position[Z_AXIS], feedrate);
+				dir_positive = !dir_positive;
+				if (endstop_z_hit_on_purpose())
+					goto endloop;
+			}
+			for (i = 0; i < nsteps_y; current_position[Y_AXIS] -= (y1 - y0) / float(nsteps_y - 1), ++i) {
+				// Run with a slightly decreasing Z axis, zig-zag movement. Stop at the Z end-stop.
+				current_position[Z_AXIS] -= FIND_BED_INDUCTION_SENSOR_POINT_Z_STEP / float(nsteps_y);
+				go_xyz(dir_positive ? x1 : x0, current_position[Y_AXIS], current_position[Z_AXIS], feedrate);
+				dir_positive = !dir_positive;
+				if (endstop_z_hit_on_purpose())
+					goto endloop;
+			}
+		}
+	endloop:
+		//        SERIAL_ECHOLN("First hit");
+
+		// we have to let the planner know where we are right now as it is not where we said to go.
+		update_current_position_xyz();
+
+		// Search in this plane for the first hit. Zig-zag first in X, then in Y axis.
+		for (int8_t iter = 0; iter < 3; ++iter) {
+			if (iter > 0) {
+				// Slightly lower the Z axis to get a reliable trigger.
+				current_position[Z_AXIS] -= 0.02f;
+				go_xyz(current_position[X_AXIS], current_position[Y_AXIS], MESH_HOME_Z_SEARCH, homing_feedrate[Z_AXIS] / 60);
+			}
+
+			// Do nsteps_y zig-zag movements.
+			float a, b;
+			enable_endstops(false);
+			enable_z_endstop(false);
+			current_position[Y_AXIS] = y0;
+			go_xy(x0, current_position[Y_AXIS], feedrate);
+			enable_z_endstop(true);
+			found = false;
+			for (i = 0, dir_positive = true; i < nsteps_y; current_position[Y_AXIS] += (y1 - y0) / float(nsteps_y - 1), ++i, dir_positive = !dir_positive) {
+				go_xy(dir_positive ? x1 : x0, current_position[Y_AXIS], feedrate);
+				if (endstop_z_hit_on_purpose()) {
+					found = true;
+					break;
+				}
+			}
+			update_current_position_xyz();
+			if (!found) {
+				//                SERIAL_ECHOLN("Search in Y - not found");
+				continue;
+			}
+			//            SERIAL_ECHOLN("Search in Y - found");
+			a = current_position[Y_AXIS];
+
+			enable_z_endstop(false);
+			current_position[Y_AXIS] = y1;
+			go_xy(x0, current_position[Y_AXIS], feedrate);
+			enable_z_endstop(true);
+			found = false;
+			for (i = 0, dir_positive = true; i < nsteps_y; current_position[Y_AXIS] -= (y1 - y0) / float(nsteps_y - 1), ++i, dir_positive = !dir_positive) {
+				go_xy(dir_positive ? x1 : x0, current_position[Y_AXIS], feedrate);
+				if (endstop_z_hit_on_purpose()) {
+					found = true;
+					break;
+				}
+			}
+			update_current_position_xyz();
+			if (!found) {
+				//                SERIAL_ECHOLN("Search in Y2 - not found");
+				continue;
+			}
+			//            SERIAL_ECHOLN("Search in Y2 - found");
+			b = current_position[Y_AXIS];
+			current_position[Y_AXIS] = 0.5f * (a + b);
+
+			// Search in the X direction along a cross.
+			found = false;
+			enable_z_endstop(false);
+			go_xy(x0, current_position[Y_AXIS], feedrate);
+			enable_z_endstop(true);
+			go_xy(x1, current_position[Y_AXIS], feedrate);
+			update_current_position_xyz();
+			if (!endstop_z_hit_on_purpose()) {
+				//                SERIAL_ECHOLN("Search X span 0 - not found");
+				continue;
+			}
+			//            SERIAL_ECHOLN("Search X span 0 - found");
+			a = current_position[X_AXIS];
+			enable_z_endstop(false);
+			go_xy(x1, current_position[Y_AXIS], feedrate);
+			enable_z_endstop(true);
+			go_xy(x0, current_position[Y_AXIS], feedrate);
+			update_current_position_xyz();
+			if (!endstop_z_hit_on_purpose()) {
+				//                SERIAL_ECHOLN("Search X span 1 - not found");
+				continue;
+			}
+			//            SERIAL_ECHOLN("Search X span 1 - found");
+			b = current_position[X_AXIS];
+			// Go to the center.
+			enable_z_endstop(false);
+			current_position[X_AXIS] = 0.5f * (a + b);
+			go_xy(current_position[X_AXIS], current_position[Y_AXIS], feedrate);
+			found = true;
 
 #if 1
-            // Search in the Y direction along a cross.
-            found = false;
-            enable_z_endstop(false);
-            go_xy(current_position[X_AXIS], y0, feedrate);
-            enable_z_endstop(true);
-            go_xy(current_position[X_AXIS], y1, feedrate);
-            update_current_position_xyz();
-            if (! endstop_z_hit_on_purpose()) {
-//                SERIAL_ECHOLN("Search Y2 span 0 - not found");
-                continue;
-            }
-//            SERIAL_ECHOLN("Search Y2 span 0 - found");
-            a = current_position[Y_AXIS];
-            enable_z_endstop(false);
-            go_xy(current_position[X_AXIS], y1, feedrate);
-            enable_z_endstop(true);
-            go_xy(current_position[X_AXIS], y0, feedrate);
-            update_current_position_xyz();
-            if (! endstop_z_hit_on_purpose()) {
-//                SERIAL_ECHOLN("Search Y2 span 1 - not found");
-                continue;
-            }
-//            SERIAL_ECHOLN("Search Y2 span 1 - found");
-            b = current_position[Y_AXIS];
-            // Go to the center.
-            enable_z_endstop(false);
-            current_position[Y_AXIS] = 0.5f * (a + b);
-            go_xy(current_position[X_AXIS], current_position[Y_AXIS], feedrate);
-            found = true;
+			// Search in the Y direction along a cross.
+			found = false;
+			enable_z_endstop(false);
+			go_xy(current_position[X_AXIS], y0, feedrate);
+			enable_z_endstop(true);
+			go_xy(current_position[X_AXIS], y1, feedrate);
+			update_current_position_xyz();
+			if (!endstop_z_hit_on_purpose()) {
+				//                SERIAL_ECHOLN("Search Y2 span 0 - not found");
+				continue;
+			}
+			//            SERIAL_ECHOLN("Search Y2 span 0 - found");
+			a = current_position[Y_AXIS];
+			enable_z_endstop(false);
+			go_xy(current_position[X_AXIS], y1, feedrate);
+			enable_z_endstop(true);
+			go_xy(current_position[X_AXIS], y0, feedrate);
+			update_current_position_xyz();
+			if (!endstop_z_hit_on_purpose()) {
+				//                SERIAL_ECHOLN("Search Y2 span 1 - not found");
+				continue;
+			}
+			//            SERIAL_ECHOLN("Search Y2 span 1 - found");
+			b = current_position[Y_AXIS];
+			// Go to the center.
+			enable_z_endstop(false);
+			current_position[Y_AXIS] = 0.5f * (a + b);
+			go_xy(current_position[X_AXIS], current_position[Y_AXIS], feedrate);
+			found = true;
 #endif
-            break;
-        }
-    }
+			break;
+		}
+	}
 
-    enable_z_endstop(false);
-    return found;
+	enable_z_endstop(false);
+	return found;
 }
 
+#endif //HEATBED_V2
+
 // Search around the current_position[X,Y,Z].
 // It is expected, that the induction sensor is switched on at the current position.
 // Look around this center point by painting a star around the point.
@@ -1368,7 +1631,7 @@ canceled:
 // Searching in a zig-zag movement in a plane for the maximum width of the response.
 // This function may set the current_position[Y_AXIS] below Y_MIN_POS, if the function succeeded.
 // If this function failed, the Y coordinate will never be outside the working space.
-#define IMPROVE_BED_INDUCTION_SENSOR_POINT3_SEARCH_RADIUS (4.f)
+#define IMPROVE_BED_INDUCTION_SENSOR_POINT3_SEARCH_RADIUS (8.f)
 #define IMPROVE_BED_INDUCTION_SENSOR_POINT3_SEARCH_STEP_FINE_Y (0.1f)
 inline bool improve_bed_induction_sensor_point3(int verbosity_level)
 {	
@@ -1855,7 +2118,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
 		#endif // SUPPORT_VERBOSITY
 		if (!find_bed_induction_sensor_point_xy(verbosity_level))
 			return BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND;
-#if 1
+#ifndef HEATBED_V2
 		
 			if (k == 0 || k == 1) {
 				// Improve the position of the 1st row sensor points by a zig-zag movement.
@@ -1876,7 +2139,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
 					// not found
 					return BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND;
 			}
-#endif
+#endif //HEATBED_V2
 			#ifdef SUPPORT_VERBOSITY
 			if (verbosity_level >= 10)
 				delay_keep_alive(3000);
@@ -2292,16 +2555,7 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
     }
 	#endif // SUPPORT_VERBOSITY
 
-	//make space
-	current_position[Z_AXIS] += 150;
-	go_to_current(homing_feedrate[Z_AXIS] / 60);
-	//plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feedrate, active_extruder););
-
-	lcd_show_fullscreen_message_and_wait_P(MSG_PLACE_STEEL_SHEET);
-
-    // Sample Z heights for the mesh bed leveling.
-    // In addition, store the results into an eeprom, to be used later for verification of the bed leveling process.
-    if (! sample_mesh_and_store_reference())
+	if(!sample_z())
         goto canceled;
 
     enable_endstops(endstops_enabled);
@@ -2323,6 +2577,22 @@ canceled:
     return result;
 }
 
+bool sample_z() {
+	bool sampled = true;
+	//make space
+	current_position[Z_AXIS] += 150;
+	go_to_current(homing_feedrate[Z_AXIS] / 60);
+	//plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feedrate, active_extruder););
+
+	lcd_show_fullscreen_message_and_wait_P(MSG_PLACE_STEEL_SHEET);
+
+	// Sample Z heights for the mesh bed leveling.
+	// In addition, store the results into an eeprom, to be used later for verification of the bed leveling process.
+	if (!sample_mesh_and_store_reference()) sampled = false;
+
+	return sampled;
+}
+
 void go_home_with_z_lift()
 {
     // Don't let the manage_inactivity() function remove power from the motors.
@@ -2508,7 +2778,7 @@ bool scan_bed_induction_points(int8_t verbosity_level)
             current_position[Y_AXIS] = Y_MIN_POS_FOR_BED_CALIBRATION;
         go_to_current(homing_feedrate[X_AXIS]/60);
         find_bed_induction_sensor_point_z();
-        scan_bed_induction_sensor_point();
+		scan_bed_induction_sensor_point();
     }
     // Don't let the manage_inactivity() function remove power from the motors.
     refresh_cmd_timeout();

+ 1 - 0
Firmware/mesh_bed_calibration.h

@@ -187,5 +187,6 @@ extern void babystep_undo();
 // Reset the current babystep counter without moving the axes.
 extern void babystep_reset();
 extern void count_xyz_details();
+extern bool sample_z();
 
 #endif /* MESH_BED_CALIBRATION_H */

+ 1 - 54
Firmware/planner.cpp

@@ -126,10 +126,6 @@ static uint8_t g_cntr_planner_queue_min = 0;
 float extrude_min_temp=EXTRUDE_MINTEMP;
 #endif
 
-#ifdef FILAMENT_SENSOR
- static char meas_sample; //temporary variable to hold filament measurement sample
-#endif
-
 #ifdef LIN_ADVANCE
     float extruder_advance_k = LIN_ADVANCE_K,
     advance_ed_ratio = LIN_ADVANCE_E_D_RATIO,
@@ -782,12 +778,6 @@ block->steps_y = labs((target[X_AXIS]-position[X_AXIS]) - (target[Y_AXIS]-positi
 #endif
   block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]);
   block->steps_e = labs(target[E_AXIS]-position[E_AXIS]);
-  if (volumetric_multiplier[active_extruder] != 1.f)
-    block->steps_e *= volumetric_multiplier[active_extruder];
-  if (extrudemultiply != 100) {
-    block->steps_e *= extrudemultiply;
-    block->steps_e /= 100;
-  }
   block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e)));
 
   // Bail if this is a zero-length block
@@ -919,7 +909,7 @@ Having the real displacement of the head, we can calculate the total movement le
     delta_mm[Y_AXIS] = ((target[X_AXIS]-position[X_AXIS]) - (target[Y_AXIS]-position[Y_AXIS]))/axis_steps_per_unit[Y_AXIS];
   #endif
   delta_mm[Z_AXIS] = (target[Z_AXIS]-position[Z_AXIS])/axis_steps_per_unit[Z_AXIS];
-  delta_mm[E_AXIS] = ((target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS])*volumetric_multiplier[active_extruder]*extrudemultiply/100.0;
+  delta_mm[E_AXIS] = (target[E_AXIS]-position[E_AXIS])/axis_steps_per_unit[E_AXIS];
   if ( block->steps_x <=dropsegments && block->steps_y <=dropsegments && block->steps_z <=dropsegments )
   {
     block->millimeters = fabs(delta_mm[E_AXIS]);
@@ -955,49 +945,6 @@ Having the real displacement of the head, we can calculate the total movement le
   block->nominal_speed = block->millimeters * inverse_second; // (mm/sec) Always > 0
   block->nominal_rate = ceil(block->step_event_count * inverse_second); // (step/sec) Always > 0
 
-#ifdef FILAMENT_SENSOR
-  //FMM update ring buffer used for delay with filament measurements
-  
-  
-    if((extruder==FILAMENT_SENSOR_EXTRUDER_NUM) && (delay_index2 > -1))  //only for extruder with filament sensor and if ring buffer is initialized
-  	  {
-    delay_dist = delay_dist + delta_mm[E_AXIS];  //increment counter with next move in e axis
-  
-    while (delay_dist >= (10*(MAX_MEASUREMENT_DELAY+1)))  //check if counter is over max buffer size in mm
-      	  delay_dist = delay_dist - 10*(MAX_MEASUREMENT_DELAY+1);  //loop around the buffer
-    while (delay_dist<0)
-    	  delay_dist = delay_dist + 10*(MAX_MEASUREMENT_DELAY+1); //loop around the buffer
-      
-    delay_index1=delay_dist/10.0;  //calculate index
-    
-    //ensure the number is within range of the array after converting from floating point
-    if(delay_index1<0)
-    	delay_index1=0;
-    else if (delay_index1>MAX_MEASUREMENT_DELAY)
-    	delay_index1=MAX_MEASUREMENT_DELAY;
-    	
-    if(delay_index1 != delay_index2)  //moved index
-  	  {
-    	meas_sample=widthFil_to_size_ratio()-100;  //subtract off 100 to reduce magnitude - to store in a signed char
-  	  }
-    while( delay_index1 != delay_index2)
-  	  {
-  	  delay_index2 = delay_index2 + 1;
-  	if(delay_index2>MAX_MEASUREMENT_DELAY)
-  			  delay_index2=delay_index2-(MAX_MEASUREMENT_DELAY+1);  //loop around buffer when incrementing
-  	  if(delay_index2<0)
-  		delay_index2=0;
-  	  else if (delay_index2>MAX_MEASUREMENT_DELAY)
-  		delay_index2=MAX_MEASUREMENT_DELAY;  
-  	  
-  	  measurement_delay[delay_index2]=meas_sample;
-  	  }
-    	
-    
-  	  }
-#endif
-
-
   // Calculate and limit speed in mm/sec for each axis
   float current_speed[4];
   float speed_factor = 1.0; //factor <=1 do decrease speed

+ 14 - 9
Firmware/stepper.cpp

@@ -98,6 +98,7 @@ static bool old_z_max_endstop=false;
 static bool check_endstops = true;
 
 static bool check_z_endstop = false;
+static bool z_endstop_invert = false;
 
 int8_t SilentMode = 0;
 
@@ -282,10 +283,15 @@ bool enable_endstops(bool check)
 
 bool enable_z_endstop(bool check)
 {
-  bool old = check_z_endstop;
-  check_z_endstop = check;
-  endstop_z_hit=false;
-  return old;
+	bool old = check_z_endstop;
+	check_z_endstop = check;
+	endstop_z_hit = false;
+	return old;
+}
+
+void invert_z_endstop(bool endstop_invert)
+{
+  z_endstop_invert = endstop_invert;
 }
 
 //         __________________________
@@ -603,9 +609,9 @@ void isr() {
         // Good for searching for the center of an induction target.
             #ifdef TMC2130_SG_HOMING
             // Stall guard homing turned on
-                z_min_endstop = (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING) || (READ(Z_TMC2130_DIAG) != 0);
+                z_min_endstop = (READ(Z_MIN_PIN) != z_endstop_invert) || (READ(Z_TMC2130_DIAG) != 0);
             #else
-				z_min_endstop = (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING);
+                z_min_endstop = (READ(Z_MIN_PIN) != z_endstop_invert);
             #endif //TMC2130_SG_HOMING
         if(z_min_endstop && old_z_min_endstop) {
           endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
@@ -1361,10 +1367,9 @@ void EEPROM_read_st(int pos, uint8_t* value, uint8_t size)
 
 
 void digipot_init() //Initialize Digipot Motor Current
-{
-
+{  
   EEPROM_read_st(EEPROM_SILENT,(uint8_t*)&SilentMode,sizeof(SilentMode));
-
+  SilentModeMenu = SilentMode;
   #if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
     if(SilentMode == 0){
     const uint8_t digipot_motor_current[] = DIGIPOT_MOTOR_CURRENT_LOUD;

+ 1 - 0
Firmware/stepper.h

@@ -93,6 +93,7 @@ bool endstop_z_hit_on_purpose();
 
 bool enable_endstops(bool check); // Enable/disable endstop checking. Return the old value.
 bool enable_z_endstop(bool check);
+void invert_z_endstop(bool endstop_invert);
 
 void checkStepperErrors(); //Print errors detected by the stepper
 

+ 1 - 59
Firmware/temperature.cpp

@@ -104,9 +104,6 @@ unsigned char soft_pwm_bed;
   volatile int babystepsTodo[3]={0,0,0};
 #endif
 
-#ifdef FILAMENT_SENSOR
-  int current_raw_filwidth = 0;  //Holds measured filament diameter - one extruder only
-#endif  
 //===========================================================================
 //=============================private variables============================
 //===========================================================================
@@ -204,9 +201,6 @@ unsigned long watchmillis[EXTRUDERS] = ARRAY_BY_EXTRUDERS(0,0,0);
 #define SOFT_PWM_SCALE 0
 #endif
 
-#ifdef FILAMENT_SENSOR
-  static int meas_shift_index;  //used to point to a delayed sample in buffer for filament width sensor
-#endif
 //===========================================================================
 //=============================   functions      ============================
 //===========================================================================
@@ -810,27 +804,6 @@ void manage_heater()
     #endif
   #endif
   
-//code for controlling the extruder rate based on the width sensor 
-#ifdef FILAMENT_SENSOR
-  if(filament_sensor) 
-	{
-	meas_shift_index=delay_index1-meas_delay_cm;
-		  if(meas_shift_index<0)
-			  meas_shift_index = meas_shift_index + (MAX_MEASUREMENT_DELAY+1);  //loop around buffer if needed
-		  
-		  //get the delayed info and add 100 to reconstitute to a percent of the nominal filament diameter
-		  //then square it to get an area
-		  
-		  if(meas_shift_index<0)
-			  meas_shift_index=0;
-		  else if (meas_shift_index>MAX_MEASUREMENT_DELAY)
-			  meas_shift_index=MAX_MEASUREMENT_DELAY;
-		  
-		     volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM] = pow((float)(100+measurement_delay[meas_shift_index])/100.0,2);
-		     if (volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM] <0.01)
-		    	 volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM]=0.01;
-	}
-#endif
 #ifdef HOST_KEEPALIVE_FEATURE
   host_keepalive();
 #endif
@@ -985,9 +958,7 @@ static void updateTemperaturesFromRawValues()
     #ifdef TEMP_SENSOR_1_AS_REDUNDANT
       redundant_temperature = analog2temp(redundant_temperature_raw, 1);
     #endif
-    #if defined (FILAMENT_SENSOR) && (FILWIDTH_PIN > -1)    //check if a sensor is supported 
-      filament_width_meas = analog2widthFil();
-    #endif  
+
     //Reset the watchdog after we know we have a temperature measurement.
     watchdog_reset();
 
@@ -997,35 +968,6 @@ static void updateTemperaturesFromRawValues()
 }
 
 
-// For converting raw Filament Width to milimeters 
-#ifdef FILAMENT_SENSOR
-float analog2widthFil() { 
-return current_raw_filwidth/16383.0*5.0; 
-//return current_raw_filwidth; 
-} 
- 
-// For converting raw Filament Width to a ratio 
-int widthFil_to_size_ratio() { 
- 
-float temp; 
-      
-temp=filament_width_meas;
-if(filament_width_meas<MEASURED_LOWER_LIMIT)
-	temp=filament_width_nominal;  //assume sensor cut out
-else if (filament_width_meas>MEASURED_UPPER_LIMIT)
-	temp= MEASURED_UPPER_LIMIT;
-
-
-return(filament_width_nominal/temp*100); 
-
-
-} 
-#endif
-
-
-
-
-
 void tp_init()
 {
 #if MB(RUMBA) && ((TEMP_SENSOR_0==-1)||(TEMP_SENSOR_1==-1)||(TEMP_SENSOR_2==-1)||(TEMP_SENSOR_BED==-1))

+ 0 - 8
Firmware/temperature.h

@@ -31,14 +31,6 @@
 void tp_init();  //initialize the heating
 void manage_heater(); //it is critical that this is called periodically.
 
-#ifdef FILAMENT_SENSOR
-// For converting raw Filament Width to milimeters 
- float analog2widthFil(); 
- 
-// For converting raw Filament Width to an extrusion ratio 
- int widthFil_to_size_ratio();
-#endif
-
 // low level conversion routines
 // do not use these routines and variables outside of temperature.cpp
 extern int target_temperature[EXTRUDERS];  

+ 104 - 38
Firmware/ultralcd.cpp

@@ -204,9 +204,9 @@ static void prusa_stat_temperatures();
 static void prusa_stat_printinfo();
 static void lcd_farm_no();
 static void lcd_menu_extruder_info();
-#ifdef TMC2130
+#if defined(TMC2130) || defined(PAT9125)
 static void lcd_menu_fails_stats();
-#endif //TMC2130
+#endif //TMC2130 or PAT9125
 
 void lcd_finishstatus();
 
@@ -1537,7 +1537,7 @@ static void lcd_menu_extruder_info()
     }
 }
 
-#ifdef TMC2130
+#if defined(TMC2130) && defined(PAT9125)
 static void lcd_menu_fails_stats_total()
 {
 //01234567890123456789
@@ -1579,7 +1579,13 @@ static void lcd_menu_fails_stats_print()
 		lcd_goto_menu(lcd_menu_fails_stats, 2);
     }    
 }
-
+/**
+ * @brief Open fail statistics menu
+ *
+ * This version of function is used, when there is filament sensor,
+ * power failure and crash detection.
+ * There are Last print and Total menu items.
+ */
 static void lcd_menu_fails_stats()
 {
 	START_MENU();
@@ -1588,6 +1594,34 @@ static void lcd_menu_fails_stats()
 	MENU_ITEM(submenu, PSTR("Total"), lcd_menu_fails_stats_total);
 	END_MENU();
 }
+#else if defined(PAT9125)
+/**
+ * @brief Print last print and total filament run outs
+ *
+ * This version of function is used, when there is filament sensor,
+ * but no other sensors (e.g. power failure, crash detection).
+ *
+ * Example screen:
+ * @code
+ * 01234567890123456789
+ * Last print failures
+ *  Filam. runouts  0
+ * Total failures
+ *  Filam. runouts  5
+ * @endcode
+ */
+static void lcd_menu_fails_stats()
+{
+    uint8_t filamentLast = eeprom_read_byte((uint8_t*)EEPROM_FERROR_COUNT);
+    uint16_t filamentTotal = eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT);
+    fprintf_P(lcdout, PSTR(ESC_H(0,0)"Last print failures"ESC_H(1,1)"Filam. runouts  %-3d"ESC_H(0,2)"Total failures"ESC_H(1,3)"Filam. runouts  %-3d"), filamentLast, filamentTotal);
+    if (lcd_clicked())
+    {
+        lcd_quick_feedback();
+        //lcd_return_to_status();
+        lcd_goto_menu(lcd_main_menu, 8); //TODO: Remove hard coded encoder value.
+    }
+}
 #endif //TMC2130
 
 
@@ -3412,7 +3446,12 @@ static void lcd_fsensor_fail()
 
 
 static void lcd_silent_mode_set() {
-  SilentModeMenu = !SilentModeMenu;
+	switch (SilentModeMenu) {
+	case 0: SilentModeMenu = 1; break;
+	case 1: SilentModeMenu = 2; break;
+	case 2: SilentModeMenu = 0; break;
+	default: SilentModeMenu = 0; break;
+	}
   eeprom_update_byte((unsigned char *)EEPROM_SILENT, SilentModeMenu);
 #ifdef TMC2130
   // Wait until the planner queue is drained and the stepper routine achieves
@@ -3891,6 +3930,14 @@ static void lcd_settings_menu()
   {
 	  MENU_ITEM(gcode, MSG_DISABLE_STEPPERS, PSTR("M84"));
   }
+  if (!farm_mode) { //dont show in menu if we are in farm mode
+	  switch (SilentModeMenu) {
+	  case 0: MENU_ITEM(function, MSG_SILENT_MODE_OFF, lcd_silent_mode_set); break;
+	  case 1: MENU_ITEM(function, MSG_SILENT_MODE_ON, lcd_silent_mode_set); break;
+	  case 2: MENU_ITEM(function, MSG_AUTO_MODE_ON, lcd_silent_mode_set); break;
+	  default: MENU_ITEM(function, MSG_SILENT_MODE_OFF, lcd_silent_mode_set); break;
+	  }
+  }
 
 #ifdef PAT9125
 #ifndef DEBUG_DISABLE_FSENSORCHECK
@@ -3944,12 +3991,15 @@ static void lcd_settings_menu()
   else {
 	  MENU_ITEM(function, MSG_TEMP_CALIBRATION_ON, lcd_temp_calibration_set);
   }
+#ifdef HAS_SECOND_SERIAL_PORT
   if (selectedSerialPort == 0) {
 	  MENU_ITEM(function, MSG_SECOND_SERIAL_OFF, lcd_second_serial_set);
   }
   else {
 	  MENU_ITEM(function, MSG_SECOND_SERIAL_ON, lcd_second_serial_set);
   }
+#endif //HAS_SECOND_SERIAL
+
 
   if (!isPrintPaused && !homing_flag)
 	{
@@ -5207,9 +5257,9 @@ static void lcd_main_menu()
 	  MENU_ITEM(submenu, MSG_STATISTICS, lcd_menu_statistics);
   }
     
-#ifdef TMC2130
+#if defined(TMC2130) || defined(PAT9125)
   MENU_ITEM(submenu, PSTR("Fail stats"), lcd_menu_fails_stats);
-#endif //TMC2130
+#endif
 
   MENU_ITEM(submenu, MSG_SUPPORT, lcd_support_menu);
 
@@ -5251,6 +5301,18 @@ static void lcd_autostart_sd()
 
 
 
+static void lcd_silent_mode_set_tune() {
+  switch (SilentModeMenu) {
+  case 0: SilentModeMenu = 1; break;
+  case 1: SilentModeMenu = 2; break;
+  case 2: SilentModeMenu = 0; break;
+  default: SilentModeMenu = 0; break;
+  }
+  eeprom_update_byte((unsigned char *)EEPROM_SILENT, SilentModeMenu);
+  digipot_init();
+  lcd_goto_menu(lcd_tune_menu, 9);
+}
+
 static void lcd_colorprint_change() {
 	
 	enquecommand_P(PSTR("M600"));
@@ -5264,51 +5326,55 @@ static void lcd_colorprint_change() {
 
 static void lcd_tune_menu()
 {
-  EEPROM_read(EEPROM_SILENT, (uint8_t*)&SilentModeMenu, sizeof(SilentModeMenu));
+	EEPROM_read(EEPROM_SILENT, (uint8_t*)&SilentModeMenu, sizeof(SilentModeMenu));
 
-  
 
-  START_MENU();
-  MENU_ITEM(back, MSG_MAIN, lcd_main_menu); //1
-  MENU_ITEM_EDIT(int3, MSG_SPEED, &feedmultiply, 10, 999);//2
 
-  MENU_ITEM_EDIT(int3, MSG_NOZZLE, &target_temperature[0], 0, HEATER_0_MAXTEMP - 10);//3
-  MENU_ITEM_EDIT(int3, MSG_BED, &target_temperature_bed, 0, BED_MAXTEMP - 10);//4
+	START_MENU();
+	MENU_ITEM(back, MSG_MAIN, lcd_main_menu); //1
+	MENU_ITEM_EDIT(int3, MSG_SPEED, &feedmultiply, 10, 999);//2
+
+	MENU_ITEM_EDIT(int3, MSG_NOZZLE, &target_temperature[0], 0, HEATER_0_MAXTEMP - 10);//3
+	MENU_ITEM_EDIT(int3, MSG_BED, &target_temperature_bed, 0, BED_MAXTEMP - 10);//4
 
-  MENU_ITEM_EDIT(int3, MSG_FAN_SPEED, &fanSpeed, 0, 255);//5
-  MENU_ITEM_EDIT(int3, MSG_FLOW, &extrudemultiply, 10, 999);//6
+	MENU_ITEM_EDIT(int3, MSG_FAN_SPEED, &fanSpeed, 0, 255);//5
+	MENU_ITEM_EDIT(int3, MSG_FLOW, &extrudemultiply, 10, 999);//6
 #ifdef FILAMENTCHANGEENABLE
-  MENU_ITEM(function, MSG_FILAMENTCHANGE, lcd_colorprint_change);//7
+	MENU_ITEM(function, MSG_FILAMENTCHANGE, lcd_colorprint_change);//7
 #endif
-  
-#ifdef PAT9125
+
 #ifndef DEBUG_DISABLE_FSENSORCHECK
-  if (FSensorStateMenu == 0) {
-    MENU_ITEM(function, MSG_FSENSOR_OFF, lcd_fsensor_state_set);
-  } else {
-    MENU_ITEM(function, MSG_FSENSOR_ON, lcd_fsensor_state_set);
-  }
+	if (FSensorStateMenu == 0) {
+		MENU_ITEM(function, MSG_FSENSOR_OFF, lcd_fsensor_state_set);
+	}
+	else {
+		MENU_ITEM(function, MSG_FSENSOR_ON, lcd_fsensor_state_set);
+	}
 #endif //DEBUG_DISABLE_FSENSORCHECK
-#endif //PAT9125
 
 #ifdef TMC2130
-  if (SilentModeMenu == 0) MENU_ITEM(function, MSG_SILENT_MODE_OFF, lcd_silent_mode_set);
-  else MENU_ITEM(function, MSG_SILENT_MODE_ON, lcd_silent_mode_set);
+	if (SilentModeMenu == 0) MENU_ITEM(function, MSG_SILENT_MODE_OFF, lcd_silent_mode_set);
+	else MENU_ITEM(function, MSG_SILENT_MODE_ON, lcd_silent_mode_set);
 
-  if (SilentModeMenu == 0)
-  {
-    if (CrashDetectMenu == 0) MENU_ITEM(function, MSG_CRASHDETECT_OFF, lcd_crash_mode_set);
-    else MENU_ITEM(function, MSG_CRASHDETECT_ON, lcd_crash_mode_set);
-  }
-  else MENU_ITEM(submenu, MSG_CRASHDETECT_NA, lcd_crash_mode_info);
+	if (SilentModeMenu == 0)
+	{
+		if (CrashDetectMenu == 0) MENU_ITEM(function, MSG_CRASHDETECT_OFF, lcd_crash_mode_set);
+		else MENU_ITEM(function, MSG_CRASHDETECT_ON, lcd_crash_mode_set);
+	}
+	else MENU_ITEM(submenu, MSG_CRASHDETECT_NA, lcd_crash_mode_info);
+#else //TMC2130
+	if (!farm_mode) { //dont show in menu if we are in farm mode
+		switch (SilentModeMenu) {
+		case 0: MENU_ITEM(function, MSG_SILENT_MODE_OFF, lcd_silent_mode_set); break;
+		case 1: MENU_ITEM(function, MSG_SILENT_MODE_ON, lcd_silent_mode_set); break;
+		case 2: MENU_ITEM(function, MSG_AUTO_MODE_ON, lcd_silent_mode_set); break;
+		default: MENU_ITEM(function, MSG_SILENT_MODE_OFF, lcd_silent_mode_set); break;
+		}
+	}
 #endif //TMC2130
-
-  END_MENU();
+	END_MENU();
 }
 
-
-
-
 static void lcd_move_menu_01mm()
 {
   move_menu_scale = 0.1;

+ 1 - 0
Firmware/ultralcd.h

@@ -118,6 +118,7 @@ void lcd_mylang();
   extern int farm_no;
   extern int farm_timer;
   extern int farm_status;
+  extern int8_t SilentModeMenu;
 
 #ifdef SNMM
   extern uint8_t snmm_extruder;