Browse Source

Convert UBL mesh tilting to all use the same algorithm (#9204)

A number of regressions were patched also. The UBL G29 P2 and P4 Press and Hold had stopped working. It is very possible this is broken in the bugfix_v1.1.x branch also.

The main purpose of the Pull Request is to get the 3-Point mesh tilting to use the LSF algorithm just like the grid based mesh tilt. This simplifies the logic and reduces the code size some what. But the real reason to do it is the 3-Point case can be solved exactly. And by feeding these numbers into the LSF algorithm it provides a way to check all that code for 'correctness'.
Roxy-3D 7 years ago
parent
commit
f5f1b069ad
No account linked to committer's email address

+ 2
- 2
Marlin/src/config/examples/gCreate/gMax1.5+/Configuration.h View File

@@ -1061,8 +1061,8 @@
1061 1061
 #define Z_SAFE_HOMING
1062 1062
 
1063 1063
 #if ENABLED(Z_SAFE_HOMING)
1064
-  #define Z_SAFE_HOMING_X_POINT ((X_BED_SIZE) / 2 - 4) // X point for Z homing when homing all axes (G28).
1065
-  #define Z_SAFE_HOMING_Y_POINT ((Y_BED_SIZE) / 2 + 4) // Y point for Z homing when homing all axes (G28).
1064
+  #define Z_SAFE_HOMING_X_POINT ((X_BED_SIZE) / 2 - 8) // X point for Z homing when homing all axes (G28).
1065
+  #define Z_SAFE_HOMING_Y_POINT ((Y_BED_SIZE) / 2 - 4) // Y point for Z homing when homing all axes (G28).
1066 1066
 #endif
1067 1067
 
1068 1068
 // Homing speeds (mm/m)

+ 14
- 14
Marlin/src/feature/Max7219_Debug_LEDs.cpp View File

@@ -237,13 +237,13 @@ void Max7219_init() {
237 237
 
238 238
   for (x = 0; x <= 7; x++)        // Do an aesthetically pleasing pattern to fully test
239 239
     for (y = 0; y <= 7; y++) {    // the Max7219 module and LEDs. First, turn them
240
-      Max7219_LED_On(x, y);       // all on.
240
+      Max7219_LED_On(y, x);       // all on.
241 241
       delay(3);
242 242
     }
243 243
 
244 244
   for (x = 0; x <= 7; x++)        // Now, turn them all off.
245 245
     for (y = 0; y <= 7; y++) {
246
-      Max7219_LED_Off(x, y);
246
+      Max7219_LED_Off(y, x);
247 247
       delay(3);                   // delay() is OK here. Max7219_init() is only called from
248 248
     }                             // setup() and nothing is running yet.
249 249
 
@@ -251,13 +251,13 @@ void Max7219_init() {
251 251
 
252 252
   for (x = 8; x--;)               // Now, do the same thing from the opposite direction
253 253
     for (y = 0; y <= 7; y++) {
254
-      Max7219_LED_On(x, y);
254
+      Max7219_LED_On(y, x);
255 255
       delay(2);
256 256
     }
257 257
 
258 258
   for (x = 8; x--;)
259 259
     for (y = 0; y <= 7; y++) {
260
-      Max7219_LED_Off(x, y);
260
+      Max7219_LED_Off(y, x);
261 261
       delay(2);
262 262
     }
263 263
 }
@@ -295,15 +295,15 @@ void Max7219_idle_tasks() {
295 295
     static int16_t last_head_cnt = 0;
296 296
     if (last_head_cnt != head) {
297 297
       if (last_head_cnt < 8)
298
-        Max7219_LED_Off(last_head_cnt, MAX7219_DEBUG_STEPPER_HEAD);
298
+        Max7219_LED_Off(MAX7219_DEBUG_STEPPER_HEAD, last_head_cnt);
299 299
       else
300
-        Max7219_LED_Off(last_head_cnt - 8, MAX7219_DEBUG_STEPPER_HEAD + 1);
300
+        Max7219_LED_Off(MAX7219_DEBUG_STEPPER_HEAD + 1, last_head_cnt - 8);
301 301
 
302 302
       last_head_cnt = head;
303 303
       if (head < 8)
304
-        Max7219_LED_On(head, MAX7219_DEBUG_STEPPER_HEAD);
304
+        Max7219_LED_On(MAX7219_DEBUG_STEPPER_HEAD, head);
305 305
       else
306
-        Max7219_LED_On(head - 8, MAX7219_DEBUG_STEPPER_HEAD + 1);
306
+        Max7219_LED_On(MAX7219_DEBUG_STEPPER_HEAD + 1, head - 8);
307 307
     }
308 308
   #endif
309 309
 
@@ -311,15 +311,15 @@ void Max7219_idle_tasks() {
311 311
     static int16_t last_tail_cnt = 0;
312 312
     if (last_tail_cnt != tail) {
313 313
       if (last_tail_cnt < 8)
314
-        Max7219_LED_Off(last_tail_cnt, MAX7219_DEBUG_STEPPER_TAIL);
314
+        Max7219_LED_Off(MAX7219_DEBUG_STEPPER_TAIL, last_tail_cnt);
315 315
       else
316
-        Max7219_LED_Off(last_tail_cnt - 8, MAX7219_DEBUG_STEPPER_TAIL + 1);
316
+        Max7219_LED_Off(MAX7219_DEBUG_STEPPER_TAIL + 1, last_tail_cnt - 8);
317 317
 
318 318
       last_tail_cnt = tail;
319 319
       if (tail < 8)
320
-        Max7219_LED_On(tail, MAX7219_DEBUG_STEPPER_TAIL);
320
+        Max7219_LED_On(MAX7219_DEBUG_STEPPER_TAIL, tail);
321 321
       else
322
-        Max7219_LED_On(tail - 8, MAX7219_DEBUG_STEPPER_TAIL + 1);
322
+        Max7219_LED_On(MAX7219_DEBUG_STEPPER_TAIL + 1, tail - 8);
323 323
     }
324 324
   #endif
325 325
 
@@ -336,10 +336,10 @@ void Max7219_idle_tasks() {
336 336
                     en = max(current_depth, last_depth);
337 337
       if (current_depth < last_depth)
338 338
         for (uint8_t i = st; i <= en; i++)   // clear the highest order LEDs
339
-          Max7219_LED_Off(i / 2, MAX7219_DEBUG_STEPPER_QUEUE + (i & 1));
339
+          Max7219_LED_Off(MAX7219_DEBUG_STEPPER_QUEUE + (i & 1), i / 2);
340 340
       else
341 341
         for (uint8_t i = st; i <= en; i++)   // set the LEDs to current depth
342
-          Max7219_LED_On(i / 2, MAX7219_DEBUG_STEPPER_QUEUE + (i & 1));
342
+          Max7219_LED_On(MAX7219_DEBUG_STEPPER_QUEUE + (i & 1), i / 2);
343 343
 
344 344
       last_depth = current_depth;
345 345
     }

+ 2
- 2
Marlin/src/feature/bedlevel/ubl/ubl.h View File

@@ -59,7 +59,7 @@ extern uint8_t ubl_cnt;
59 59
 
60 60
 #if ENABLED(ULTRA_LCD)
61 61
   extern char lcd_status_message[];
62
-  void lcd_quick_feedback();
62
+  void lcd_quick_feedback(const bool clear_buttons);
63 63
 #endif
64 64
 
65 65
 #define MESH_X_DIST (float(MESH_MAX_X - (MESH_MIN_X)) / float(GRID_MAX_POINTS_X - 1))
@@ -85,7 +85,7 @@ class unified_bed_leveling {
85 85
     #if ENABLED(NEWPANEL)
86 86
       static void move_z_with_encoder(const float &multiplier);
87 87
       static float measure_point_with_encoder();
88
-      static float measure_business_card_thickness(const float&);
88
+      static float measure_business_card_thickness(float);
89 89
       static void manually_probe_remaining_mesh(const float&, const float&, const float&, const float&, const bool);
90 90
       static void fine_tune_mesh(const float &rx, const float &ry, const bool do_ubl_mesh_map);
91 91
     #endif

+ 151
- 164
Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp View File

@@ -40,6 +40,8 @@
40 40
   #include "../../../feature/bedlevel/bedlevel.h"
41 41
   #include "../../../libs/least_squares_fit.h"
42 42
 
43
+#include "../../../feature/Max7219_Debug_LEDs.h"
44
+
43 45
   #include <math.h>
44 46
 
45 47
   #define UBL_G29_P31
@@ -98,8 +100,9 @@
98 100
    *   C     Continue   G29 P1 C continues the generation of a partially-constructed Mesh without invalidating
99 101
    *                    previous measurements.
100 102
    *
101
-   *   C     Constant   G29 P2 C specifies a Constant and tells the Manual Probe subsystem to use the current
102
-   *                    location in its search for the closest unmeasured Mesh Point.
103
+   *   C                G29 P2 C tells the Manual Probe subsystem to not use the current nozzle
104
+   *                    location in its search for the closest unmeasured Mesh Point.  Instead, attempt to
105
+   *                    start at one end of the uprobed points and Continue sequentually.
103 106
    *
104 107
    *                    G29 P3 C specifies the Constant for the fill. Otherwise, uses a "reasonable" value.
105 108
    *
@@ -281,9 +284,7 @@
281 284
    *
282 285
    *   Release Notes:
283 286
    *   You MUST do M502, M500 to initialize the storage. Failure to do this will cause all
284
-   *   kinds of problems. Enabling EEPROM Storage is highly recommended. With EEPROM Storage
285
-   *   of the mesh, you are limited to 3-Point and Grid Leveling. (G29 P0 T and G29 P0 G
286
-   *   respectively.)
287
+   *   kinds of problems. Enabling EEPROM Storage is required.
287 288
    *
288 289
    *   When you do a G28 and then a G29 P1 to automatically build your first mesh, you are going to notice
289 290
    *   the Unified Bed Leveling probes points further and further away from the starting location. (The
@@ -385,36 +386,16 @@
385 386
       if (parser.seen('J')) {
386 387
         if (g29_grid_size) {  // if not 0 it is a normal n x n grid being probed
387 388
           save_ubl_active_state_and_disable();
388
-          tilt_mesh_based_on_probed_grid(parser.seen('T'));
389
+          tilt_mesh_based_on_probed_grid(false /* false says to do normal grid probing */ );
389 390
           restore_ubl_active_state_and_leave();
390 391
         }
391 392
         else { // grid_size == 0 : A 3-Point leveling has been requested
392
-          float z3, z2, z1 = probe_pt(UBL_PROBE_PT_1_X, UBL_PROBE_PT_1_Y, false, g29_verbose_level);
393
-          if (!isnan(z1)) {
394
-            z2 = probe_pt(UBL_PROBE_PT_2_X, UBL_PROBE_PT_2_Y, false, g29_verbose_level);
395
-            if (!isnan(z2))
396
-              z3 = probe_pt(UBL_PROBE_PT_3_X, UBL_PROBE_PT_3_Y, true, g29_verbose_level);
397
-          }
398
-
399
-          if (isnan(z1) || isnan(z2) || isnan(z3)) { // probe_pt will return NAN if unreachable
400
-            SERIAL_ERROR_START();
401
-            SERIAL_ERRORLNPGM("Attempt to probe off the bed.");
402
-            goto LEAVE;
403
-          }
404
-
405
-          // Adjust z1, z2, z3 by the Mesh Height at these points. Just because they're non-zero
406
-          // doesn't mean the Mesh is tilted! (Compensate each probe point by what the Mesh says
407
-          // its height is.)
408 393
 
409 394
           save_ubl_active_state_and_disable();
410
-          z1 -= get_z_correction(UBL_PROBE_PT_1_X, UBL_PROBE_PT_1_Y) /* + zprobe_zoffset */ ;
411
-          z2 -= get_z_correction(UBL_PROBE_PT_2_X, UBL_PROBE_PT_2_Y) /* + zprobe_zoffset */ ;
412
-          z3 -= get_z_correction(UBL_PROBE_PT_3_X, UBL_PROBE_PT_3_Y) /* + zprobe_zoffset */ ;
413
-
414
-          do_blocking_move_to_xy(0.5 * (MESH_MAX_X - (MESH_MIN_X)), 0.5 * (MESH_MAX_Y - (MESH_MIN_Y)));
415
-          tilt_mesh_based_on_3pts(z1, z2, z3);
395
+          tilt_mesh_based_on_probed_grid(true /* true says to do 3-Point leveling */ );
416 396
           restore_ubl_active_state_and_leave();
417 397
         }
398
+        do_blocking_move_to_xy(0.5 * (MESH_MAX_X - (MESH_MIN_X)), 0.5 * (MESH_MAX_Y - (MESH_MIN_Y)));
418 399
       }
419 400
 
420 401
     #endif // HAS_BED_PROBE
@@ -464,7 +445,7 @@
464 445
             SERIAL_PROTOCOLLNPGM("Manually probing unreachable mesh locations.");
465 446
             do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);
466 447
 
467
-            if (!g29_x_flag && !g29_y_flag) {
448
+            if (parser.seen('C') && !g29_x_flag && !g29_y_flag) {
468 449
               /**
469 450
                * Use a good default location for the path.
470 451
                * The flipped > and < operators in these comparisons is intentional.
@@ -481,13 +462,8 @@
481 462
               #endif
482 463
             }
483 464
 
484
-            if (parser.seen('C')) {
485
-              g29_x_pos = current_position[X_AXIS];
486
-              g29_y_pos = current_position[Y_AXIS];
487
-            }
488
-
489 465
             if (parser.seen('B')) {
490
-              g29_card_thickness = parser.has_value() ? parser.value_float() : measure_business_card_thickness(Z_CLEARANCE_BETWEEN_PROBES);
466
+              g29_card_thickness = parser.has_value() ? parser.value_float() : measure_business_card_thickness((float) Z_CLEARANCE_BETWEEN_PROBES);
491 467
               if (FABS(g29_card_thickness) > 1.5) {
492 468
                 SERIAL_PROTOCOLLNPGM("?Error in Business Card measurement.");
493 469
                 return;
@@ -672,7 +648,7 @@
672 648
     #if ENABLED(NEWPANEL)
673 649
       lcd_reset_alert_level();
674 650
       LCD_MESSAGEPGM("");
675
-      lcd_quick_feedback();
651
+      lcd_quick_feedback(true);
676 652
       lcd_external_control = false;
677 653
     #endif
678 654
 
@@ -730,12 +706,13 @@
730 706
 
731 707
     bool click_and_hold(const clickFunc_t func=NULL) {
732 708
       if (is_lcd_clicked()) {
733
-        lcd_quick_feedback();
709
+        lcd_quick_feedback(false); // Do NOT clear button status!  If cleared, the code
710
+                                   // code can not look for a 'click and hold'
734 711
         const millis_t nxt = millis() + 1500UL;
735 712
         while (is_lcd_clicked()) {                // Loop while the encoder is pressed. Uses hardware flag!
736 713
           idle();                                 // idle, of course
737 714
           if (ELAPSED(millis(), nxt)) {           // After 1.5 seconds
738
-            lcd_quick_feedback();
715
+            lcd_quick_feedback(true);
739 716
             if (func) (*func)();
740 717
             wait_for_release();
741 718
             safe_delay(50);                       // Debounce the Encoder wheel
@@ -743,6 +720,7 @@
743 720
           }
744 721
         }
745 722
       }
723
+      safe_delay(5);
746 724
       return false;
747 725
     }
748 726
 
@@ -771,11 +749,12 @@
771 749
         #if ENABLED(NEWPANEL)
772 750
           if (is_lcd_clicked()) {
773 751
             SERIAL_PROTOCOLLNPGM("\nMesh only partially populated.\n");
774
-            lcd_quick_feedback();
752
+            lcd_quick_feedback(false);
775 753
             STOW_PROBE();
776
-            wait_for_release();
754
+            while (is_lcd_clicked()) idle();
777 755
             lcd_external_control = false;
778 756
             restore_ubl_active_state_and_leave();
757
+            safe_delay(50);  // Debounce the Encoder wheel
779 758
             return;
780 759
           }
781 760
         #endif
@@ -804,109 +783,6 @@
804 783
       );
805 784
     }
806 785
 
807
-    void unified_bed_leveling::tilt_mesh_based_on_3pts(const float &z1, const float &z2, const float &z3) {
808
-      matrix_3x3 rotation;
809
-      vector_3 v1 = vector_3( (UBL_PROBE_PT_1_X - UBL_PROBE_PT_2_X),
810
-                              (UBL_PROBE_PT_1_Y - UBL_PROBE_PT_2_Y),
811
-                              (z1 - z2) ),
812
-
813
-               v2 = vector_3( (UBL_PROBE_PT_3_X - UBL_PROBE_PT_2_X),
814
-                              (UBL_PROBE_PT_3_Y - UBL_PROBE_PT_2_Y),
815
-                              (z3 - z2) ),
816
-
817
-               normal = vector_3::cross(v1, v2);
818
-
819
-      normal = normal.get_normal();
820
-
821
-      /**
822
-       * This vector is normal to the tilted plane.
823
-       * However, we don't know its direction. We need it to point up. So if
824
-       * Z is negative, we need to invert the sign of all components of the vector
825
-       */
826
-      if (normal.z < 0.0) {
827
-        normal.x = -normal.x;
828
-        normal.y = -normal.y;
829
-        normal.z = -normal.z;
830
-      }
831
-
832
-      rotation = matrix_3x3::create_look_at(vector_3(normal.x, normal.y, 1));
833
-
834
-      if (g29_verbose_level > 2) {
835
-        SERIAL_ECHOPGM("bed plane normal = [");
836
-        SERIAL_PROTOCOL_F(normal.x, 7);
837
-        SERIAL_PROTOCOLCHAR(',');
838
-        SERIAL_PROTOCOL_F(normal.y, 7);
839
-        SERIAL_PROTOCOLCHAR(',');
840
-        SERIAL_PROTOCOL_F(normal.z, 7);
841
-        SERIAL_ECHOLNPGM("]");
842
-        rotation.debug(PSTR("rotation matrix:"));
843
-      }
844
-
845
-      //
846
-      // All of 3 of these points should give us the same d constant
847
-      //
848
-
849
-      float t = normal.x * (UBL_PROBE_PT_1_X) + normal.y * (UBL_PROBE_PT_1_Y),
850
-            d = t + normal.z * z1;
851
-
852
-      if (g29_verbose_level>2) {
853
-        SERIAL_ECHOPGM("D constant: ");
854
-        SERIAL_PROTOCOL_F(d, 7);
855
-        SERIAL_ECHOLNPGM(" ");
856
-      }
857
-
858
-      #if ENABLED(DEBUG_LEVELING_FEATURE)
859
-        if (DEBUGGING(LEVELING)) {
860
-          SERIAL_ECHOPGM("d from 1st point: ");
861
-          SERIAL_ECHO_F(d, 6);
862
-          SERIAL_EOL();
863
-          t = normal.x * (UBL_PROBE_PT_2_X) + normal.y * (UBL_PROBE_PT_2_Y);
864
-          d = t + normal.z * z2;
865
-          SERIAL_ECHOPGM("d from 2nd point: ");
866
-          SERIAL_ECHO_F(d, 6);
867
-          SERIAL_EOL();
868
-          t = normal.x * (UBL_PROBE_PT_3_X) + normal.y * (UBL_PROBE_PT_3_Y);
869
-          d = t + normal.z * z3;
870
-          SERIAL_ECHOPGM("d from 3rd point: ");
871
-          SERIAL_ECHO_F(d, 6);
872
-          SERIAL_EOL();
873
-        }
874
-      #endif
875
-
876
-      for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
877
-        for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
878
-          float x_tmp = mesh_index_to_xpos(i),
879
-                y_tmp = mesh_index_to_ypos(j),
880
-                z_tmp = z_values[i][j];
881
-          #if ENABLED(DEBUG_LEVELING_FEATURE)
882
-            if (DEBUGGING(LEVELING)) {
883
-              SERIAL_ECHOPGM("before rotation = [");
884
-              SERIAL_PROTOCOL_F(x_tmp, 7);
885
-              SERIAL_PROTOCOLCHAR(',');
886
-              SERIAL_PROTOCOL_F(y_tmp, 7);
887
-              SERIAL_PROTOCOLCHAR(',');
888
-              SERIAL_PROTOCOL_F(z_tmp, 7);
889
-              SERIAL_ECHOPGM("]   ---> ");
890
-              safe_delay(20);
891
-            }
892
-          #endif
893
-          apply_rotation_xyz(rotation, x_tmp, y_tmp, z_tmp);
894
-          #if ENABLED(DEBUG_LEVELING_FEATURE)
895
-            if (DEBUGGING(LEVELING)) {
896
-              SERIAL_ECHOPGM("after rotation = [");
897
-              SERIAL_PROTOCOL_F(x_tmp, 7);
898
-              SERIAL_PROTOCOLCHAR(',');
899
-              SERIAL_PROTOCOL_F(y_tmp, 7);
900
-              SERIAL_PROTOCOLCHAR(',');
901
-              SERIAL_PROTOCOL_F(z_tmp, 7);
902
-              SERIAL_ECHOLNPGM("]");
903
-              safe_delay(55);
904
-            }
905
-          #endif
906
-          z_values[i][j] += z_tmp - d;
907
-        }
908
-      }
909
-    }
910 786
 
911 787
   #endif // HAS_BED_PROBE
912 788
 
@@ -932,7 +808,7 @@
932 808
 
933 809
     static void echo_and_take_a_measurement() { SERIAL_PROTOCOLLNPGM(" and take a measurement."); }
934 810
 
935
-    float unified_bed_leveling::measure_business_card_thickness(const float &in_height) {
811
+    float unified_bed_leveling::measure_business_card_thickness(float in_height) {
936 812
       lcd_external_control = true;
937 813
       save_ubl_active_state_and_disable();   // Disable bed level correction for probing
938 814
 
@@ -985,7 +861,7 @@
985 861
       lcd_external_control = true;
986 862
 
987 863
       save_ubl_active_state_and_disable();   // we don't do bed level correction because we want the raw data when we probe
988
-      do_blocking_move_to(rx, ry, Z_CLEARANCE_BETWEEN_PROBES);
864
+      do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], z_clearance);
989 865
 
990 866
       lcd_return_to_status();
991 867
 
@@ -1047,7 +923,7 @@
1047 923
 
1048 924
     #if ENABLED(NEWPANEL)
1049 925
       LCD_MESSAGEPGM(MSG_UBL_DOING_G29);
1050
-      lcd_quick_feedback();
926
+      lcd_quick_feedback(true);
1051 927
     #endif
1052 928
 
1053 929
     g29_constant = 0.0;
@@ -1170,7 +1046,7 @@
1170 1046
         SERIAL_ECHOLNPGM("save_ubl_active_state_and_disabled() called multiple times in a row.");
1171 1047
         #if ENABLED(NEWPANEL)
1172 1048
           LCD_MESSAGEPGM(MSG_UBL_SAVE_ERROR);
1173
-          lcd_quick_feedback();
1049
+          lcd_quick_feedback(true);
1174 1050
         #endif
1175 1051
         return;
1176 1052
       }
@@ -1185,7 +1061,7 @@
1185 1061
         SERIAL_ECHOLNPGM("restore_ubl_active_state_and_leave() called too many times.");
1186 1062
         #if ENABLED(NEWPANEL)
1187 1063
           LCD_MESSAGEPGM(MSG_UBL_RESTORE_ERROR);
1188
-          lcd_quick_feedback();
1064
+          lcd_quick_feedback(true);
1189 1065
         #endif
1190 1066
         return;
1191 1067
       }
@@ -1217,6 +1093,8 @@
1217 1093
       SERIAL_EOL();
1218 1094
     #endif
1219 1095
 
1096
+    find_mean_mesh_height();
1097
+
1220 1098
     #if HAS_BED_PROBE
1221 1099
       SERIAL_PROTOCOLPGM("zprobe_zoffset: ");
1222 1100
       SERIAL_PROTOCOL_F(zprobe_zoffset, 7);
@@ -1531,13 +1409,13 @@
1531 1409
 
1532 1410
         lcd_mesh_edit_setup(new_z);
1533 1411
 
1534
-        while (!is_lcd_clicked()) {
1412
+        do {
1535 1413
           new_z = lcd_mesh_edit();
1536 1414
           #if ENABLED(UBL_MESH_EDIT_MOVES_Z)
1537 1415
             do_blocking_move_to_z(h_offset + new_z); // Move the nozzle as the point is edited
1538 1416
           #endif
1539 1417
           idle();
1540
-        }
1418
+        } while (!is_lcd_clicked());
1541 1419
 
1542 1420
         if (!lcd_map_control) lcd_return_to_status();
1543 1421
 
@@ -1632,24 +1510,87 @@
1632 1510
 
1633 1511
   #if HAS_BED_PROBE
1634 1512
 
1635
-    void unified_bed_leveling::tilt_mesh_based_on_probed_grid(const bool do_ubl_mesh_map) {
1513
+    void unified_bed_leveling::tilt_mesh_based_on_probed_grid(const bool do_3_pt_leveling) {
1636 1514
       constexpr int16_t x_min = max(MIN_PROBE_X, MESH_MIN_X),
1637 1515
                         x_max = min(MAX_PROBE_X, MESH_MAX_X),
1638 1516
                         y_min = max(MIN_PROBE_Y, MESH_MIN_Y),
1639 1517
                         y_max = min(MAX_PROBE_Y, MESH_MAX_Y);
1640 1518
 
1519
+      bool abort_flag=false;
1520
+
1521
+      float measured_z;
1522
+
1641 1523
       const float dx = float(x_max - x_min) / (g29_grid_size - 1.0),
1642 1524
                   dy = float(y_max - y_min) / (g29_grid_size - 1.0);
1643 1525
 
1644 1526
       struct linear_fit_data lsf_results;
1527
+
1528
+//    float z1, z2, z3;  // Needed for algorithm validation down below.
1529
+
1645 1530
       incremental_LSF_reset(&lsf_results);
1646 1531
 
1532
+      if (do_3_pt_leveling) {
1533
+        measured_z = probe_pt(UBL_PROBE_PT_1_X, UBL_PROBE_PT_1_Y, false, g29_verbose_level);
1534
+        if (isnan(measured_z))
1535
+          abort_flag = true;
1536
+        else {
1537
+          measured_z -= get_z_correction(UBL_PROBE_PT_1_X, UBL_PROBE_PT_1_Y);
1538
+//        z1 = measured_z;
1539
+          if (g29_verbose_level>3) {
1540
+            serial_spaces(16);
1541
+            SERIAL_ECHOLNPAIR("Corrected_Z=", measured_z);
1542
+          }
1543
+          incremental_LSF(&lsf_results, UBL_PROBE_PT_1_X, UBL_PROBE_PT_1_Y, measured_z);
1544
+        }
1545
+
1546
+        if (!abort_flag) {
1547
+          measured_z = probe_pt(UBL_PROBE_PT_2_X, UBL_PROBE_PT_2_Y, false, g29_verbose_level);
1548
+//        z2 = measured_z;
1549
+          if (isnan(measured_z))
1550
+            abort_flag = true;
1551
+          else {
1552
+            measured_z -= get_z_correction(UBL_PROBE_PT_2_X, UBL_PROBE_PT_2_Y);
1553
+            if (g29_verbose_level>3) {
1554
+              serial_spaces(16);
1555
+              SERIAL_ECHOLNPAIR("Corrected_Z=", measured_z);
1556
+            }
1557
+            incremental_LSF(&lsf_results, UBL_PROBE_PT_2_X, UBL_PROBE_PT_2_Y, measured_z);
1558
+          }
1559
+        }
1560
+
1561
+        if (!abort_flag) {
1562
+          measured_z = probe_pt(UBL_PROBE_PT_3_X, UBL_PROBE_PT_3_Y, true, g29_verbose_level);
1563
+//        z3 = measured_z;
1564
+          if (isnan(measured_z))
1565
+            abort_flag = true;
1566
+          else {
1567
+            measured_z -= get_z_correction(UBL_PROBE_PT_3_X, UBL_PROBE_PT_3_Y);
1568
+            if (g29_verbose_level>3) {
1569
+              serial_spaces(16);
1570
+              SERIAL_ECHOLNPAIR("Corrected_Z=", measured_z);
1571
+            }
1572
+            incremental_LSF(&lsf_results, UBL_PROBE_PT_3_X, UBL_PROBE_PT_3_Y, measured_z);
1573
+          }
1574
+        }
1575
+
1576
+        if (abort_flag) {
1577
+          SERIAL_ECHOPGM("?Error probing point.  Aborting operation.\n");
1578
+          return;
1579
+        }
1580
+      } else {
1581
+
1647 1582
       bool zig_zag = false;
1648 1583
       for (uint8_t ix = 0; ix < g29_grid_size; ix++) {
1649 1584
         const float rx = float(x_min) + ix * dx;
1650 1585
         for (int8_t iy = 0; iy < g29_grid_size; iy++) {
1651 1586
           const float ry = float(y_min) + dy * (zig_zag ? g29_grid_size - 1 - iy : iy);
1652
-          float measured_z = probe_pt(rx, ry, parser.seen('E'), g29_verbose_level); // TODO: Needs error handling
1587
+
1588
+            if (!abort_flag) {
1589
+              measured_z = probe_pt(rx, ry, parser.seen('E'), g29_verbose_level); // TODO: Needs error handling
1590
+
1591
+              if (isnan(measured_z))
1592
+                abort_flag = true;
1593
+
1653 1594
           #if ENABLED(DEBUG_LEVELING_FEATURE)
1654 1595
             if (DEBUGGING(LEVELING)) {
1655 1596
               SERIAL_CHAR('(');
@@ -1680,24 +1621,18 @@
1680 1621
 
1681 1622
           incremental_LSF(&lsf_results, rx, ry, measured_z);
1682 1623
         }
1624
+          }
1683 1625
 
1684 1626
         zig_zag ^= true;
1685 1627
       }
1686 1628
 
1687
-      if (finish_incremental_LSF(&lsf_results)) {
1629
+      }
1630
+
1631
+      if (abort_flag || finish_incremental_LSF(&lsf_results)) {
1688 1632
         SERIAL_ECHOPGM("Could not complete LSF!");
1689 1633
         return;
1690 1634
       }
1691 1635
 
1692
-      if (g29_verbose_level > 3) {
1693
-        SERIAL_ECHOPGM("LSF Results A=");
1694
-        SERIAL_PROTOCOL_F(lsf_results.A, 7);
1695
-        SERIAL_ECHOPGM("  B=");
1696
-        SERIAL_PROTOCOL_F(lsf_results.B, 7);
1697
-        SERIAL_ECHOPGM("  D=");
1698
-        SERIAL_PROTOCOL_F(lsf_results.D, 7);
1699
-        SERIAL_EOL();
1700
-      }
1701 1636
 
1702 1637
       vector_3 normal = vector_3(lsf_results.A, lsf_results.B, 1.0000).get_normal();
1703 1638
 
@@ -1753,7 +1688,7 @@
1753 1688
 
1754 1689
       #if ENABLED(DEBUG_LEVELING_FEATURE)
1755 1690
         if (DEBUGGING(LEVELING)) {
1756
-          rotation.debug(PSTR("rotation matrix:"));
1691
+          rotation.debug(PSTR("rotation matrix:\n"));
1757 1692
           SERIAL_ECHOPGM("LSF Results A=");
1758 1693
           SERIAL_PROTOCOL_F(lsf_results.A, 7);
1759 1694
           SERIAL_ECHOPGM("  B=");
@@ -1771,10 +1706,62 @@
1771 1706
           SERIAL_PROTOCOL_F(normal.z, 7);
1772 1707
           SERIAL_ECHOPGM("]\n");
1773 1708
           SERIAL_EOL();
1709
+
1710
+/*
1711
+ * The following code can be used to check the validity of the mesh tilting algorithm.
1712
+ * When a 3-Point Mesh Tilt is done, the same algorithm is used as the grid based tilting.
1713
+ * The only difference is just 3 points are used in the calculations.   That fact guarantees
1714
+ * each probed point should have an exact match when a get_z_correction() for that location
1715
+ * is calculated.  The Z error between the probed point locations and the get_z_correction()
1716
+ * numbers for those locations should be 0.000
1717
+ */
1718
+/*
1719
+          float t, t1, d;
1720
+          t = normal.x * (UBL_PROBE_PT_1_X) + normal.y * (UBL_PROBE_PT_1_Y);
1721
+          d = t + normal.z * z1;
1722
+          SERIAL_ECHOPGM("D from 1st point: ");
1723
+          SERIAL_ECHO_F(d, 6);
1724
+          SERIAL_ECHO("   Z error: ");
1725
+          SERIAL_ECHO_F(normal.z*z1-get_z_correction(UBL_PROBE_PT_1_X, UBL_PROBE_PT_1_Y),6);
1726
+          SERIAL_EOL();
1727
+
1728
+          t = normal.x * (UBL_PROBE_PT_2_X) + normal.y * (UBL_PROBE_PT_2_Y);
1729
+          d = t + normal.z * z2;
1730
+          SERIAL_EOL();
1731
+          SERIAL_ECHOPGM("D from 2nd point: ");
1732
+          SERIAL_ECHO_F(d, 6);
1733
+          SERIAL_ECHO("   Z error: ");
1734
+          SERIAL_ECHO_F(normal.z*z2-get_z_correction(UBL_PROBE_PT_2_X, UBL_PROBE_PT_2_Y),6);
1735
+          SERIAL_EOL();
1736
+
1737
+          t = normal.x * (UBL_PROBE_PT_3_X) + normal.y * (UBL_PROBE_PT_3_Y);
1738
+          d = t + normal.z * z3;
1739
+          SERIAL_ECHOPGM("D from 3rd point: ");
1740
+          SERIAL_ECHO_F(d, 6);
1741
+          SERIAL_ECHO("   Z error: ");
1742
+          SERIAL_ECHO_F(normal.z*z3-get_z_correction(UBL_PROBE_PT_3_X, UBL_PROBE_PT_3_Y),6);
1743
+          SERIAL_EOL();
1744
+
1745
+          t = normal.x * (Z_SAFE_HOMING_X_POINT) + normal.y * (Z_SAFE_HOMING_Y_POINT);
1746
+          d = t + normal.z * 0.000;
1747
+          SERIAL_ECHOPGM("D from home location with Z=0 : ");
1748
+          SERIAL_ECHO_F(d, 6);
1749
+          SERIAL_EOL();
1750
+
1751
+          t = normal.x * (Z_SAFE_HOMING_X_POINT) + normal.y * (Z_SAFE_HOMING_Y_POINT);
1752
+          d = t + get_z_correction(Z_SAFE_HOMING_X_POINT, Z_SAFE_HOMING_Y_POINT); // normal.z * 0.000;
1753
+          SERIAL_ECHOPGM("D from home location using mesh value for Z: ");
1754
+          SERIAL_ECHO_F(d, 6);
1755
+
1756
+          SERIAL_ECHOPAIR("   Z error: (", Z_SAFE_HOMING_X_POINT );
1757
+          SERIAL_ECHOPAIR(",", Z_SAFE_HOMING_Y_POINT );
1758
+          SERIAL_ECHO(") = ");
1759
+          SERIAL_ECHO_F( get_z_correction(Z_SAFE_HOMING_X_POINT, Z_SAFE_HOMING_Y_POINT),6);
1760
+          SERIAL_EOL();
1761
+*/
1774 1762
         }
1775 1763
       #endif
1776 1764
 
1777
-      if (do_ubl_mesh_map) display_map(g29_map_type);
1778 1765
     }
1779 1766
 
1780 1767
   #endif // HAS_BED_PROBE

+ 15
- 6
Marlin/src/gcode/bedlevel/G26.cpp View File

@@ -165,7 +165,7 @@ int8_t g26_prime_flag;
165 165
     if (!is_lcd_clicked()) return false; // Return if the button isn't pressed
166 166
     lcd_setstatusPGM(PSTR("Mesh Validation Stopped."), 99);
167 167
     #if ENABLED(ULTIPANEL)
168
-      lcd_quick_feedback();
168
+      lcd_quick_feedback(true);
169 169
     #endif
170 170
     wait_for_release();
171 171
     return true;
@@ -421,7 +421,7 @@ inline bool turn_on_heaters() {
421 421
     #if ENABLED(ULTRA_LCD)
422 422
       if (g26_bed_temp > 25) {
423 423
         lcd_setstatusPGM(PSTR("G26 Heating Bed."), 99);
424
-        lcd_quick_feedback();
424
+        lcd_quick_feedback(true);
425 425
         lcd_external_control = true;
426 426
     #endif
427 427
         thermalManager.setTargetBed(g26_bed_temp);
@@ -441,7 +441,7 @@ inline bool turn_on_heaters() {
441 441
     #if ENABLED(ULTRA_LCD)
442 442
       }
443 443
       lcd_setstatusPGM(PSTR("G26 Heating Nozzle."), 99);
444
-      lcd_quick_feedback();
444
+      lcd_quick_feedback(true);
445 445
     #endif
446 446
   #endif
447 447
 
@@ -463,7 +463,7 @@ inline bool turn_on_heaters() {
463 463
 
464 464
   #if ENABLED(ULTRA_LCD)
465 465
     lcd_reset_status();
466
-    lcd_quick_feedback();
466
+    lcd_quick_feedback(true);
467 467
   #endif
468 468
 
469 469
   return G26_OK;
@@ -509,7 +509,7 @@ inline bool prime_nozzle() {
509 509
       strcpy_P(lcd_status_message, PSTR("Done Priming")); // We can't do lcd_setstatusPGM() without having it continue;
510 510
                                                           // So... We cheat to get a message up.
511 511
       lcd_setstatusPGM(PSTR("Done Priming"), 99);
512
-      lcd_quick_feedback();
512
+      lcd_quick_feedback(true);
513 513
       lcd_external_control = false;
514 514
     }
515 515
     else
@@ -517,7 +517,7 @@ inline bool prime_nozzle() {
517 517
   {
518 518
     #if ENABLED(ULTRA_LCD)
519 519
       lcd_setstatusPGM(PSTR("Fixed Length Prime."), 99);
520
-      lcd_quick_feedback();
520
+      lcd_quick_feedback(true);
521 521
     #endif
522 522
     set_destination_from_current();
523 523
     destination[E_AXIS] += g26_prime_length;
@@ -680,9 +680,12 @@ void GcodeSuite::G26() {
680 680
   set_bed_leveling_enabled(!parser.seen('D'));
681 681
 
682 682
   if (current_position[Z_AXIS] < Z_CLEARANCE_BETWEEN_PROBES) {
683
+SERIAL_PROTOCOLLNPGM("! move nozzle to Z_CLEARANCE_BETWEEN_PROBES height.");
684
+SERIAL_ECHOLNPAIR("  Z at:", current_position[Z_AXIS]);
683 685
     do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);
684 686
     stepper.synchronize();
685 687
     set_current_from_destination();
688
+SERIAL_ECHOLNPAIR("  Z now at:", current_position[Z_AXIS]);
686 689
   }
687 690
 
688 691
   if (turn_on_heaters() != G26_OK) goto LEAVE;
@@ -708,8 +711,14 @@ void GcodeSuite::G26() {
708 711
 
709 712
   // Move nozzle to the specified height for the first layer
710 713
   set_destination_from_current();
714
+SERIAL_PROTOCOLLNPGM("! moving nozzle to 1st layer height.");
715
+SERIAL_ECHOLNPAIR("  Z1 at:", current_position[Z_AXIS]);
716
+
711 717
   destination[Z_AXIS] = g26_layer_height;
712 718
   move_to(destination, 0.0);
719
+  stepper.synchronize();
720
+  set_destination_from_current();
721
+SERIAL_ECHOLNPAIR("  Z2 at:", current_position[Z_AXIS]);
713 722
   move_to(destination, g26_ooze_amount);
714 723
 
715 724
   #if ENABLED(ULTRA_LCD)

+ 8
- 5
Marlin/src/lcd/ultralcd.cpp View File

@@ -774,9 +774,12 @@ void kill_screen(const char* lcd_msg) {
774 774
     #endif
775 775
   }
776 776
 
777
-  void lcd_quick_feedback() {
777
+  void lcd_quick_feedback(const bool clear_buttons) {
778 778
     lcdDrawUpdate = LCDVIEW_CLEAR_CALL_REDRAW;
779
-    buttons = 0;
779
+
780
+    if (clear_buttons)
781
+      buttons = 0;
782
+
780 783
     next_button_update_ms = millis() + 500;
781 784
 
782 785
     // Buzz and wait. The delay is needed for buttons to settle!
@@ -4672,8 +4675,8 @@ void kill_screen(const char* lcd_msg) {
4672 4675
         if (encoderDirection == -1) { // side effect which signals we are inside a menu
4673 4676
           if      (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_DOWN)  encoderPosition -= ENCODER_STEPS_PER_MENU_ITEM;
4674 4677
           else if (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_UP)    encoderPosition += ENCODER_STEPS_PER_MENU_ITEM;
4675
-          else if (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_LEFT)  { menu_action_back(); lcd_quick_feedback(); }
4676
-          else if (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_RIGHT) { lcd_return_to_status(); lcd_quick_feedback(); }
4678
+          else if (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_LEFT)  { menu_action_back(); lcd_quick_feedback(true); }
4679
+          else if (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_RIGHT) { lcd_return_to_status(); lcd_quick_feedback(true); }
4677 4680
         }
4678 4681
         else {
4679 4682
           if (buttons_reprapworld_keypad & (EN_REPRAPWORLD_KEYPAD_DOWN|EN_REPRAPWORLD_KEYPAD_UP|EN_REPRAPWORLD_KEYPAD_RIGHT)) {
@@ -4941,7 +4944,7 @@ void lcd_update() {
4941 4944
         wait_for_unclick = true;         //  Set debounce flag to ignore continous clicks
4942 4945
         lcd_clicked = !wait_for_user && !no_reentry; //  Keep the click if not waiting for a user-click
4943 4946
         wait_for_user = false;           //  Any click clears wait for user
4944
-        lcd_quick_feedback();            //  Always make a click sound
4947
+        lcd_quick_feedback(true);        //  Always make a click sound
4945 4948
       }
4946 4949
     }
4947 4950
     else wait_for_unclick = false;

+ 1
- 1
Marlin/src/lcd/ultralcd.h View File

@@ -116,7 +116,7 @@
116 116
 
117 117
     extern volatile uint8_t buttons;  // The last-checked buttons in a bit array.
118 118
     void lcd_buttons_update();
119
-    void lcd_quick_feedback();        // Audible feedback for a button click - could also be visual
119
+    void lcd_quick_feedback(const bool clear_buttons); // Audible feedback for a button click - could also be visual
120 120
     void lcd_completion_feedback(const bool good=true);
121 121
 
122 122
     #if ENABLED(ADVANCED_PAUSE_FEATURE)

Loading…
Cancel
Save