Browse Source

Z_PROBE_REPEATABILITY test

Z_PROBE_REPEATABILITY test for Auto Bed Leveling.
Implemented as M48 with extra user specified options.
Full support at
http://3dprintboard.com/showthread.php?2802-Auto_Bed_Leveling-Z-Probe-Repeatability-code
Roxy-3DPrintBoard 11 years ago
parent
commit
0091865583
2 changed files with 277 additions and 2 deletions
  1. 2
    1
      Marlin/Configuration.h
  2. 275
    1
      Marlin/Marlin_main.cpp

+ 2
- 1
Marlin/Configuration.h View File

@@ -375,7 +375,8 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
375 375
 #define Z_MAX_LENGTH (Z_MAX_POS - Z_MIN_POS)
376 376
 //============================= Bed Auto Leveling ===========================
377 377
 
378
-//#define ENABLE_AUTO_BED_LEVELING // Delete the comment to enable (remove // at the start of the line)
378
+#define ENABLE_AUTO_BED_LEVELING // Delete the comment to enable (remove // at the start of the line)
379
+#define Z_PROBE_REPEATABILITY_TEST  // Delete the comment to enable (remove // at the start of the line)
379 380
 
380 381
 #ifdef ENABLE_AUTO_BED_LEVELING
381 382
 

+ 275
- 1
Marlin/Marlin_main.cpp View File

@@ -894,7 +894,7 @@ static void set_bed_level_equation_lsq(double *plane_equation_coefficients)
894 894
     current_position[Y_AXIS] = corrected_position.y;
895 895
     current_position[Z_AXIS] = corrected_position.z;
896 896
 
897
-    // but the bed at 0 so we don't go below it.
897
+    // put the bed at 0 so we don't go below it.
898 898
     current_position[Z_AXIS] = zprobe_zoffset; // in the lsq we reach here after raising the extruder due to the loop structure
899 899
 
900 900
     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()
1862 1862
         }
1863 1863
       }
1864 1864
      break;
