From 3129260c44656107dfc968c0cd41f6fa615314ea Mon Sep 17 00:00:00 2001
From: Roxy-3D <Roxy-3D@users.noreply.github.com>
Date: Sun, 21 May 2017 22:09:51 -0500
Subject: [PATCH] Misc. Clean Up (#6822)

* Misc. Clean Up

Mostly UBL related clean up.
- But fixed a bug in the thermistortables.
- Made G26 more responsive to user aborts.
- Added sanity checks for older name for UBL_MESH_VALIDATION.
- Made G29 P4 able to edit invalidated mesh points
- Restore a reasonable Fade Height for UBL when creating new state information
- Get UBL's Topology Map to look a little bit better
- Make sure the user doesn't see a blank screen when doing Mesh Editing.

* Huh???   GitHub Desktop screwed up!

* get the planner object in scope

* Fix out of scope z_fade_height

* Travis timed out...

I need a change so I can force a new commit and sync.
---
 Marlin/G26_Mesh_Validation_Tool.cpp | 96 ++++++++++++++---------------
 Marlin/SanityCheck.h                |  2 +
 Marlin/thermistortables.h           |  2 +-
 Marlin/ubl.cpp                      | 13 ++--
 Marlin/ubl_G29.cpp                  | 82 +++++++++++++-----------
 Marlin/ultralcd.cpp                 |  2 +
 6 files changed, 106 insertions(+), 91 deletions(-)

diff --git a/Marlin/G26_Mesh_Validation_Tool.cpp b/Marlin/G26_Mesh_Validation_Tool.cpp
index d605cc70e7..ff329bf161 100644
--- a/Marlin/G26_Mesh_Validation_Tool.cpp
+++ b/Marlin/G26_Mesh_Validation_Tool.cpp
@@ -144,7 +144,7 @@
 
   void un_retract_filament(float where[XYZE]);
   void retract_filament(float where[XYZE]);
-  void look_for_lines_to_connect();
+  bool look_for_lines_to_connect();
   bool parse_G26_parameters();
   void move_to(const float&, const float&, const float&, const float&) ;
   void print_line_from_here_to_there(const float&, const float&, const float&, const float&, const float&, const float&);
@@ -249,24 +249,6 @@
     }
 
     do {
-
-      if (ubl_lcd_clicked()) {              // Check if the user wants to stop the Mesh Validation
-        #if ENABLED(ULTRA_LCD)
-          lcd_setstatuspgm(PSTR("Mesh Validation Stopped."), 99);
-          lcd_quick_feedback();
-        #endif
-        while (!ubl_lcd_clicked()) {         // Wait until the user is done pressing the
-          idle();                            // Encoder Wheel if that is why we are leaving
-          lcd_reset_alert_level();
-          lcd_setstatuspgm(PSTR(""));
-        }
-        while (ubl_lcd_clicked()) {          // Wait until the user is done pressing the
-          idle();                            // Encoder Wheel if that is why we are leaving
-          lcd_setstatuspgm(PSTR("Unpress Wheel"), 99);
-        }
-        goto LEAVE;
-      }
-
       location = continue_with_closest
         ? find_closest_circle_to_print(current_position[X_AXIS], current_position[Y_AXIS])
         : find_closest_circle_to_print(x_pos, y_pos); // Find the closest Mesh Intersection to where we are now.
@@ -317,6 +299,27 @@
         }
 
         for (tmp = start_angle; tmp < end_angle - 0.1; tmp += 30.0) {
+
+          // this sequence to detect an ubl_lcd_clicked() debounce it and leave if it is
+          // a Press and Hold is repeated in a lot of places (including ubl_G29.cpp).   This
+          // should be redone and compressed.
+          if (ubl_lcd_clicked()) {              // Check if the user wants to stop the Mesh Validation
+            #if ENABLED(ULTRA_LCD)
+              lcd_setstatuspgm(PSTR("Mesh Validation Stopped."), 99);
+              lcd_quick_feedback();
+            #endif
+            while (!ubl_lcd_clicked()) {         // Wait until the user is done pressing the
+              idle();                            // Encoder Wheel if that is why we are leaving
+              lcd_reset_alert_level();
+              lcd_setstatuspgm(PSTR(""));
+            }
+            while (ubl_lcd_clicked()) {          // Wait until the user is done pressing the
+              idle();                            // Encoder Wheel if that is why we are leaving
+              lcd_setstatuspgm(PSTR("Unpress Wheel"), 99);
+            }
+            goto LEAVE;
+          }
+
           int tmp_div_30 = tmp / 30.0;
           if (tmp_div_30 < 0) tmp_div_30 += 360 / 30;
           if (tmp_div_30 > 11) tmp_div_30 -= 360 / 30;
@@ -349,14 +352,9 @@
           print_line_from_here_to_there(LOGICAL_X_POSITION(x), LOGICAL_Y_POSITION(y), layer_height, LOGICAL_X_POSITION(xe), LOGICAL_Y_POSITION(ye), layer_height);
 
         }
