|  |  |  | @ -894,7 +894,7 @@ static void set_bed_level_equation_lsq(double *plane_equation_coefficients) | 
			
		
	
		
			
				
					|  |  |  |  |     current_position[Y_AXIS] = corrected_position.y; | 
			
		
	
		
			
				
					|  |  |  |  |     current_position[Z_AXIS] = corrected_position.z; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // but the bed at 0 so we don't go below it.
 | 
			
		
	
		
			
				
					|  |  |  |  |     // put the bed at 0 so we don't go below it.
 | 
			
		
	
		
			
				
					|  |  |  |  |     current_position[Z_AXIS] = zprobe_zoffset; // in the lsq we reach here after raising the extruder due to the loop structure
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); | 
			
		
	
	
		
			
				
					|  |  |  | @ -1862,6 +1862,280 @@ void process_commands() | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  |      break; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // M48 Z-Probe repeatability measurement function.
 | 
			
		
	
		
			
				
					|  |  |  |  | //
 | 
			
		
	
		
			
				
					|  |  |  |  | // Usage:   M48 <n #_samples> <X X_position_for_samples> <Y Y_position_for_samples> <V Verbose_Level> <Engage_probe_for_each_reading> <L legs_of_movement_prior_to_doing_probe>
 | 
			
		
	
		
			
				
					|  |  |  |  | //	
 | 
			
		
	
		
			
				
					|  |  |  |  | // This function assumes the bed has been homed.  Specificaly, that a G28 command
 | 
			
		
	
		
			
				
					|  |  |  |  | // as been issued prior to invoking the M48 Z-Probe repeatability measurement function.
 | 
			
		
	
		
			
				
					|  |  |  |  | // Any information generated by a prior G29 Bed leveling command will be lost and need to be
 | 
			
		
	
		
			
				
					|  |  |  |  | // regenerated.
 | 
			
		
	
		
			
				
					|  |  |  |  | //
 | 
			
		
	
		
			
				
					|  |  |  |  | // The number of samples will default to 10 if not specified.  You can use upper or lower case
 | 
			
		
	
		
			
				
					|  |  |  |  | // letters for any of the options EXCEPT n.  n must be in lower case because Marlin uses a capital
 | 
			
		
	
		
			
				
					|  |  |  |  | // N for its communication protocol and will get horribly confused if you send it a capital N.
 | 
			
		
	
		
			
				
					|  |  |  |  | //
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | #ifdef ENABLE_AUTO_BED_LEVELING | 
			
		
	
		
			
				
					|  |  |  |  | #ifdef Z_PROBE_REPEATABILITY_TEST  | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     case 48: // M48 Z-Probe repeatability
 | 
			
		
	
		
			
				
					|  |  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |  |             #if Z_MIN_PIN == -1 | 
			
		
	
		
			
				
					|  |  |  |  |             #error "You must have a Z_MIN endstop in order to enable calculation of Z-Probe repeatability." | 
			
		
	
		
			
				
					|  |  |  |  |             #endif | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	double sum=0.0;  | 
			
		
	
		
			
				
					|  |  |  |  | 	double mean=0.0;  | 
			
		
	
		
			
				
					|  |  |  |  | 	double sigma=0.0; | 
			
		
	
		
			
				
					|  |  |  |  | 	double sample_set[50]; | 
			
		
	
		
			
				
					|  |  |  |  | 	int verbose_level=1, n=0, j, n_samples = 10, n_legs=0, engage_probe_for_each_reading=0 ; | 
			
		
	
		
			
				
					|  |  |  |  | 	double X_current, Y_current, Z_current; | 
			
		
	
		
			
				
					|  |  |  |  | 	double X_probe_location, Y_probe_location, Z_start_location, ext_position; | 
			
		
	
		
			
				
					|  |  |  |  | 	 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (code_seen('V') || code_seen('v')) { | 
			
		
	
		
			
				
					|  |  |  |  |         	verbose_level = code_value(); | 
			
		
	
		
			
				
					|  |  |  |  | 		if (verbose_level<0 || verbose_level>4 ) { | 
			
		
	
		
			
				
					|  |  |  |  | 			SERIAL_PROTOCOLPGM("?Verbose Level not plausable.\n"); | 
			
		
	
		
			
				
					|  |  |  |  | 			goto Sigma_Exit; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (verbose_level > 0)   { | 
			
		
	
		
			
				
					|  |  |  |  | 		SERIAL_PROTOCOLPGM("M48 Z-Probe Repeatability test.   Version 2.00\n"); | 
			
		
	
		
			
				
					|  |  |  |  | 		SERIAL_PROTOCOLPGM("Full support at: http://3dprintboard.com/forum.php\n"); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (code_seen('n')) { | 
			
		
	
		
			
				
					|  |  |  |  |         	n_samples = code_value(); | 
			
		
	
		
			
				
					|  |  |  |  | 		if (n_samples<4 || n_samples>50 ) { | 
			
		
	
		
			
				
					|  |  |  |  | 			SERIAL_PROTOCOLPGM("?Specified sample size not plausable.\n"); | 
			
		
	
		
			
				
					|  |  |  |  | 			goto Sigma_Exit; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	X_current = X_probe_location = st_get_position_mm(X_AXIS); | 
			
		
	
		
			
				
					|  |  |  |  | 	Y_current = Y_probe_location = st_get_position_mm(Y_AXIS); | 
			
		
	
		
			
				
					|  |  |  |  | 	Z_current = st_get_position_mm(Z_AXIS); | 
			
		
	
		
			
				
					|  |  |  |  | 	Z_start_location = st_get_position_mm(Z_AXIS) + Z_RAISE_BEFORE_PROBING; | 
			
		
	
		
			
				
					|  |  |  |  | 	ext_position	 = st_get_position_mm(E_AXIS); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (code_seen('E') || code_seen('e') )  | 
			
		
	
		
			
				
					|  |  |  |  | 		engage_probe_for_each_reading++; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (code_seen('X') || code_seen('x') ) { | 
			
		
	
		
			
				
					|  |  |  |  |         	X_probe_location = code_value() -  X_PROBE_OFFSET_FROM_EXTRUDER; | 
			
		
	
		
			
				
					|  |  |  |  | 		if (X_probe_location<X_MIN_POS || X_probe_location>X_MAX_POS ) { | 
			
		
	
		
			
				
					|  |  |  |  | 			SERIAL_PROTOCOLPGM("?Specified X position out of range.\n"); | 
			
		
	
		
			
				
					|  |  |  |  | 			goto Sigma_Exit; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (code_seen('Y') || code_seen('y') ) { | 
			
		
	
		
			
				
					|  |  |  |  |         	Y_probe_location = code_value() -  Y_PROBE_OFFSET_FROM_EXTRUDER; | 
			
		
	
		
			
				
					|  |  |  |  | 		if (Y_probe_location<Y_MIN_POS || Y_probe_location>Y_MAX_POS ) { | 
			
		
	
		
			
				
					|  |  |  |  | 			SERIAL_PROTOCOLPGM("?Specified Y position out of range.\n"); | 
			
		
	
		
			
				
					|  |  |  |  | 			goto Sigma_Exit; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (code_seen('L') || code_seen('l') ) { | 
			
		
	
		
			
				
					|  |  |  |  |         	n_legs = code_value(); | 
			
		
	
		
			
				
					|  |  |  |  | 		if ( n_legs==1 )  | 
			
		
	
		
			
				
					|  |  |  |  | 			n_legs = 2; | 
			
		
	
		
			
				
					|  |  |  |  | 		if ( n_legs<0 || n_legs>15 ) { | 
			
		
	
		
			
				
					|  |  |  |  | 			SERIAL_PROTOCOLPGM("?Specified number of legs in movement not plausable.\n"); | 
			
		
	
		
			
				
					|  |  |  |  | 			goto Sigma_Exit; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | //
 | 
			
		
	
		
			
				
					|  |  |  |  | // Do all the preliminary setup work.   First raise the probe.
 | 
			
		
	
		
			
				
					|  |  |  |  | //
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         st_synchronize(); | 
			
		
	
		
			
				
					|  |  |  |  |         plan_bed_level_matrix.set_to_identity(); | 
			
		
	
		
			
				
					|  |  |  |  | 	plan_buffer_line( X_current, Y_current, Z_start_location, | 
			
		
	
		
			
				
					|  |  |  |  | 			ext_position, | 
			
		
	
		
			
				
					|  |  |  |  |     			homing_feedrate[Z_AXIS]/60, | 
			
		
	
		
			
				
					|  |  |  |  | 			active_extruder); | 
			
		
	
		
			
				
					|  |  |  |  |         st_synchronize(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | //
 | 
			
		
	
		
			
				
					|  |  |  |  | // Now get everything to the specified probe point So we can safely do a probe to
 | 
			
		
	
		
			
				
					|  |  |  |  | // get us close to the bed.  If the Z-Axis is far from the bed, we don't want to 
 | 
			
		
	
		
			
				
					|  |  |  |  | // use that as a starting point for each probe.
 | 
			
		
	
		
			
				
					|  |  |  |  | //
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (verbose_level > 2)  | 
			
		
	
		
			
				
					|  |  |  |  | 		SERIAL_PROTOCOL("Positioning probe for the test.\n"); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	plan_buffer_line( X_probe_location, Y_probe_location, Z_start_location, | 
			
		
	
		
			
				
					|  |  |  |  | 			ext_position, | 
			
		
	
		
			
				
					|  |  |  |  |     			homing_feedrate[X_AXIS]/60, | 
			
		
	
		
			
				
					|  |  |  |  | 			active_extruder); | 
			
		
	
		
			
				
					|  |  |  |  |         st_synchronize(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	current_position[X_AXIS] = X_current = st_get_position_mm(X_AXIS); | 
			
		
	
		
			
				
					|  |  |  |  | 	current_position[Y_AXIS] = Y_current = st_get_position_mm(Y_AXIS); | 
			
		
	
		
			
				
					|  |  |  |  | 	current_position[Z_AXIS] = Z_current = st_get_position_mm(Z_AXIS); | 
			
		
	
		
			
				
					|  |  |  |  | 	current_position[E_AXIS] = ext_position = st_get_position_mm(E_AXIS); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | // 
 | 
			
		
	
		
			
				
					|  |  |  |  | // OK, do the inital probe to get us close to the bed.
 | 
			
		
	
		
			
				
					|  |  |  |  | // Then retrace the right amount and use that in subsequent probes
 | 
			
		
	
		
			
				
					|  |  |  |  | //
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         engage_z_probe();	 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	setup_for_endstop_move(); | 
			
		
	
		
			
				
					|  |  |  |  | 	run_z_probe(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	current_position[Z_AXIS] = Z_current = st_get_position_mm(Z_AXIS); | 
			
		
	
		
			
				
					|  |  |  |  | 	Z_start_location = st_get_position_mm(Z_AXIS) + Z_RAISE_BEFORE_PROBING; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	plan_buffer_line( X_probe_location, Y_probe_location, Z_start_location, | 
			
		
	
		
			
				
					|  |  |  |  | 			ext_position, | 
			
		
	
		
			
				
					|  |  |  |  |     			homing_feedrate[X_AXIS]/60, | 
			
		
	
		
			
				
					|  |  |  |  | 			active_extruder); | 
			
		
	
		
			
				
					|  |  |  |  |         st_synchronize(); | 
			
		
	
		
			
				
					|  |  |  |  | 	current_position[Z_AXIS] = Z_current = st_get_position_mm(Z_AXIS); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (engage_probe_for_each_reading) | 
			
		
	
		
			
				
					|  |  |  |  |         	retract_z_probe(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         for( n=0; n<n_samples; n++) { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		do_blocking_move_to( X_probe_location, Y_probe_location, Z_start_location); // Make sure we are at the probe location
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if ( n_legs)  { | 
			
		
	
		
			
				
					|  |  |  |  | 		double radius=0.0, theta=0.0, x_sweep, y_sweep; | 
			
		
	
		
			
				
					|  |  |  |  | 		int rotational_direction, l; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			rotational_direction = (unsigned long) millis() & 0x0001;			// clockwise or counter clockwise
 | 
			
		
	
		
			
				
					|  |  |  |  | 			radius = (unsigned long) millis() % (long) (X_MAX_LENGTH/4); 			// limit how far out to go 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			theta = (float) ((unsigned long) millis() % (long) 360) / (360./(2*3.1415926));	// turn into radians
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | //SERIAL_ECHOPAIR("starting radius: ",radius);
 | 
			
		
	
		
			
				
					|  |  |  |  | //SERIAL_ECHOPAIR("   theta: ",theta);
 | 
			
		
	
		
			
				
					|  |  |  |  | //SERIAL_ECHOPAIR("   direction: ",rotational_direction);
 | 
			
		
	
		
			
				
					|  |  |  |  | //SERIAL_PROTOCOLLNPGM("");
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			for( l=0; l<n_legs-1; l++) { | 
			
		
	
		
			
				
					|  |  |  |  | 				if (rotational_direction==1) | 
			
		
	
		
			
				
					|  |  |  |  | 					theta += (float) ((unsigned long) millis() % (long) 20) / (360.0/(2*3.1415926)); // turn into radians
 | 
			
		
	
		
			
				
					|  |  |  |  | 				else | 
			
		
	
		
			
				
					|  |  |  |  | 					theta -= (float) ((unsigned long) millis() % (long) 20) / (360.0/(2*3.1415926)); // turn into radians
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				radius += (float) ( ((long) ((unsigned long) millis() % (long) 10)) - 5); | 
			
		
	
		
			
				
					|  |  |  |  | 				if ( radius<0.0 ) | 
			
		
	
		
			
				
					|  |  |  |  | 					radius = -radius; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				X_current = X_probe_location + cos(theta) * radius; | 
			
		
	
		
			
				
					|  |  |  |  | 				Y_current = Y_probe_location + sin(theta) * radius; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				if ( X_current<X_MIN_POS)		// Make sure our X & Y are sane
 | 
			
		
	
		
			
				
					|  |  |  |  | 					 X_current = X_MIN_POS; | 
			
		
	
		
			
				
					|  |  |  |  | 				if ( X_current>X_MAX_POS) | 
			
		
	
		
			
				
					|  |  |  |  | 					 X_current = X_MAX_POS; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				if ( Y_current<Y_MIN_POS)		// Make sure our X & Y are sane
 | 
			
		
	
		
			
				
					|  |  |  |  | 					 Y_current = Y_MIN_POS; | 
			
		
	
		
			
				
					|  |  |  |  | 				if ( Y_current>Y_MAX_POS) | 
			
		
	
		
			
				
					|  |  |  |  | 					 Y_current = Y_MAX_POS; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				if (verbose_level>3 ) { | 
			
		
	
		
			
				
					|  |  |  |  | 					SERIAL_ECHOPAIR("x: ", X_current); | 
			
		
	
		
			
				
					|  |  |  |  | 					SERIAL_ECHOPAIR("y: ", Y_current); | 
			
		
	
		
			
				
					|  |  |  |  | 					SERIAL_PROTOCOLLNPGM(""); | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				do_blocking_move_to( X_current, Y_current, Z_current ); | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 			do_blocking_move_to( X_probe_location, Y_probe_location, Z_start_location); // Go back to the probe location
 | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (engage_probe_for_each_reading)  { | 
			
		
	
		
			
				
					|  |  |  |  |         		engage_z_probe();	 | 
			
		
	
		
			
				
					|  |  |  |  |           		delay(1000); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		setup_for_endstop_move(); | 
			
		
	
		
			
				
					|  |  |  |  |                 run_z_probe(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		sample_set[n] = current_position[Z_AXIS]; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | //
 | 
			
		
	
		
			
				
					|  |  |  |  | // Get the current mean for the data points we have so far
 | 
			
		
	
		
			
				
					|  |  |  |  | //
 | 
			
		
	
		
			
				
					|  |  |  |  | 		sum=0.0;  | 
			
		
	
		
			
				
					|  |  |  |  | 		for( j=0; j<=n; j++) { | 
			
		
	
		
			
				
					|  |  |  |  | 			sum = sum + sample_set[j]; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		mean = sum / (double (n+1)); | 
			
		
	
		
			
				
					|  |  |  |  | //
 | 
			
		
	
		
			
				
					|  |  |  |  | // Now, use that mean to calculate the standard deviation for the
 | 
			
		
	
		
			
				
					|  |  |  |  | // data points we have so far
 | 
			
		
	
		
			
				
					|  |  |  |  | //
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		sum=0.0;  | 
			
		
	
		
			
				
					|  |  |  |  | 		for( j=0; j<=n; j++) { | 
			
		
	
		
			
				
					|  |  |  |  | 			sum = sum + (sample_set[j]-mean) * (sample_set[j]-mean); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		sigma = sqrt( sum / (double (n+1)) ); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (verbose_level > 1) { | 
			
		
	
		
			
				
					|  |  |  |  | 			SERIAL_PROTOCOL(n+1); | 
			
		
	
		
			
				
					|  |  |  |  | 			SERIAL_PROTOCOL(" of "); | 
			
		
	
		
			
				
					|  |  |  |  | 			SERIAL_PROTOCOL(n_samples); | 
			
		
	
		
			
				
					|  |  |  |  | 			SERIAL_PROTOCOLPGM("   z: "); | 
			
		
	
		
			
				
					|  |  |  |  | 			SERIAL_PROTOCOL_F(current_position[Z_AXIS], 6); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (verbose_level > 2) { | 
			
		
	
		
			
				
					|  |  |  |  | 			SERIAL_PROTOCOL(" mean: "); | 
			
		
	
		
			
				
					|  |  |  |  | 			SERIAL_PROTOCOL_F(mean,6); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 			SERIAL_PROTOCOL("   sigma: "); | 
			
		
	
		
			
				
					|  |  |  |  | 			SERIAL_PROTOCOL_F(sigma,6); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (verbose_level > 0)  | 
			
		
	
		
			
				
					|  |  |  |  | 			SERIAL_PROTOCOLPGM("\n"); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		plan_buffer_line( X_probe_location, Y_probe_location, Z_start_location,  | 
			
		
	
		
			
				
					|  |  |  |  | 				  current_position[E_AXIS], homing_feedrate[Z_AXIS]/60, active_extruder); | 
			
		
	
		
			
				
					|  |  |  |  |         	st_synchronize(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (engage_probe_for_each_reading)  { | 
			
		
	
		
			
				
					|  |  |  |  |         		retract_z_probe();	 | 
			
		
	
		
			
				
					|  |  |  |  |           		delay(1000); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         retract_z_probe(); | 
			
		
	
		
			
				
					|  |  |  |  | 	delay(1000); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         clean_up_after_endstop_move(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | //      enable_endstops(true);
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (verbose_level > 0) { | 
			
		
	
		
			
				
					|  |  |  |  | 		SERIAL_PROTOCOLPGM("Mean: "); | 
			
		
	
		
			
				
					|  |  |  |  | 		SERIAL_PROTOCOL_F(mean, 6); | 
			
		
	
		
			
				
					|  |  |  |  | 		SERIAL_PROTOCOLPGM("\n"); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | SERIAL_PROTOCOLPGM("Standard Deviation: "); | 
			
		
	
		
			
				
					|  |  |  |  | SERIAL_PROTOCOL_F(sigma, 6); | 
			
		
	
		
			
				
					|  |  |  |  | SERIAL_PROTOCOLPGM("\n\n"); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | Sigma_Exit: | 
			
		
	
		
			
				
					|  |  |  |  |         break; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | #endif		// Z_PROBE_REPEATABILITY_TEST 
 | 
			
		
	
		
			
				
					|  |  |  |  | #endif		// ENABLE_AUTO_BED_LEVELING
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     case 104: // M104
 | 
			
		
	
		
			
				
					|  |  |  |  |       if(setTargetedHotend(104)){ | 
			
		
	
		
			
				
					|  |  |  |  |         break; | 
			
		
	
	
		
			
				
					|  |  |  | 
 |