Browse Source

Map clean up of UBL

UBL's maps are cleaner.   And with a 1 value, G29 O 1  will generate a
map suitable to be Cut & Pasted into Excel so a Suface Map can be
generated.
Roxy-3D 7 years ago
parent
commit
9d3ac66f73
3 changed files with 135 additions and 79 deletions
  1. 2
    2
      Marlin/UBL.h
  2. 67
    58
      Marlin/UBL_Bed_Leveling.cpp
  3. 66
    19
      Marlin/UBL_G29.cpp

+ 2
- 2
Marlin/UBL.h View File

@@ -42,13 +42,13 @@
42 42
     bool axis_unhomed_error(bool, bool, bool);
43 43
     void dump(char * const str, const float &f);
44 44
     bool ubl_lcd_clicked();
45
-    void probe_entire_mesh(const float&, const float&, const bool, const bool);
45
+    void probe_entire_mesh(const float&, const float&, const bool, const bool, const bool);
46 46
     void debug_current_and_destination(char *title);
47 47
     void ubl_line_to_destination(const float&, const float&, const float&, const float&, const float&, uint8_t);
48 48
     void manually_probe_remaining_mesh(const float&, const float&, const float&, const float&, const bool);
49 49
     vector_3 tilt_mesh_based_on_3pts(const float&, const float&, const float&);
50 50
     float measure_business_card_thickness(const float&);
51
-    mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType, const float&, const float&, const bool, unsigned int[16]);
51
+    mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType, const float&, const float&, const bool, unsigned int[16], bool);
52 52
     void find_mean_mesh_height();
53 53
     void shift_mesh_height();
54 54
     bool g29_parameter_parsing();

+ 67
- 58
Marlin/UBL_Bed_Leveling.cpp View File

@@ -166,32 +166,34 @@
166 166
     int8_t i, j;
167 167
     UNUSED(map_type);
168 168
 
169
-    SERIAL_PROTOCOLLNPGM("\nBed Topography Report:\n");
169
+    if (map_type==0) {
170
+      SERIAL_PROTOCOLLNPGM("\nBed Topography Report:\n");
170 171
 
171
-    SERIAL_ECHOPAIR("(", 0);
172
-    SERIAL_ECHOPAIR(", ", UBL_MESH_NUM_Y_POINTS - 1);
173
-    SERIAL_ECHOPGM(")    ");
172
+      SERIAL_ECHOPAIR("(", 0);
173
+      SERIAL_ECHOPAIR(", ", UBL_MESH_NUM_Y_POINTS - 1);
174
+      SERIAL_ECHOPGM(")    ");
175
+    }
174 176
 
175 177
     current_xi = ubl.get_cell_index_x(current_position[X_AXIS] + (MESH_X_DIST) / 2.0);
176 178
     current_yi = ubl.get_cell_index_y(current_position[Y_AXIS] + (MESH_Y_DIST) / 2.0);
177 179
 
