Browse Source

Add G29_RETRY_AND_RECOVER feature

- Add an option to retry G29, optionally executing a G-code procedure after each failed probe.
Marcio Teixeira 6 years ago
parent
commit
5cc7916e69

+ 24
- 0
Marlin/Configuration_adv.h View File

@@ -746,6 +746,30 @@
746 746
   //#define MESH_MAX_Y Y_BED_SIZE - (MESH_INSET)
747 747
 #endif
748 748
 
749
+/**
750
+ * Repeatedly attempt G29 leveling until it succeeds.
751
+ * Stop after G29_MAX_RETRIES attempts.
752
+ */
753
+//#define G29_RETRY_AND_RECOVER
754
+#if ENABLED(G29_RETRY_AND_RECOVER)
755
+  #define G29_MAX_RETRIES 3
756
+  #define G29_HALT_ON_FAILURE
757
+  /**
758
+   * Specify the GCODE commands that will be executed when leveling succeeds,
759
+   * between attempts, and after the maximum number of retries have been tried.
760
+   */
761
+  #define G29_SUCCESS_COMMANDS "M117 Bed leveling done."
762
+  #define G29_RECOVER_COMMANDS "M117 Probe failed. Rewiping.\nG28\nG12 P0 S12 T0"
763
+  #define G29_FAILURE_COMMANDS "M117 Bed leveling failed.\nG0 Z10\nM300 P25 S880\nM300 P50 S0\nM300 P25 S880\nM300 P50 S0\nM300 P25 S880\nM300 P50 S0\nG4 S1"
764
+  /**
765
+   * Specify an action command to send to the host on a recovery attempt or failure.
766
+   * Will be sent in the form '//action:ACTION_ON_G29_FAILURE', e.g. '//action:probe_failed'.
767
+   * The host must be configured to handle the action command.
768
+   */
769
+  #define G29_ACTION_ON_RECOVER "probe_rewipe"
770
+  #define G29_ACTION_ON_FAILURE "probe_failed"
771
+#endif
772
+
749 773
 // @section extras
750 774
 
751 775
 //

+ 24
- 0
Marlin/src/config/default/Configuration_adv.h View File

@@ -746,6 +746,30 @@
746 746
   //#define MESH_MAX_Y Y_BED_SIZE - (MESH_INSET)
747 747
 #endif
748 748
 
749
+/**
750
+ * Repeatedly attempt G29 leveling until it succeeds.
751
+ * Stop after G29_MAX_RETRIES attempts.
752
+ */
753
+//#define G29_RETRY_AND_RECOVER
754
+#if ENABLED(G29_RETRY_AND_RECOVER)
755
+  #define G29_MAX_RETRIES 3
756
+  #define G29_HALT_ON_FAILURE
757
+  /**
758
+   * Specify the GCODE commands that will be executed when leveling succeeds,
759
+   * between attempts, and after the maximum number of retries have been tried.
760
+   */
761
+  #define G29_SUCCESS_COMMANDS "M117 Bed leveling done."
762
+  #define G29_RECOVER_COMMANDS "M117 Probe failed. Rewiping.\nG28\nG12 P0 S12 T0"
763
+  #define G29_FAILURE_COMMANDS "M117 Bed leveling failed.\nG0 Z10\nM300 P25 S880\nM300 P50 S0\nM300 P25 S880\nM300 P50 S0\nM300 P25 S880\nM300 P50 S0\nG4 S1"
764
+  /**
765
+   * Specify an action command to send to the host on a recovery attempt or failure.
766
+   * Will be sent in the form '//action:ACTION_ON_G29_FAILURE', e.g. '//action:probe_failed'.
767
+   * The host must be configured to handle the action command.
768
+   */
769
+  #define G29_ACTION_ON_RECOVER "probe_rewipe"
770
+  #define G29_ACTION_ON_FAILURE "probe_failed"
771
+#endif
772
+
749 773
 // @section extras
750 774
 
751 775
 //

+ 91
- 4
Marlin/src/gcode/gcode.cpp View File

