瀏覽代碼

Improve UBL mesh report. Add M420 T, M421 N

Scott Lahteine 7 年之前
父節點
當前提交
0746aff595

+ 78
- 58
Marlin/src/feature/bedlevel/ubl/ubl.cpp 查看文件

51
   ) {
51
   ) {
52
     if (!leveling_is_valid()) return;
52
     if (!leveling_is_valid()) return;
53
     SERIAL_ECHO_START_P(port);
53
     SERIAL_ECHO_START_P(port);
54
-    SERIAL_ECHOLNPGM_P(port, "  G29 I 999");
54
+    SERIAL_ECHOLNPGM_P(port, "  G29 I99");
55
     for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++)
55
     for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++)
56
       for (uint8_t y = 0;  y < GRID_MAX_POINTS_Y; y++)
56
       for (uint8_t y = 0;  y < GRID_MAX_POINTS_Y; y++)
57
         if (!isnan(z_values[x][y])) {
57
         if (!isnan(z_values[x][y])) {
59
           SERIAL_ECHOPAIR_P(port, "  M421 I", x);
59
           SERIAL_ECHOPAIR_P(port, "  M421 I", x);
60
           SERIAL_ECHOPAIR_P(port, " J", y);
60
           SERIAL_ECHOPAIR_P(port, " J", y);
61
           SERIAL_ECHOPGM_P(port, " Z");
61
           SERIAL_ECHOPGM_P(port, " Z");
62
-          SERIAL_ECHO_F_P(port, z_values[x][y], 6);
63
-          SERIAL_ECHOPAIR_P(port, " ; X", LOGICAL_X_POSITION(mesh_index_to_xpos(x)));
64
-          SERIAL_ECHOPAIR_P(port, ", Y", LOGICAL_Y_POSITION(mesh_index_to_ypos(y)));
62
+          SERIAL_ECHO_F_P(port, z_values[x][y], 2);
65
           SERIAL_EOL_P(port);
63
           SERIAL_EOL_P(port);
66
           safe_delay(75); // Prevent Printrun from exploding
64
           safe_delay(75); // Prevent Printrun from exploding
67
         }
65
         }
83
     safe_delay(50);
81
     safe_delay(50);
84
   }
82
   }
85
 
83
 
86
-  static void serial_echo_xy(const int16_t x, const int16_t y) {
87
-    SERIAL_CHAR('(');
88
-    SERIAL_ECHO(x);
89
-    SERIAL_CHAR(',');
90
-    SERIAL_ECHO(y);
91
-    SERIAL_CHAR(')');
92
-    safe_delay(10);
93
-  }
94
-
95
   #if ENABLED(UBL_DEVEL_DEBUGGING)
84
   #if ENABLED(UBL_DEVEL_DEBUGGING)
96
 
85
 
97
     static void debug_echo_axis(const AxisEnum axis) {
86
     static void debug_echo_axis(const AxisEnum axis) {
189
     }
178
     }
190
   }
179
   }
191
 
180
 
192
-  // display_map() currently produces three different mesh map types
193
-  // 0 : suitable for PronterFace and Repetier's serial console
194
-  // 1 : .CSV file suitable for importation into various spread sheets
195
-  // 2 : disply of the map data on a RepRap Graphical LCD Panel
181
+  static void serial_echo_xy(const uint8_t sp, const int16_t x, const int16_t y) {
182
+    SERIAL_ECHO_SP(sp);
183
+    SERIAL_CHAR('(');
184
+    if (x < 100) { SERIAL_CHAR(' '); if (x < 10) SERIAL_CHAR(' '); }
185
+    SERIAL_ECHO(x);
186
+    SERIAL_CHAR(',');
187
+    if (y < 100) { SERIAL_CHAR(' '); if (y < 10) SERIAL_CHAR(' '); }
188
+    SERIAL_ECHO(y);
189
+    SERIAL_CHAR(')');
190
+    safe_delay(5);
191
+  }
192
+
193
+  static void serial_echo_column_labels(const uint8_t sp) {
194
+    SERIAL_ECHO_SP(7);
195
+    for (int8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
196
+      if (i < 10) SERIAL_CHAR(' ');
197
+      SERIAL_ECHO(i);
198
+      SERIAL_ECHO_SP(sp);
199
+    }
200
+    safe_delay(10);
201
+  }
196
 