178
-    for (i = 0; i < UBL_MESH_NUM_X_POINTS - 1; i++) {
179
-      SERIAL_ECHOPGM("            ");
180
-      #if TX_BUFFER_SIZE>0
181
-        MYSERIAL.flushTX();
182
-      #endif
183
-      delay(15);
184
-    }
185
-
186
-    SERIAL_ECHOPAIR("(", UBL_MESH_NUM_X_POINTS - 1);
187
-    SERIAL_ECHOPAIR(",", UBL_MESH_NUM_Y_POINTS - 1);
188
-    SERIAL_ECHOLNPGM(")");
189
-
190
-    //  if (map_type || 1) {
180
+    if (map_type==0) {
181
+      for (i = 0; i < UBL_MESH_NUM_X_POINTS - 1; i++) {
182
+        SERIAL_ECHOPGM("            ");
183
+        #if TX_BUFFER_SIZE>0
184
+          MYSERIAL.flushTX();
185
+        #endif
186
+        delay(15);
187
+      }
188
+      
189
+      SERIAL_ECHOPAIR("(", UBL_MESH_NUM_X_POINTS - 1);
190
+      SERIAL_ECHOPAIR(",", UBL_MESH_NUM_Y_POINTS - 1);
191
+      SERIAL_ECHOLNPGM(")");
191 192
 
192 193
       SERIAL_ECHOPAIR("(", UBL_MESH_MIN_X);
193 194
       SERIAL_ECHOPAIR(",", UBL_MESH_MAX_Y);
194 195
       SERIAL_CHAR(')');
196
+      delay(15);
195 197
 
196 198
       for (i = 0; i < UBL_MESH_NUM_X_POINTS - 1; i++) {
197 199
         SERIAL_ECHOPGM("            ");
@@ -204,75 +206,82 @@
204 206
       SERIAL_ECHOPAIR("(", UBL_MESH_MAX_X);
205 207
       SERIAL_ECHOPAIR(",", UBL_MESH_MAX_Y);
206 208
       SERIAL_ECHOLNPGM(")");
207
-
208
-    //  }
209
+      delay(15);
210
+    }
209 211
 
210 212
     for (j = UBL_MESH_NUM_Y_POINTS - 1; j >= 0; j--) {
211 213
       for (i = 0; i < UBL_MESH_NUM_X_POINTS; i++) {
212 214
         f = z_values[i][j];
213 215
 
214 216
         // is the nozzle here?  if so, mark the number
215
-        SERIAL_CHAR(i == current_xi && j == current_yi ? '[' : ' ');
217
+        if (map_type==0) 
218
+          SERIAL_CHAR(i == current_xi && j == current_yi ? '[' : ' ');
216 219
 
217 220
         if (isnan(f))
218
-          SERIAL_PROTOCOLPGM("    .    ");
221
+          if (map_type==0) {
222
+            SERIAL_PROTOCOLPGM("    .    ");
223
+          } else 
224
+            SERIAL_PROTOCOLPGM("NAN");
219 225
         else {
220 226
           // if we don't do this, the columns won't line up nicely
221
-          if (f >= 0.0) SERIAL_CHAR(' ');
227
+          if (f>=0.0 && map_type==0) SERIAL_CHAR(' ');
222 228
           SERIAL_PROTOCOL_F(f, 3);
223 229
           idle();
224 230
         }
231
+        if (map_type!=0 && i<UBL_MESH_NUM_X_POINTS-1) 
232
+         SERIAL_PROTOCOLPGM(",");
233
+
225 234
         #if TX_BUFFER_SIZE>0
226 235
           MYSERIAL.flushTX();
227 236
         #endif
228 237
         delay(15);
229
-        if (i == current_xi && j == current_yi) // is the nozzle here? if so, finish marking the number
230
-          SERIAL_CHAR(']');
231
-        else
232
-          SERIAL_PROTOCOL("  ");
233
-
234
-        SERIAL_CHAR(' ');
238
+        if (map_type==0) {
239
+          if (i == current_xi && j == current_yi) // is the nozzle here? if so, finish marking the number
240
+            SERIAL_CHAR(']');
241
+          else
242
+            SERIAL_PROTOCOL("  ");
243
+          SERIAL_CHAR(' ');
244
+        }
235 245
       }
236 246
       SERIAL_EOL;
237
-      if (j) { // we want the (0,0) up tight against the block of numbers
247
+      if (j && map_type==0) { // we want the (0,0) up tight against the block of numbers
238 248
         SERIAL_CHAR(' ');
239 249
         SERIAL_EOL;
240 250
       }
241 251
     }
242 252
 
243
-    //  if (map_type) {
244
-    SERIAL_ECHOPAIR("(", int(UBL_MESH_MIN_X));
245
-    SERIAL_ECHOPAIR(",", int(UBL_MESH_MIN_Y));
246
-    SERIAL_ECHOPGM(")    ");
253
+    if (map_type==0) {
254
+      SERIAL_ECHOPAIR("(", int(UBL_MESH_MIN_X));
255
+      SERIAL_ECHOPAIR(",", int(UBL_MESH_MIN_Y));
256
+      SERIAL_ECHOPGM(")    ");
247 257
 
248
-    for (i = 0; i < UBL_MESH_NUM_X_POINTS - 1; i++)  {
249
-      SERIAL_ECHOPGM("            ");
250
-      #if TX_BUFFER_SIZE>0
251
-        MYSERIAL.flushTX();
252
-      #endif
253
-      delay(15);
254
-    }
255
-
256
-    SERIAL_ECHOPAIR("(", int(UBL_MESH_MAX_X));
257
-    SERIAL_ECHOPAIR(",", int(UBL_MESH_MIN_Y));
258
-    SERIAL_CHAR(')');
259
-    SERIAL_EOL;
258
+      for (i = 0; i < UBL_MESH_NUM_X_POINTS - 1; i++)  {
259
+        SERIAL_ECHOPGM("            ");
260
+        #if TX_BUFFER_SIZE>0
261
+          MYSERIAL.flushTX();
262
+        #endif
263
+        delay(15);
264
+      }
265
+      SERIAL_ECHOPAIR("(", int(UBL_MESH_MAX_X));
266
+      SERIAL_ECHOPAIR(",", int(UBL_MESH_MIN_Y));
267
+      SERIAL_CHAR(')');
268
+      SERIAL_EOL;
260 269
 
261
-    SERIAL_ECHOPAIR("(", 0);
262
-    SERIAL_ECHOPAIR(",", 0);
263
-    SERIAL_ECHOPGM(")       ");
270
+      SERIAL_ECHOPAIR("(", 0);
271
+      SERIAL_ECHOPAIR(",", 0);
272
+      SERIAL_ECHOPGM(")       ");
264 273
 
265
-    for (i = 0; i < UBL_MESH_NUM_X_POINTS - 1; i++) {
266
-      SERIAL_ECHOPGM("            ");
267
-      #if TX_BUFFER_SIZE>0
268
-        MYSERIAL.flushTX();
269
-      #endif
270
-      delay(15);
274
+      for (i = 0; i < UBL_MESH_NUM_X_POINTS - 1; i++) {
275
+        SERIAL_ECHOPGM("            ");
276
+        #if TX_BUFFER_SIZE>0
277
+          MYSERIAL.flushTX();
278
+        #endif
279
+        delay(15);
280
+      }
281
+      SERIAL_ECHOPAIR("(", UBL_MESH_NUM_X_POINTS-1);
282
+      SERIAL_ECHOPAIR(",", 0);
283
+      SERIAL_ECHOLNPGM(")");
271 284
     }
272
-
273
-    SERIAL_ECHOPAIR("(", UBL_MESH_NUM_X_POINTS-1);
274
-    SERIAL_ECHOPAIR(",", 0);
275
-    SERIAL_ECHOLNPGM(")");
276 285
   }
277 286
 
278 287
   bool unified_bed_leveling::sanity_check() {

+ 66
- 19
Marlin/UBL_G29.cpp View File

@@ -125,7 +125,10 @@
125 125
    *   O     Map   *    Display the Mesh Map Topology.
126 126
    *                    The parameter can be specified alone (ie. G29 O) or in combination with many of the
127 127
    *                    other commands. The Mesh Map option works with all of the Phase
128
-   *                    commands (ie. G29 P4 R 5 X 50 Y100 C -.1 O)
128
+   *                    commands (ie. G29 P4 R 5 X 50 Y100 C -.1 O)  The Map parameter can also of a Map Type
129
+   *                    specified.  A map type of 0 is the default is user readable.   A map type of 1 can
130
+   *                    be specified and is suitable to Cut & Paste into Excel to allow graphing of the user's
131
+   *                    mesh.
129 132
    *
130 133
    *   N    No Home     G29 normally insists that a G28 has been performed. You can over rule this with an
131 134
    *                    N option. In general, you should not do this. This can only be done safely with
@@ -250,6 +253,10 @@
250 253
    *
251 254
    *   T     3-Point    Perform a 3 Point Bed Leveling on the current Mesh
252 255
    *
256
+   *   U     Unlevel    Perform a probe of the outer perimeter to assist in physically leveling unlevel beds.
257
+   *                    Only used for G29 P1 O U   It will speed up the probing of the edge of the bed.  This
258
+   *                    is useful when the entire bed does not need to be probed because it will be adjusted.
259
+   *
253 260
    *   W     What?      Display valuable data the Unified Bed Leveling System knows.
254 261
    *
255 262
    *   X #   *      *   X Location for this line of commands
@@ -297,7 +304,7 @@
297 304
 
298 305
   // The simple parameter flags and values are 'static' so parameter parsing can be in a support routine.
299 306
   static int g29_verbose_level = 0, phase_value = -1, repetition_cnt = 1,
300
-             storage_slot = 0, test_pattern = 0;
307
+             storage_slot = 0, map_type = 0, test_pattern = 0, unlevel_value = -1;
301 308
   static bool repeat_flag = UBL_OK, c_flag = false, x_flag = UBL_OK, y_flag = UBL_OK, statistics_flag = UBL_OK, business_card_mode = false;
302 309
   static float x_pos = 0.0, y_pos = 0.0, height_value = 5.0, measured_z, card_thickness = 0.0, constant = 0.0;
303 310
 
@@ -331,7 +338,7 @@
331 338
     if (code_seen('I')) {
332 339
       repetition_cnt = code_has_value() ? code_value_int() : 1;
333 340
       while (repetition_cnt--) {
334
-        const mesh_index_pair location = find_closest_mesh_point_of_type(REAL, x_pos, y_pos, 0, NULL);  // The '0' says we want to use the nozzle's position
341
+        const mesh_index_pair location = find_closest_mesh_point_of_type(REAL, x_pos, y_pos, 0, NULL, false);  // The '0' says we want to use the nozzle's position
335 342
         if (location.x_index < 0) {
336 343
           SERIAL_PROTOCOLLNPGM("Entire Mesh invalidated.\n");
337 344
           break;            // No more invalid Mesh Points to populate
@@ -381,6 +388,16 @@
381 388
       }
382 389
     }
383 390
 
391
+/*
392
+    if (code_seen('U')) {
393
+      unlevel_value = code_value_int();
394
+//    if (unlevel_value < 0 || unlevel_value > 7) {
395
+//      SERIAL_PROTOCOLLNPGM("Invalid Unlevel value. (0-4)\n");
396
+//      return;
397
+//    }
398
+    }
399
+*/
400
+
384 401
     if (code_seen('P')) {
385 402
       phase_value = code_value_int();
386 403
       if (phase_value < 0 || phase_value > 7) {
@@ -410,7 +427,7 @@
410 427
             SERIAL_PROTOCOLLNPGM(")\n");
411 428
           }
412 429
           probe_entire_mesh(x_pos + X_PROBE_OFFSET_FROM_EXTRUDER, y_pos + Y_PROBE_OFFSET_FROM_EXTRUDER,
413
-                            code_seen('O') || code_seen('M'), code_seen('E'));
430
+                            code_seen('O') || code_seen('M'), code_seen('E'), code_seen('U'));
414 431
           break;
415 432
         //
416 433
         // Manually Probe Mesh in areas that can not be reached by the probe
@@ -455,7 +472,7 @@
455 472
           // If no repetition is specified, do the whole Mesh
456 473
           if (!repeat_flag) repetition_cnt = 9999;
457 474
           while (repetition_cnt--) {
458
-            const mesh_index_pair location = find_closest_mesh_point_of_type(INVALID, x_pos, y_pos, 0, NULL); // The '0' says we want to use the nozzle's position
475
+            const mesh_index_pair location = find_closest_mesh_point_of_type(INVALID, x_pos, y_pos, 0, NULL, false); // The '0' says we want to use the nozzle's position
459 476
             if (location.x_index < 0) break; // No more invalid Mesh Points to populate
460 477
             z_values[location.x_index][location.y_index] = height_value;
461 478
           }
@@ -700,7 +717,7 @@
700 717
    * Probe all invalidated locations of the mesh that can be reached by the probe.
701 718
    * This attempts to fill in locations closest to the nozzle's start location first.
702 719
    */
703
-  void probe_entire_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map, const bool stow_probe) {
720
+  void probe_entire_mesh(const float &lx, const float &ly, const bool do_ubl_mesh_map, const bool stow_probe, bool do_furthest) {
704 721
     mesh_index_pair location;
705 722
 
706 723
     ubl_has_control_of_lcd_panel++;
@@ -721,7 +738,7 @@
721 738
         return;
722 739
       }
723 740
 
724
-      location = find_closest_mesh_point_of_type(INVALID, lx, ly, 1, NULL);  // the '1' says we want the location to be relative to the probe
741
+      location = find_closest_mesh_point_of_type(INVALID, lx, ly, 1, NULL, do_furthest );  // the '1' says we want the location to be relative to the probe
725 742
       if (location.x_index >= 0 && location.y_index >= 0) {
726 743
         const float xProbe = ubl.map_x_index_to_bed_location(location.x_index),
727 744
                     yProbe = ubl.map_y_index_to_bed_location(location.y_index);
@@ -734,7 +751,7 @@
734 751
         z_values[location.x_index][location.y_index] = measured_z + Z_PROBE_OFFSET_FROM_EXTRUDER;
735 752
       }
736 753
 
737
-      if (do_ubl_mesh_map) ubl.display_map(1);
754
+      if (do_ubl_mesh_map) ubl.display_map(map_type);
738 755
 
739 756
     } while (location.x_index >= 0 && location.y_index >= 0);
740 757
 
@@ -862,9 +879,9 @@
862 879
     float last_x = -9999.99, last_y = -9999.99;
863 880
     mesh_index_pair location;
864 881
     do {
865
-      if (do_ubl_mesh_map) ubl.display_map(1);
882
+      if (do_ubl_mesh_map) ubl.display_map(map_type);
866 883
 
867
-      location = find_closest_mesh_point_of_type(INVALID, lx, ly, 0, NULL); // The '0' says we want to use the nozzle's position
884
+      location = find_closest_mesh_point_of_type(INVALID, lx, ly, 0, NULL, false); // The '0' says we want to use the nozzle's position
868 885
       // It doesn't matter if the probe can not reach the
869 886
       // NAN location. This is a manual probe.
870 887
       if (location.x_index < 0 && location.y_index < 0) continue;
@@ -923,7 +940,7 @@
923 940
       }
924 941
     } while (location.x_index >= 0 && location.y_index >= 0);
925 942
 
926
-    if (do_ubl_mesh_map) ubl.display_map(1);
943
+    if (do_ubl_mesh_map) ubl.display_map(map_type);
927 944
 
928 945
     LEAVE:
929 946
     restore_ubl_active_state_and_leave();
@@ -941,6 +958,7 @@
941 958
     x_pos = current_position[X_AXIS];
942 959
     y_pos = current_position[Y_AXIS];
943 960
     x_flag = y_flag = repeat_flag = false;
961
+    map_type = 0;
944 962
     constant = 0.0;
945 963
     repetition_cnt = 1;
946 964
 
@@ -1008,6 +1026,23 @@
1008 1026
         return UBL_ERR;
1009 1027
       }
1010 1028
     }