@@ -61,6 +61,11 @@ bool GcodeSuite::axis_relative_modes[] = AXIS_RELATIVE_MODES;
61 61
   float GcodeSuite::coordinate_system[MAX_COORDINATE_SYSTEMS][XYZ];
62 62
 #endif
63 63
 
64
+#if HAS_LEVELING && ENABLED(G29_RETRY_AND_RECOVER)
65
+  #include "../feature/bedlevel/bedlevel.h"
66
+  #include "../module/planner.h"
67
+#endif
68
+
64 69
 /**
65 70
  * Set target_extruder from the T parameter or the active_extruder
66 71
  *
@@ -125,6 +130,44 @@ void GcodeSuite::dwell(millis_t time) {
125 130
   while (PENDING(millis(), time)) idle();
126 131
 }
127 132
 
133
+/**
134
+ * When G29_RETRY_AND_RECOVER is enabled, call G29() in
135
+ * a loop with recovery and retry handling.
136
+ */
137
+#if HAS_LEVELING && ENABLED(G29_RETRY_AND_RECOVER)
138
+
139
+  void GcodeSuite::G29_with_retry() {
140
+    set_bed_leveling_enabled(false);
141
+    for (uint8_t i = G29_MAX_RETRIES; i--;) {
142
+      G29();
143
+      if (planner.leveling_active) break;
144
+      #ifdef G29_ACTION_ON_RECOVER
145
+        SERIAL_ECHOLNPGM("//action:" G29_ACTION_ON_RECOVER);
146
+      #endif
147
+      #ifdef G29_RECOVERY_COMMANDS
148
+        process_subcommands_now_P(PSTR(G29_RECOVER_COMMANDS));
149
+      #endif
150
+    }
151
+    if (planner.leveling_active) {
152
+      #ifdef G29_SUCCESS_COMMANDS
153
+        process_subcommands_now_P(PSTR(G29_SUCCESS_COMMANDS));
154
+      #endif
155
+    }
156
+    else {
157
+      #ifdef G29_FAILURE_COMMANDS
158
+        process_subcommands_now_P(PSTR(G29_FAILURE_COMMANDS));
159
+      #endif
160
+      #ifdef G29_ACTION_ON_FAILURE
161
+        SERIAL_ECHOLNPGM("//action:" G29_ACTION_ON_FAILURE);
162
+      #endif
163
+      #if ENABLED(G29_HALT_ON_FAILURE)
164
+        kill(PSTR(MSG_ERR_PROBING_FAILED));
165
+      #endif
166
+    }
167
+  }
168
+
169
+#endif // HAS_LEVELING && G29_RETRY_AND_RECOVER
170
+
128 171
 //
129 172
 // Placeholders for non-migrated codes
130 173
 //