202
 
203
+  /**
204
+   * Produce one of these mesh maps:
205
+   *   0: Human-readable
206
+   *   1: CSV format for spreadsheet import
207
+   *   2: TODO: Display on Graphical LCD
208
+   *   4: Compact Human-Readable
209
+   */
197
   void unified_bed_leveling::display_map(const int map_type) {
210
   void unified_bed_leveling::display_map(const int map_type) {
198
     #if HAS_AUTO_REPORTING || ENABLED(HOST_KEEPALIVE_FEATURE)
211
     #if HAS_AUTO_REPORTING || ENABLED(HOST_KEEPALIVE_FEATURE)
199
       suspend_auto_report = true;
212
       suspend_auto_report = true;
200
     #endif
213
     #endif
201
 
214
 
202
-    constexpr uint8_t spaces = 8 * (GRID_MAX_POINTS_X - 2);
215
+    constexpr uint8_t eachsp = 1 + 6 + 1,                           // [-3.567]
216
+                      twixt = eachsp * (GRID_MAX_POINTS_X) - 9 * 2; // Leading 4sp, Coordinates 9sp each
203
 
217
 
204
-    SERIAL_PROTOCOLPGM("\nBed Topography Report");
205
-    if (map_type == 0) {
206
-      SERIAL_PROTOCOLPGM(":\n\n");
207
-      serial_echo_xy(0, GRID_MAX_POINTS_Y - 1);
208
-      SERIAL_ECHO_SP(spaces + 3);
209
-      serial_echo_xy(GRID_MAX_POINTS_X - 1, GRID_MAX_POINTS_Y - 1);
210
-      SERIAL_EOL();
211
-      serial_echo_xy(MESH_MIN_X, MESH_MAX_Y);
212
-      SERIAL_ECHO_SP(spaces);
213
-      serial_echo_xy(MESH_MAX_X, MESH_MAX_Y);
218
+    const bool human = !(map_type & 0x3), csv = map_type == 1, lcd = map_type == 2, comp = map_type & 0x4;
219
+
220
+    SERIAL_ECHOPGM("\nBed Topography Report");
221
+    if (human) {
222
+      SERIAL_ECHOPGM(":\n\n");
223
+      serial_echo_xy(4, MESH_MIN_X, MESH_MAX_Y);
224
+      serial_echo_xy(twixt, MESH_MAX_X, MESH_MAX_Y);
214
       SERIAL_EOL();
225
       SERIAL_EOL();
226
+      serial_echo_column_labels(eachsp - 2);
215
     }
227
     }
216
     else {
228
     else {
217
-      SERIAL_PROTOCOLPGM(" for ");
218
-      serialprintPGM(map_type == 1 ? PSTR("CSV:\n\n") : PSTR("LCD:\n\n"));
229
+      SERIAL_ECHOPGM(" for ");
230
+      serialprintPGM(csv ? PSTR("CSV:\n") : PSTR("LCD:\n"));
219
     }
231
     }
220
 
232
 
221
     const float current_xi = get_cell_index_x(current_position[X_AXIS] + (MESH_X_DIST) / 2.0),
233
     const float current_xi = get_cell_index_x(current_position[X_AXIS] + (MESH_X_DIST) / 2.0),
222
                 current_yi = get_cell_index_y(current_position[Y_AXIS] + (MESH_Y_DIST) / 2.0);
234
                 current_yi = get_cell_index_y(current_position[Y_AXIS] + (MESH_Y_DIST) / 2.0);
223
 
235
 
236
+    if (!lcd) SERIAL_EOL();
224
     for (int8_t j = GRID_MAX_POINTS_Y - 1; j >= 0; j--) {
237
     for (int8_t j = GRID_MAX_POINTS_Y - 1; j >= 0; j--) {
238
+
239
+      // Row Label (J index)
240
+      if (human) {
241
+        if (j < 10) SERIAL_CHAR(' ');
242
+        SERIAL_ECHO(j);
243
+        SERIAL_ECHOPGM(" |");
244
+      }
245
+
246
+      // Row Values (I indexes)
225
       for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
247
       for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
226
-        const bool is_current = i == current_xi && j == current_yi;
227
 
248
 
228
-        // is the nozzle here? then mark the number
229
-        if (map_type == 0) SERIAL_CHAR(is_current ? '[' : ' ');
249
+        // Opening Brace or Space
250
+        const bool is_current = i == current_xi && j == current_yi;
251
+        if (human) SERIAL_CHAR(is_current ? '[' : ' ');
230
 
252
 
253
+        // Z Value at current I, J
231
         const float f = z_values[i][j];
254
         const float f = z_values[i][j];
232
-        if (isnan(f)) {
233
-          serialprintPGM(map_type == 0 ? PSTR("    .   ") : PSTR("NAN"));
255
+        if (lcd) {
256
+          // TODO: Display on Graphical LCD
234
         }
257
         }
235
-        else if (map_type <= 1) {
236
-          // if we don't do this, the columns won't line up nicely
237
-          if (map_type == 0 && f >= 0.0) SERIAL_CHAR(' ');
238
-          SERIAL_PROTOCOL_F(f, 3);
258
+        else if (isnan(f))
259
+          serialprintPGM(human ? PSTR("  .   ") : PSTR("NAN"));
260
+        else if (human || csv) {
261
+          if (human && f >= 0.0) SERIAL_CHAR(f > 0 ? '+' : ' ');  // Space for positive ('-' for negative)
262
+          SERIAL_ECHO_F(f, 3);                                    // Positive: 5 digits, Negative: 6 digits
239
         }
263
         }
240
-        idle();
241
-        if (map_type == 1 && i < GRID_MAX_POINTS_X - 1) SERIAL_CHAR(',');
264
+        if (csv && i < GRID_MAX_POINTS_X - 1) SERIAL_CHAR('\t');
265
+
266
+        // Closing Brace or Space
267
+        if (human) SERIAL_CHAR(is_current ? ']' : ' ');
268
+
242
         SERIAL_FLUSHTX();
269
         SERIAL_FLUSHTX();
243
-        safe_delay(15);
244
-        if (map_type == 0) {
245
-          SERIAL_CHAR(is_current ? ']' : ' ');
246
-          SERIAL_CHAR(' ');
247
-        }
248
-      }
249
-      SERIAL_EOL();
250
-      if (j && map_type == 0) { // we want the (0,0) up tight against the block of numbers
251
-        SERIAL_CHAR(' ');
252
-        SERIAL_EOL();
270
+        idle();
253
       }
271
       }
272
+      if (!lcd) SERIAL_EOL();
273
+
274
+      // A blank line between rows (unless compact)
275
+      if (j && human && !comp) SERIAL_ECHOLNPGM("   |");
254
     }
276
     }