-
-        //debug_current_and_destination(PSTR("Looking for lines to connect."));
-        look_for_lines_to_connect();
-        //debug_current_and_destination(PSTR("Done with line connect."));
+        if (look_for_lines_to_connect())
+          goto LEAVE;
       }
-
-      //debug_current_and_destination(PSTR("Done with current circle."));
-
     } while (--g26_repeats && location.x_index >= 0 && location.y_index >= 0);
 
     LEAVE:
@@ -432,12 +430,32 @@
     return return_val;
   }
 
-  void look_for_lines_to_connect() {
+  bool look_for_lines_to_connect() {
     float sx, sy, ex, ey;
 
     for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
       for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
 
+        // this sequence to detect an ubl_lcd_clicked() debounce it and leave if it is
+        // a Press and Hold is repeated in a lot of places (including ubl_G29.cpp).   This
+        // should be redone and compressed.
+        if (ubl_lcd_clicked()) {              // Check if the user wants to stop the Mesh Validation
+          #if ENABLED(ULTRA_LCD)
+            lcd_setstatuspgm(PSTR("Mesh Validation Stopped."), 99);
+            lcd_quick_feedback();
+          #endif
+          while (!ubl_lcd_clicked()) {         // Wait until the user is done pressing the
+            idle();                            // Encoder Wheel if that is why we are leaving
+            lcd_reset_alert_level();
+            lcd_setstatuspgm(PSTR(""));
+          }
+          while (ubl_lcd_clicked()) {          // Wait until the user is done pressing the
+            idle();                            // Encoder Wheel if that is why we are leaving
+            lcd_setstatuspgm(PSTR("Unpress Wheel"), 99);
+          }
+          return true;
+        }
+
         if (i < GRID_MAX_POINTS_X) { // We can't connect to anything to the right than GRID_MAX_POINTS_X.
                                          // This is already a half circle because we are at the edge of the bed.
 
@@ -509,6 +527,7 @@
         }
       }
     }
+    return false;
   }
 
   void move_to(const float &x, const float &y, const float &z, const float &e_delta) {
@@ -517,11 +536,7 @@
 
     bool has_xy_component = (x != current_position[X_AXIS] || y != current_position[Y_AXIS]); // Check if X or Y is involved in the movement.
 
-    //if (ubl.g26_debug_flag) SERIAL_ECHOLNPAIR("in move_to()  has_xy_component:", (int)has_xy_component);
-
     if (z != last_z) {
-      //if (ubl.g26_debug_flag) SERIAL_ECHOLNPAIR("in move_to()  changing Z to ", (int)z);
-
       last_z = z;
       feed_value = planner.max_feedrate_mm_s[Z_AXIS]/(3.0);  // Base the feed rate off of the configured Z_AXIS feed rate
 
@@ -534,8 +549,6 @@
 
       stepper.synchronize();
       set_destination_to_current();
-
-      //if (ubl.g26_debug_flag) debug_current_and_destination(PSTR(" in move_to() done with Z move"));
     }
 
     // Check if X or Y is involved in the movement.
@@ -548,12 +561,8 @@
     destination[Y_AXIS] = y;
     destination[E_AXIS] += e_delta;
 
-    //if (ubl.g26_debug_flag) debug_current_and_destination(PSTR(" in move_to() doing last move"));
-
     G26_line_to_destination(feed_value);
 
-    //if (ubl.g26_debug_flag) debug_current_and_destination(PSTR(" in move_to() after last move"));
-
     stepper.synchronize();
     set_destination_to_current();
 
@@ -562,9 +571,7 @@
   void retract_filament(float where[XYZE]) {
     if (!g26_retracted) { // Only retract if we are not already retracted!
       g26_retracted = true;
-      //if (ubl.g26_debug_flag) SERIAL_ECHOLNPGM(" Decided to do retract.");
       move_to(where[X_AXIS], where[Y_AXIS], where[Z_AXIS], -1.0 * retraction_multiplier);
-      //if (ubl.g26_debug_flag) SERIAL_ECHOLNPGM(" Retraction done.");
     }
   }
 
@@ -572,7 +579,6 @@
     if (g26_retracted) { // Only un-retract if we are retracted.
       move_to(where[X_AXIS], where[Y_AXIS], where[Z_AXIS], 1.2 * retraction_multiplier);
       g26_retracted = false;
-      //if (ubl.g26_debug_flag) SERIAL_ECHOLNPGM(" unretract done.");
     }
   }
 