1029
+
1030
+    if (code_seen('O')) {     // Check if a map type was specified
1031
+      map_type = code_value_int() ? code_has_value() : 0; 
1032
+      if ( map_type<0 || map_type>1) {
1033
+        SERIAL_PROTOCOLLNPGM("Invalid map type.\n");
1034
+        return UBL_ERR;
1035
+      }
1036
+    }
1037
+
1038
+    if (code_seen('M')) {     // Check if a map type was specified
1039
+      map_type = code_value_int() ? code_has_value() : 0; 
1040
+      if ( map_type<0 || map_type>1) {
1041
+        SERIAL_PROTOCOLLNPGM("Invalid map type.\n");
1042
+        return UBL_ERR;
1043
+      }
1044
+    }
1045
+
1011 1046
     return UBL_OK;
1012 1047
   }
1013 1048
 
@@ -1217,9 +1252,9 @@
1217 1252
         z_values[x][y] = z_values[x][y] - tmp_z_values[x][y];
1218 1253
   }
1219 1254
 
1220
-  mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType type, const float &lx, const float &ly, const bool probe_as_reference, unsigned int bits[16]) {
1221
-    int i, j;
1222
-    float closest = 99999.99;
1255
+  mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType type, const float &lx, const float &ly, const bool probe_as_reference, unsigned int bits[16], bool far_flag) {
1256
+    int i, j, k, l;
1257
+    float distance, closest = far_flag ? -99999.99 : 99999.99;
1223 1258
     mesh_index_pair return_val;
1224 1259
 
1225 1260
     return_val.x_index = return_val.y_index = -1;
@@ -1254,9 +1289,21 @@
1254 1289
 
1255 1290
           // We can get to it. Let's see if it is the closest location to the nozzle.
1256 1291
           // Add in a weighting factor that considers the current location of the nozzle.
1257
-          const float distance = HYPOT(px - mx, py - my) + HYPOT(current_x - mx, current_y - my) * 0.01;
1258 1292
 
1259
-          if (distance < closest) {
1293
+          distance = HYPOT(px - mx, py - my) + HYPOT(current_x - mx, current_y - my) * 0.1;
1294
+
1295
+	  if (far_flag) {                                    // If doing the far_flag action, we want to be as far as possible
1296
+            for (k = 0; k < UBL_MESH_NUM_X_POINTS; k++) {    // from the starting point and from any other probed points.  We
1297
+              for (l = 0; j < UBL_MESH_NUM_Y_POINTS; l++) {  // want the next point spread out and filling in any blank spaces
1298
+                if ( !isnan(z_values[k][l])) {               // in the mesh.   So we add in some of the distance to every probed 
1299
+                  distance += (i-k)*(i-k)*MESH_X_DIST*.05;   // point we can find.
1300
+                  distance += (j-l)*(j-l)*MESH_Y_DIST*.05;
1301
+		}
1302
+              }
1303
+	    }
1304
+	  }
1305
+
1306
+          if ( (!far_flag&&(distance < closest)) || (far_flag&&(distance > closest)) ) {  // if far_flag, look for furthest away point
1260 1307
             closest = distance;       // We found a closer location with
1261 1308
             return_val.x_index = i;   // the specified type of mesh value.
1262 1309
             return_val.y_index = j;
@@ -1283,9 +1330,9 @@
1283 1330
     do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);
1284 1331
     do_blocking_move_to_xy(lx, ly);
1285 1332
     do {
1286
-      if (do_ubl_mesh_map) ubl.display_map(1);
1333
+      if (do_ubl_mesh_map) ubl.display_map(map_type);
1287 1334
 
1288
-      location = find_closest_mesh_point_of_type( SET_IN_BITMAP, lx,  ly, 0, not_done); // The '0' says we want to use the nozzle's position
1335
+      location = find_closest_mesh_point_of_type( SET_IN_BITMAP, lx,  ly, 0, not_done, false); // The '0' says we want to use the nozzle's position
1289 1336
                                                                                               // It doesn't matter if the probe can not reach this
1290 1337
                                                                                               // location. This is a manual edit of the Mesh Point.
1291 1338
       if (location.x_index < 0 && location.y_index < 0) continue; // abort if we can't find any more points.
@@ -1356,7 +1403,7 @@
1356 1403
 
1357 1404
     ubl_has_control_of_lcd_panel = false;
1358 1405
 
1359
-    if (do_ubl_mesh_map) ubl.display_map(1);
1406
+    if (do_ubl_mesh_map) ubl.display_map(map_type);
1360 1407
     restore_ubl_active_state_and_leave();
1361 1408
     do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);
1362 1409
 

Loading…
Cancel
Save