1865
+
1866
+// M48 Z-Probe repeatability measurement function.
1867
+//
1868
+// 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>
1869
+//	
1870
+// This function assumes the bed has been homed.  Specificaly, that a G28 command
1871
+// as been issued prior to invoking the M48 Z-Probe repeatability measurement function.
1872
+// Any information generated by a prior G29 Bed leveling command will be lost and need to be
1873
+// regenerated.
1874
+//
1875
+// The number of samples will default to 10 if not specified.  You can use upper or lower case
1876
+// letters for any of the options EXCEPT n.  n must be in lower case because Marlin uses a capital
1877
+// N for its communication protocol and will get horribly confused if you send it a capital N.
1878
+//
1879
+
1880
+#ifdef ENABLE_AUTO_BED_LEVELING
1881
+#ifdef Z_PROBE_REPEATABILITY_TEST 
1882
+
1883
+    case 48: // M48 Z-Probe repeatability
1884
+        {
1885
+            #if Z_MIN_PIN == -1
1886
+            #error "You must have a Z_MIN endstop in order to enable calculation of Z-Probe repeatability."
1887
+            #endif
1888
+
1889
+	double sum=0.0; 
1890
+	double mean=0.0; 
1891
+	double sigma=0.0;
1892
+	double sample_set[50];
1893
+	int verbose_level=1, n=0, j, n_samples = 10, n_legs=0, engage_probe_for_each_reading=0 ;
1894
+	double X_current, Y_current, Z_current;
1895
+	double X_probe_location, Y_probe_location, Z_start_location, ext_position;
1896
+	
1897
+	if (code_seen('V') || code_seen('v')) {
1898
+        	verbose_level = code_value();
1899
+		if (verbose_level<0 || verbose_level>4 ) {
1900
+			SERIAL_PROTOCOLPGM("?Verbose Level not plausable.\n");
1901
+			goto Sigma_Exit;
1902
+		}
1903
+	}
1904
+
1905
+	if (verbose_level > 0)   {
1906
+		SERIAL_PROTOCOLPGM("M48 Z-Probe Repeatability test.   Version 2.00\n");
1907
+		SERIAL_PROTOCOLPGM("Full support at: http://3dprintboard.com/forum.php\n");
1908
+	}
1909
+
1910
+	if (code_seen('n')) {
1911
+        	n_samples = code_value();
1912
+		if (n_samples<4 || n_samples>50 ) {
1913
+			SERIAL_PROTOCOLPGM("?Specified sample size not plausable.\n");
1914
+			goto Sigma_Exit;
1915
+		}
1916
+	}
1917
+
1918
+	X_current = X_probe_location = st_get_position_mm(X_AXIS);
1919
+	Y_current = Y_probe_location = st_get_position_mm(Y_AXIS);
1920
+	Z_current = st_get_position_mm(Z_AXIS);
1921
+	Z_start_location = st_get_position_mm(Z_AXIS) + Z_RAISE_BEFORE_PROBING;
1922
+	ext_position	 = st_get_position_mm(E_AXIS);
1923
+
1924
+	if (code_seen('E') || code_seen('e') ) 
1925
+		engage_probe_for_each_reading++;
1926
+
1927
+	if (code_seen('X') || code_seen('x') ) {
1928
+        	X_probe_location = code_value() -  X_PROBE_OFFSET_FROM_EXTRUDER;
1929
+		if (X_probe_location<X_MIN_POS || X_probe_location>X_MAX_POS ) {
1930
+			SERIAL_PROTOCOLPGM("?Specified X position out of range.\n");
1931
+			goto Sigma_Exit;
1932
+		}
1933
+	}
1934
+
1935
+	if (code_seen('Y') || code_seen('y') ) {
1936
+        	Y_probe_location = code_value() -  Y_PROBE_OFFSET_FROM_EXTRUDER;
1937
+		if (Y_probe_location<Y_MIN_POS || Y_probe_location>Y_MAX_POS ) {
1938
+			SERIAL_PROTOCOLPGM("?Specified Y position out of range.\n");
1939
+			goto Sigma_Exit;
1940
+		}
1941
+	}
1942
+
1943
+	if (code_seen('L') || code_seen('l') ) {
1944
+        	n_legs = code_value();
1945
+		if ( n_legs==1 ) 
1946
+			n_legs = 2;
1947
+		if ( n_legs<0 || n_legs>15 ) {
1948
+			SERIAL_PROTOCOLPGM("?Specified number of legs in movement not plausable.\n");
1949
+			goto Sigma_Exit;
1950
+		}
1951
+	}
1952
+
1953
+//
1954
+// Do all the preliminary setup work.   First raise the probe.
1955
+//
1956
+
1957
+        st_synchronize();
1958
+        plan_bed_level_matrix.set_to_identity();
1959
+	plan_buffer_line( X_current, Y_current, Z_start_location,
1960
+			ext_position,
1961
+    			homing_feedrate[Z_AXIS]/60,
1962
+			active_extruder);
1963
+        st_synchronize();
1964
+
1965
+//
1966
+// Now get everything to the specified probe point So we can safely do a probe to
1967
+// get us close to the bed.  If the Z-Axis is far from the bed, we don't want to 
1968
+// use that as a starting point for each probe.
1969
+//
1970
+	if (verbose_level > 2) 
1971
+		SERIAL_PROTOCOL("Positioning probe for the test.\n");
1972
+
1973
+	plan_buffer_line( X_probe_location, Y_probe_location, Z_start_location,
1974
+			ext_position,
1975
+    			homing_feedrate[X_AXIS]/60,
1976
+			active_extruder);
1977
+        st_synchronize();
1978
+
1979
+	current_position[X_AXIS] = X_current = st_get_position_mm(X_AXIS);
1980
+	current_position[Y_AXIS] = Y_current = st_get_position_mm(Y_AXIS);
1981
+	current_position[Z_AXIS] = Z_current = st_get_position_mm(Z_AXIS);
1982
+	current_position[E_AXIS] = ext_position = st_get_position_mm(E_AXIS);
1983
+
1984
+// 
1985
+// OK, do the inital probe to get us close to the bed.
1986
+// Then retrace the right amount and use that in subsequent probes
1987
+//
1988
+
1989
+        engage_z_probe();	
1990
+
1991
+	setup_for_endstop_move();
1992
+	run_z_probe();
1993
+
1994
+	current_position[Z_AXIS] = Z_current = st_get_position_mm(Z_AXIS);
1995
+	Z_start_location = st_get_position_mm(Z_AXIS) + Z_RAISE_BEFORE_PROBING;
1996
+
1997
+	plan_buffer_line( X_probe_location, Y_probe_location, Z_start_location,
1998
+			ext_position,
1999
+    			homing_feedrate[X_AXIS]/60,
2000
+			active_extruder);
2001
+        st_synchronize();
2002
+	current_position[Z_AXIS] = Z_current = st_get_position_mm(Z_AXIS);
2003
+
2004
+	if (engage_probe_for_each_reading)
2005
+        	retract_z_probe();
2006
+
2007
+        for( n=0; n<n_samples; n++) {
2008
+
2009
+		do_blocking_move_to( X_probe_location, Y_probe_location, Z_start_location); // Make sure we are at the probe location
2010
+
2011
+		if ( n_legs)  {
2012
+		double radius=0.0, theta=0.0, x_sweep, y_sweep;
2013
+		int rotational_direction, l;
2014
+
2015
+			rotational_direction = (unsigned long) millis() & 0x0001;			// clockwise or counter clockwise
2016
+			radius = (unsigned long) millis() % (long) (X_MAX_LENGTH/4); 			// limit how far out to go 
2017
+			theta = (float) ((unsigned long) millis() % (long) 360) / (360./(2*3.1415926));	// turn into radians
2018
+
2019
+//SERIAL_ECHOPAIR("starting radius: ",radius);
2020
+//SERIAL_ECHOPAIR("   theta: ",theta);
2021
+//SERIAL_ECHOPAIR("   direction: ",rotational_direction);
2022
+//SERIAL_PROTOCOLLNPGM("");
2023
+
2024
+			for( l=0; l<n_legs-1; l++) {
2025
+				if (rotational_direction==1)
2026
+					theta += (float) ((unsigned long) millis() % (long) 20) / (360.0/(2*3.1415926)); // turn into radians
2027
+				else
2028
+					theta -= (float) ((unsigned long) millis() % (long) 20) / (360.0/(2*3.1415926)); // turn into radians
2029
+
2030
+				radius += (float) ( ((long) ((unsigned long) millis() % (long) 10)) - 5);
2031
+				if ( radius<0.0 )
2032
+					radius = -radius;
2033
+
2034
+				X_current = X_probe_location + cos(theta) * radius;
2035
+				Y_current = Y_probe_location + sin(theta) * radius;
2036
+
2037
+				if ( X_current<X_MIN_POS)		// Make sure our X & Y are sane
2038
+					 X_current = X_MIN_POS;
2039
+				if ( X_current>X_MAX_POS)
2040
+					 X_current = X_MAX_POS;
2041
+
2042
+				if ( Y_current<Y_MIN_POS)		// Make sure our X & Y are sane
2043
+					 Y_current = Y_MIN_POS;
2044
+				if ( Y_current>Y_MAX_POS)
2045
+					 Y_current = Y_MAX_POS;
2046
+
2047
+				if (verbose_level>3 ) {
2048
+					SERIAL_ECHOPAIR("x: ", X_current);
2049
+					SERIAL_ECHOPAIR("y: ", Y_current);
2050
+					SERIAL_PROTOCOLLNPGM("");
2051
+				}
2052
+
2053
+				do_blocking_move_to( X_current, Y_current, Z_current );
2054
+			}
2055
+			do_blocking_move_to( X_probe_location, Y_probe_location, Z_start_location); // Go back to the probe location
2056
+		}
2057
+
2058
+		if (engage_probe_for_each_reading)  {
2059
+        		engage_z_probe();	
2060
+          		delay(1000);
2061
+		}
2062
+
2063
+		setup_for_endstop_move();
2064
+                run_z_probe();
2065
+
2066
+		sample_set[n] = current_position[Z_AXIS];
2067
+
2068
+//
2069
+// Get the current mean for the data points we have so far
2070
+//
2071
+		sum=0.0; 
2072
+		for( j=0; j<=n; j++) {
2073
+			sum = sum + sample_set[j];
2074
+		}
2075
+		mean = sum / (double (n+1));
2076
+//
2077
+// Now, use that mean to calculate the standard deviation for the
2078
+// data points we have so far
2079
+//
2080
+
2081
+		sum=0.0; 
2082
+		for( j=0; j<=n; j++) {
2083
+			sum = sum + (sample_set[j]-mean) * (sample_set[j]-mean);
2084
+		}
2085
+		sigma = sqrt( sum / (double (n+1)) );
2086
+
2087
+		if (verbose_level > 1) {
2088
+			SERIAL_PROTOCOL(n+1);
2089
+			SERIAL_PROTOCOL(" of ");
2090
+			SERIAL_PROTOCOL(n_samples);
2091
+			SERIAL_PROTOCOLPGM("   z: ");
2092
+			SERIAL_PROTOCOL_F(current_position[Z_AXIS], 6);
2093
+		}
2094
+
2095
+		if (verbose_level > 2) {
2096
+			SERIAL_PROTOCOL(" mean: ");
2097
+			SERIAL_PROTOCOL_F(mean,6);
2098
+
2099
+			SERIAL_PROTOCOL("   sigma: ");
2100
+			SERIAL_PROTOCOL_F(sigma,6);
2101
+		}
2102
+
2103
+		if (verbose_level > 0) 
2104
+			SERIAL_PROTOCOLPGM("\n");
2105
+
2106
+		plan_buffer_line( X_probe_location, Y_probe_location, Z_start_location, 
2107
+				  current_position[E_AXIS], homing_feedrate[Z_AXIS]/60, active_extruder);
2108
+        	st_synchronize();
2109
+
2110
+		if (engage_probe_for_each_reading)  {
2111
+        		retract_z_probe();	
2112
+          		delay(1000);
2113
+		}
2114
+	}
2115
+
2116
+        retract_z_probe();
2117
+	delay(1000);
2118
+
2119
+        clean_up_after_endstop_move();
2120
+
2121
+//      enable_endstops(true);
2122
+
2123
+	if (verbose_level > 0) {
2124
+		SERIAL_PROTOCOLPGM("Mean: ");
2125
+		SERIAL_PROTOCOL_F(mean, 6);
2126
+		SERIAL_PROTOCOLPGM("\n");
2127
+	}
2128
+
2129
+SERIAL_PROTOCOLPGM("Standard Deviation: ");
2130
+SERIAL_PROTOCOL_F(sigma, 6);
2131
+SERIAL_PROTOCOLPGM("\n\n");
2132
+
2133
+Sigma_Exit:
2134
+        break;
2135
+	}
2136
+#endif		// Z_PROBE_REPEATABILITY_TEST 
2137
+#endif		// ENABLE_AUTO_BED_LEVELING
2138
+
1865 2139
     case 104: // M104
1866 2140
       if(setTargetedHotend(104)){
1867 2141
         break;

Loading…
Cancel
Save