255
 
277
 
256
-    if (map_type == 0) {
257
-      serial_echo_xy(MESH_MIN_X, MESH_MIN_Y);
258
-      SERIAL_ECHO_SP(spaces + 4);
259
-      serial_echo_xy(MESH_MAX_X, MESH_MIN_Y);
278
+    if (human) {
279
+      serial_echo_column_labels(eachsp - 2);
280
+      SERIAL_EOL();
281
+      serial_echo_xy(4, MESH_MIN_X, MESH_MIN_Y);
282
+      serial_echo_xy(twixt, MESH_MAX_X, MESH_MIN_Y);
260
       SERIAL_EOL();
283
       SERIAL_EOL();
261
-      serial_echo_xy(0, 0);
262
-      SERIAL_ECHO_SP(spaces + 5);
263
-      serial_echo_xy(GRID_MAX_POINTS_X - 1, 0);
264
       SERIAL_EOL();
284
       SERIAL_EOL();
265
     }
285
     }
266
 
286
 

+ 1
- 3
Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp 查看文件

252
    *                    for subsequent Load and Store operations. Valid storage slot numbers begin at 0 and
252
    *                    for subsequent Load and Store operations. Valid storage slot numbers begin at 0 and
253
    *                    extend to a limit related to the available EEPROM storage.
253
    *                    extend to a limit related to the available EEPROM storage.
254
    *
254
    *
255
-   *   S -1  Store      Store the current Mesh as a print out that is suitable to be feed back into the system
256
-   *                    at a later date. The GCode output can be saved and later replayed by the host software
257
-   *                    to reconstruct the current mesh on another machine.
255
+   *   S -1  Store      Print the current Mesh as G-code that can be used to restore the mesh anytime.
258
    *
256
    *