@@ -135,7 +178,11 @@ void GcodeSuite::dwell(millis_t time) {
135 178
 /**
136 179
  * Process the parsed command and dispatch it to its handler
137 180
  */
138
-void GcodeSuite::process_parsed_command() {
181
+void GcodeSuite::process_parsed_command(
182
+  #if ENABLED(USE_EXECUTE_COMMANDS_IMMEDIATE)
183
+    const bool no_ok
184
+  #endif
185
+) {
139 186
   KEEPALIVE_STATE(IN_HANDLER);
140 187
 
141 188
   // Handle a known G, M, or T
@@ -190,8 +237,14 @@ void GcodeSuite::process_parsed_command() {
190 237
       case 28: G28(false); break;                                 // G28: Home all axes, one at a time
191 238
 
192 239
       #if HAS_LEVELING
193
-        case 29: G29(); break;                                    // G29: Bed leveling calibration
194
-      #endif
240
+        case 29:                                                  // G29: Bed leveling calibration
241
+          #if ENABLED(G29_RETRY_AND_RECOVER)
242
+            G29_with_retry();
243
+          #else
244
+            G29();
245
+          #endif
246
+          break;
247
+      #endif // HAS_LEVELING
195 248
 
196 249
       #if HAS_BED_PROBE
197 250
         case 30: G30(); break;                                    // G30: Single Z probe
@@ -612,7 +665,10 @@ void GcodeSuite::process_parsed_command() {
612 665
 
613 666
   KEEPALIVE_STATE(NOT_BUSY);
614 667
 
615
-  ok_to_send();
668
+  #if ENABLED(USE_EXECUTE_COMMANDS_IMMEDIATE)
669
+    if (!no_ok)
670
+  #endif
671
+      ok_to_send();
616 672
 }
617 673
 
618 674
 /**
@@ -638,6 +694,37 @@ void GcodeSuite::process_next_command() {
638 694
   process_parsed_command();
639 695
 }
640 696
 
697
+#if ENABLED(USE_EXECUTE_COMMANDS_IMMEDIATE)
698
+  /**
699
+   * Run a series of commands, bypassing the command queue to allow
700
+   * G-code "macros" to be called from within other G-code handlers.
701
+   */
702
+  void GcodeSuite::process_subcommands_now_P(const char *pgcode) {
703
+    // Save the parser state
704
+    char saved_cmd[strlen(parser.command_ptr) + 1];
705
+    strcpy(saved_cmd, parser.command_ptr);
706
+
707
+    // Process individual commands in string
708
+    while (pgm_read_byte_near(pgcode)) {
709
+      // Break up string at '\n' delimiters
710
+      const char *delim = strchr_P(pgcode, '\n');
711
+      size_t len = delim ? delim - pgcode : strlen_P(pgcode);
712
+      char cmd[len + 1];
713
+      strncpy_P(cmd, pgcode, len);
714
+      cmd[len] = '\0';
715
+      pgcode += len;
716
+      if (delim) pgcode++;
717
+
718
+      // Parse the next command in the string
719
+      parser.parse(cmd);
720
+      process_parsed_command(true);
721
+    }
722
+
723
+    // Restore the parser state
724
+    parser.parse(saved_cmd);
725
+  }
726
+#endif
727
+
641 728
 #if ENABLED(HOST_KEEPALIVE_FEATURE)
642 729
 
643 730
   /**

+ 12
- 1
Marlin/src/gcode/gcode.h View File

@@ -285,9 +285,17 @@ public:
285 285
 
286 286
   static bool get_target_extruder_from_command();
287 287
   static void get_destination_from_command();
288
-  static void process_parsed_command();
288
+  static void process_parsed_command(
289
+    #if ENABLED(USE_EXECUTE_COMMANDS_IMMEDIATE)
290
+      const bool no_ok = false
291
+    #endif
292
+  );
289 293
   static void process_next_command();
290 294
 
295
+  #if ENABLED(USE_EXECUTE_COMMANDS_IMMEDIATE)
296
+    static void process_subcommands_now_P(const char *pgcode);
297
+  #endif
298
+
291 299
   FORCE_INLINE static void home_all_axes() { G28(true); }
292 300
 
293 301
   /**
@@ -380,6 +388,9 @@ private:
380 388
 
381 389
   #if HAS_LEVELING
382 390
     static void G29();
391
+    #if ENABLED(G29_RETRY_AND_RECOVER)
392
+      static void G29_with_retry();
393
+    #endif
383 394
   #endif
384 395
 
385 396
   #if HAS_BED_PROBE

+ 4
- 0
Marlin/src/inc/Conditionals_post.h View File

@@ -1448,4 +1448,8 @@
1448 1448
 // If platform requires early initialization of watchdog to properly boot
1449 1449
 #define EARLY_WATCHDOG (ENABLED(USE_WATCHDOG) && defined(ARDUINO_ARCH_SAM))
1450 1450
 
1451
+#if ENABLED(G29_RETRY_AND_RECOVER)
1452
+  #define USE_EXECUTE_COMMANDS_IMMEDIATE
1453
+#endif
1454
+
1451 1455
 #endif // CONDITIONALS_POST_H

Loading…
Cancel
Save