@@ -605,7 +611,6 @@
     // If the end point of the line is closer to the nozzle, flip the direction,
     // moving from the end to the start. On very small lines the optimization isn't worth it.
     if (dist_end < dist_start && (SIZE_OF_INTERSECTION_CIRCLES) < abs(line_length)) {
-      //if (ubl.g26_debug_flag) SERIAL_ECHOLNPGM("  Reversing start and end of print_line_from_here_to_there()");
       return print_line_from_here_to_there(ex, ey, ez, sx, sy, sz);
     }
 
@@ -613,9 +618,6 @@
 
     if (dist_start > 2.0) {
       retract_filament(destination);
-      //if (ubl.g26_debug_flag) SERIAL_ECHOLNPGM("  filament retracted.");
-
-      //if (ubl.g26_debug_flag) SERIAL_ECHOLNPGM("  Z bumping by 0.500 to minimize scraping.");
       //todo:  parameterize the bump height with a define
       move_to(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] + 0.500, 0.0);  // Z bump to minimize scraping
       move_to(sx, sy, sz + 0.500, 0.0); // Get to the starting point with no extrusion while bumped
@@ -626,11 +628,6 @@
     const float e_pos_delta = line_length * g26_e_axis_feedrate * extrusion_multiplier;
 
     un_retract_filament(destination);
-
-    //if (ubl.g26_debug_flag) {
-    //  SERIAL_ECHOLNPGM("  doing printing move.");
-    //  debug_current_and_destination(PSTR("doing final move_to() inside print_line_from_here_to_there()"));
-    //}
     move_to(ex, ey, ez, e_pos_delta);  // Get to the ending point with an appropriate amount of extrusion
   }
 