259
    *   T     Topology   Display the Mesh Map Topology.
257
    *   T     Topology   Display the Mesh Map Topology.
260
    *                    'T' can be used alone (e.g., G29 T) or in combination with most of the other commands.
258
    *                    'T' can be used alone (e.g., G29 T) or in combination with most of the other commands.

+ 2
- 1
Marlin/src/gcode/bedlevel/M420.cpp 查看文件

42
  * With AUTO_BED_LEVELING_UBL only:
42
  * With AUTO_BED_LEVELING_UBL only:
43
  *
43
  *
44
  *   L[index]  Load UBL mesh from index (0 is default)
44
  *   L[index]  Load UBL mesh from index (0 is default)
45
+ *   T[map]    0:Human-readable 1:CSV 2:"LCD" 4:Compact
45
  */
46
  */
46
 void GcodeSuite::M420() {
47
 void GcodeSuite::M420() {
47
 
48
 
80
 
81
 
81
     // L or V display the map info
82
     // L or V display the map info
82
     if (parser.seen('L') || parser.seen('V')) {
83
     if (parser.seen('L') || parser.seen('V')) {
83
-      ubl.display_map(0);  // Currently only supports one map type
84
+      ubl.display_map(parser.byteval('T'));
84
       SERIAL_ECHOLNPAIR("ubl.mesh_is_valid = ", ubl.mesh_is_valid());
85
       SERIAL_ECHOLNPAIR("ubl.mesh_is_valid = ", ubl.mesh_is_valid());
85
       SERIAL_ECHOLNPAIR("ubl.storage_slot = ", ubl.storage_slot);
86
       SERIAL_ECHOLNPAIR("ubl.storage_slot = ", ubl.storage_slot);
86
     }
87
     }

+ 4
- 2
Marlin/src/gcode/bedlevel/ubl/M421.cpp 查看文件

37
  * Usage:
37
  * Usage:
38
  *   M421 I<xindex> J<yindex> Z<linear>
38
  *   M421 I<xindex> J<yindex> Z<linear>
39
  *   M421 I<xindex> J<yindex> Q<offset>
39
  *   M421 I<xindex> J<yindex> Q<offset>
40
+ *   M421 I<xindex> J<yindex> N
40
  *   M421 C Z<linear>
41
  *   M421 C Z<linear>
41
  *   M421 C Q<offset>
42
  *   M421 C Q<offset>
42
  */
43
  */
45
   const bool hasI = ix >= 0,
46
   const bool hasI = ix >= 0,
46
              hasJ = iy >= 0,
47
              hasJ = iy >= 0,
47
              hasC = parser.seen('C'),
48
              hasC = parser.seen('C'),
49
+             hasN = parser.seen('N'),
48
              hasZ = parser.seen('Z'),
50
              hasZ = parser.seen('Z'),
49
              hasQ = !hasZ && parser.seen('Q');
51
              hasQ = !hasZ && parser.seen('Q');
50
 
52
 
54
     iy = location.y_index;
56
     iy = location.y_index;
55
   }
57
   }
56
 
58
 
57
-  if (int(hasC) + int(hasI && hasJ) != 1 || !(hasZ || hasQ)) {
59
+  if (int(hasC) + int(hasI && hasJ) != 1 || !(hasZ || hasQ || hasN)) {
58
     SERIAL_ERROR_START();
60
     SERIAL_ERROR_START();
59
     SERIAL_ERRORLNPGM(MSG_ERR_M421_PARAMETERS);
61
     SERIAL_ERRORLNPGM(MSG_ERR_M421_PARAMETERS);
60
   }
62
   }
63
     SERIAL_ERRORLNPGM(MSG_ERR_MESH_XY);
65
     SERIAL_ERRORLNPGM(MSG_ERR_MESH_XY);
64
   }
66
   }
65
   else
67
   else
66
-    ubl.z_values[ix][iy] = parser.value_linear_units() + (hasQ ? ubl.z_values[ix][iy] : 0);
68
+    ubl.z_values[ix][iy] = hasN ? NAN : parser.value_linear_units() + (hasQ ? ubl.z_values[ix][iy] : 0);
67
 }
69
 }
68
 
70
 
69
 #endif // AUTO_BED_LEVELING_UBL
71
 #endif // AUTO_BED_LEVELING_UBL

Loading…
取消
儲存