@@ -754,7 +751,6 @@
   }
 
   bool exit_from_g26() {
-    //strcpy(lcd_status_message, "Leaving G26"); // We can't do lcd_setstatus() without having it continue;
     lcd_reset_alert_level();
     lcd_setstatuspgm(PSTR("Leaving G26"));
     while (ubl_lcd_clicked()) idle();
diff --git a/Marlin/SanityCheck.h b/Marlin/SanityCheck.h
index cc466b2336..952200d145 100644
--- a/Marlin/SanityCheck.h
+++ b/Marlin/SanityCheck.h
@@ -160,6 +160,8 @@
   #error "UBL_MESH_EDIT_ENABLED is now UBL_G26_MESH_VALIDATION. Please update your configuration."
 #elif defined(UBL_MESH_EDITING)
   #error "UBL_MESH_EDITING is now UBL_G26_MESH_VALIDATION. Please update your configuration."
+#elif defined(BLTOUCH_HEATERS_OFF)
+  #error "BLTOUCH_HEATERS_OFF is now PROBING_HEATERS_OFF. Please update your configuration."
 #elif defined(BEEPER)
   #error "BEEPER is now BEEPER_PIN. Please update your pins definitions."
 #elif defined(SDCARDDETECT)
diff --git a/Marlin/thermistortables.h b/Marlin/thermistortables.h
index 3777cf2e42..164afa5ea2 100644
--- a/Marlin/thermistortables.h
+++ b/Marlin/thermistortables.h
@@ -89,7 +89,7 @@
   #include "thermistortable_52.h"
 #endif
 #if ANY_THERMISTOR_IS(55) // 100k ATC Semitec 104GT-2 (Used on ParCan) (WITH 1kohm RESISTOR FOR PULLUP, R9 ON SANGUINOLOLU! NOT FOR 4.7kohm PULLUP! THIS IS NOT NORMAL!)
-  #include "thermistortable_53.h"
+  #include "thermistortable_55.h"
 #endif
 #if ANY_THERMISTOR_IS(60) // Maker's Tool Works Kapton Bed Thermistor
   #include "thermistortable_60.h"
diff --git a/Marlin/ubl.cpp b/Marlin/ubl.cpp
index 8ca43c5be1..8e6190953e 100644
--- a/Marlin/ubl.cpp
+++ b/Marlin/ubl.cpp
@@ -29,6 +29,8 @@
   #include "hex_print_routines.h"
   #include "temperature.h"
 
+  extern Planner planner;
+
   /**
    * These support functions allow the use of large bit arrays of flags that take very
    * little RAM. Currently they are limited to being 16x16 in size. Changing the declaration
@@ -76,7 +78,7 @@
   volatile int unified_bed_leveling::encoder_diff;
 
   unified_bed_leveling::unified_bed_leveling() {
-    ubl_cnt++;  // Debug counter to insure we only have one UBL object present in memory.
+    ubl_cnt++;  // Debug counter to insure we only have one UBL object present in memory.  We can eliminate this (and all references to ubl_cnt) very soon.
     reset();
   }
 
@@ -84,9 +86,10 @@
     state.active = false;
     state.z_offset = 0;
     state.storage_slot = -1;
-
+    #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
+      planner.z_fade_height = 10.0;
+    #endif
     ZERO(z_values);
-
     last_specified_z = -999.9;
   }
 
@@ -100,7 +103,7 @@
 
   void unified_bed_leveling::display_map(const int map_type) {
     const bool map0 = map_type == 0;
-    constexpr uint8_t spaces = 9 * (GRID_MAX_POINTS_X - 2);
+    constexpr uint8_t spaces = 8 * (GRID_MAX_POINTS_X - 2);
 
     if (map0) {
       SERIAL_PROTOCOLLNPGM("\nBed Topography Report:\n");
@@ -126,7 +129,7 @@
 
         const float f = z_values[i][j];
         if (isnan(f)) {
-          serialprintPGM(map0 ? PSTR("   .  ") : PSTR("NAN"));
+          serialprintPGM(map0 ? PSTR("    .   ") : PSTR("NAN"));
         }
         else {
           // if we don't do this, the columns won't line up nicely
diff --git a/Marlin/ubl_G29.cpp b/Marlin/ubl_G29.cpp
index b8b992baa1..1b718dd647 100644
--- a/Marlin/ubl_G29.cpp
+++ b/Marlin/ubl_G29.cpp
@@ -1009,6 +1009,9 @@
         }
       }
 
+      // this sequence to detect an ubl_lcd_clicked() debounce it and leave if it is
+      // a Press and Hold is repeated in a lot of places (including G26_Mesh_Validation.cpp).   This
+      // should be redone and compressed.
       const millis_t nxt = millis() + 1500L;
       while (ubl_lcd_clicked()) {     // debounce and watch for abort
         idle();
@@ -1327,10 +1330,9 @@
 
     // Get our reference position. Either the nozzle or probe location.
     const float px = RAW_X_POSITION(lx) - (probe_as_reference == USE_PROBE_AS_REFERENCE ? X_PROBE_OFFSET_FROM_EXTRUDER : 0),
-                py = RAW_Y_POSITION(ly) - (probe_as_reference == USE_PROBE_AS_REFERENCE ? Y_PROBE_OFFSET_FROM_EXTRUDER : 0),
-                raw_x = RAW_CURRENT_POSITION(X), raw_y = RAW_CURRENT_POSITION(Y);
+                py = RAW_Y_POSITION(ly) - (probe_as_reference == USE_PROBE_AS_REFERENCE ? Y_PROBE_OFFSET_FROM_EXTRUDER : 0);
 
-    float closest = far_flag ? -99999.99 : 99999.99;
+    float best_so_far = far_flag ? -99999.99 : 99999.99;
 
     for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
       for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
@@ -1339,10 +1341,10 @@
           || (type == REAL && !isnan(ubl.z_values[i][j]))
           || (type == SET_IN_BITMAP && is_bit_set(bits, i, j))
         ) {
-
           // We only get here if we found a Mesh Point of the specified type
 
-          const float mx = pgm_read_float(&ubl.mesh_index_to_xpos[i]), // Check if we can probe this mesh location
+          float raw_x = RAW_CURRENT_POSITION(X), raw_y = RAW_CURRENT_POSITION(Y);
+          const float mx = pgm_read_float(&ubl.mesh_index_to_xpos[i]),
                       my = pgm_read_float(&ubl.mesh_index_to_ypos[j]);
 
           // If using the probe as the reference there are some unreachable locations.
@@ -1352,10 +1354,10 @@
           if (probe_as_reference ? !position_is_reachable_by_probe_raw_xy(mx, my) : !position_is_reachable_raw_xy(mx, my))
             continue;
 
-          // Reachable. Check if it's the closest location to the nozzle.
+          // Reachable. Check if it's the best_so_far location to the nozzle.
           // Add in a weighting factor that considers the current location of the nozzle.
 
-          float distance = HYPOT(px - mx, py - my) + HYPOT(raw_x - mx, raw_y - my) * 0.1;
+          float distance = HYPOT(px - mx, py - my);
 
           /**
            * If doing the far_flag action, we want to be as far as possible
@@ -1367,20 +1369,24 @@
           if (far_flag) {
             for (uint8_t k = 0; k < GRID_MAX_POINTS_X; k++) {
               for (uint8_t l = 0; l < GRID_MAX_POINTS_Y; l++) {
-                if (!isnan(ubl.z_values[k][l])) {
-                  distance += sq(i - k) * (MESH_X_DIST) * .05
-                            + sq(j - l) * (MESH_Y_DIST) * .05;
+                if (i != k && j != l && !isnan(ubl.z_values[k][l])) {
+//                distance += pow((float) abs(i - k) * (MESH_X_DIST), 2) + pow((float) abs(j - l) * (MESH_Y_DIST), 2);  // working here
+                  distance += HYPOT((MESH_X_DIST),(MESH_Y_DIST)) / log(HYPOT((i - k) * (MESH_X_DIST)+.001, (j - l) * (MESH_Y_DIST))+.001);
                 }
               }
             }
           }
+          else
+          // factor in the distance from the current location for the normal case
+          // so the nozzle isn't running all over the bed.
+            distance += HYPOT(raw_x - mx, raw_y - my) * 0.1;
 
           // if far_flag, look for farthest point
-          if (far_flag == (distance > closest) && distance != closest) {
-            closest = distance;       // We found a closer/farther location with
+          if (far_flag == (distance > best_so_far) && distance != best_so_far) {
+            best_so_far = distance;   // We found a closer/farther location with
             out_mesh.x_index = i;     // the specified type of mesh value.
             out_mesh.y_index = j;
-            out_mesh.distance = closest;
+            out_mesh.distance = best_so_far;
           }
         }
       } // for j
@@ -1408,7 +1414,7 @@
 
     LCD_MESSAGEPGM("Fine Tuning Mesh"); // TODO: Make translatable string
 
-    do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);
+    do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);
     do_blocking_move_to_xy(lx, ly);
     do {
       location = find_closest_mesh_point_of_type(SET_IN_BITMAP, lx, ly, USE_NOZZLE_AS_REFERENCE, not_done, false);
@@ -1426,42 +1432,48 @@
 
       float new_z = ubl.z_values[location.x_index][location.y_index];
 
-      if (!isnan(new_z)) {  //can't fine tune a point that hasn't been probed
+      if (isnan(new_z)) // if the mesh point is invalid, set it to 0.0 so it can be edited
+        new_z = 0.0;
 
-        do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);    // Move the nozzle to where we are going to edit
-        do_blocking_move_to_xy(LOGICAL_X_POSITION(rawx), LOGICAL_Y_POSITION(rawy));
+      do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);    // Move the nozzle to where we are going to edit
+      do_blocking_move_to_xy(LOGICAL_X_POSITION(rawx), LOGICAL_Y_POSITION(rawy));
 
-        new_z = floor(new_z * 1000.0) * 0.001; // Chop off digits after the 1000ths place
+      new_z = floor(new_z * 1000.0) * 0.001; // Chop off digits after the 1000ths place
 
-        KEEPALIVE_STATE(PAUSED_FOR_USER);
-        ubl.has_control_of_lcd_panel = true;
+      KEEPALIVE_STATE(PAUSED_FOR_USER);
+      ubl.has_control_of_lcd_panel = true;
 
-        if (do_ubl_mesh_map) ubl.display_map(map_type);  // show the user which point is being adjusted
+      if (do_ubl_mesh_map) ubl.display_map(map_type);  // show the user which point is being adjusted
 
-        lcd_implementation_clear();
+      lcd_implementation_clear();
 
-        lcd_mesh_edit_setup(new_z);
+      lcd_mesh_edit_setup(new_z);
 
-        do {
-          new_z = lcd_mesh_edit();
-          idle();
-        } while (!ubl_lcd_clicked());
+      do {
+        new_z = lcd_mesh_edit();
+        #ifdef UBL_MESH_EDIT_MOVES_Z
+          do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES+new_z);  // Move the nozzle as the point is edited
+        #endif
+        idle();
+      } while (!ubl_lcd_clicked());
 
-        lcd_return_to_status();
+      lcd_return_to_status();
 
-        // The technique used here generates a race condition for the encoder click.
-        // It could get detected in lcd_mesh_edit (actually _lcd_mesh_fine_tune) or here.
-        // Let's work on specifying a proper API for the LCD ASAP, OK?
-        ubl.has_control_of_lcd_panel = true;
-      }
+      // The technique used here generates a race condition for the encoder click.
+      // It could get detected in lcd_mesh_edit (actually _lcd_mesh_fine_tune) or here.
+      // Let's work on specifying a proper API for the LCD ASAP, OK?
+      ubl.has_control_of_lcd_panel = true;
 
+      // this sequence to detect an ubl_lcd_clicked() debounce it and leave if it is
+      // a Press and Hold is repeated in a lot of places (including G26_Mesh_Validation.cpp).   This
+      // should be redone and compressed.
       const millis_t nxt = millis() + 1500UL;
       while (ubl_lcd_clicked()) { // debounce and watch for abort
         idle();
         if (ELAPSED(millis(), nxt)) {
           lcd_return_to_status();
           //SERIAL_PROTOCOLLNPGM("\nFine Tuning of Mesh Stopped.");
-          do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);
+          do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);
           LCD_MESSAGEPGM("Mesh Editing Stopped"); // TODO: Make translatable string
 
           while (ubl_lcd_clicked()) idle();
@@ -1485,7 +1497,7 @@
 
     if (do_ubl_mesh_map) ubl.display_map(map_type);
     ubl.restore_ubl_active_state_and_leave();
-    do_blocking_move_to_z(Z_CLEARANCE_DEPLOY_PROBE);
+    do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);
 
     do_blocking_move_to_xy(lx, ly);
 
diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp
index 7edbdc519d..894c6276fe 100644
--- a/Marlin/ultralcd.cpp
+++ b/Marlin/ultralcd.cpp
@@ -958,11 +958,13 @@ void kill_screen(const char* lcd_msg) {
     }
 
     void _lcd_mesh_edit() {
+      lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
       _lcd_mesh_fine_tune(PSTR("Mesh Editor"));
     }
 
     float lcd_mesh_edit() {
       lcd_goto_screen(_lcd_mesh_edit_NOP);
+      lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
       _lcd_mesh_fine_tune(PSTR("Mesh Editor"));
       return mesh_edit_value;
     }
-- 
GitLab