浏览代码

Improve Power-loss Recovery (#15135)

Scott Lahteine 5 年前
父节点
当前提交
c590e8ac05
没有帐户链接到提交者的电子邮件

+ 3
- 0
Marlin/src/Marlin.cpp 查看文件

@@ -672,6 +672,9 @@ void idle(
672 672
     bool no_stepper_sleep/*=false*/
673 673
   #endif
674 674
 ) {
675
+  #if ENABLED(POWER_LOSS_RECOVERY) && PIN_EXISTS(POWER_LOSS)
676
+    recovery.outage();
677
+  #endif
675 678
 
676 679
   #if ENABLED(SPI_ENDSTOPS)
677 680
     if (endstops.tmc_spi_homing.any

+ 21
- 26
Marlin/src/feature/power_loss_recovery.cpp 查看文件

@@ -36,6 +36,9 @@ bool PrintJobRecovery::enabled; // Initialized by settings.load()
36 36
 SdFile PrintJobRecovery::file;
37 37
 job_recovery_info_t PrintJobRecovery::info;
38 38
 const char PrintJobRecovery::filename[5] = "/PLR";
39
+uint8_t PrintJobRecovery::queue_index_r;
40
+uint32_t PrintJobRecovery::cmd_sdpos, // = 0
41
+         PrintJobRecovery::sdpos[BUFSIZE];
39 42
 
40 43
 #include "../sd/cardreader.h"
41 44
 #include "../lcd/ultralcd.h"
@@ -125,6 +128,14 @@ void PrintJobRecovery::load() {
125 128
 }
126 129
 
127 130
 /**
131
+ * Set info fields that won't change
132
+ */
133
+void PrintJobRecovery::prepare() {
134
+  card.getAbsFilename(info.sd_filename);  // SD filename
135
+  cmd_sdpos = 0;
136
+}
137
+
138
+/**
128 139
  * Save the current machine state to the power-loss recovery file
129 140
  */
130 141
 void PrintJobRecovery::save(const bool force/*=false*/, const bool save_queue/*=true*/) {
@@ -141,9 +152,6 @@ void PrintJobRecovery::save(const bool force/*=false*/, const bool save_queue/*=
141 152
   // Did Z change since the last call?
142 153
   if (force
143 154
     #if DISABLED(SAVE_EACH_CMD_MODE)      // Always save state when enabled
144
-      #if PIN_EXISTS(POWER_LOSS)          // Save if power loss pin is triggered
145
-        || READ(POWER_LOSS_PIN) == POWER_LOSS_STATE
146
-      #endif
147 155
       #if SAVE_INFO_INTERVAL_MS > 0       // Save if interval is elapsed
148 156
         || ELAPSED(ms, next_save_ms)
149 157
       #endif
@@ -211,27 +219,20 @@ void PrintJobRecovery::save(const bool force/*=false*/, const bool save_queue/*=
211 219
     info.relative_mode = relative_mode;
212 220
     info.relative_modes_e = gcode.axis_relative_modes[E_AXIS];
213 221
 
214
-    // Commands in the queue
215
-    info.queue_length = save_queue ? queue.length : 0;
216
-    info.queue_index_r = queue.index_r;
217
-    COPY(info.queue_buffer, queue.command_buffer);
218
-
219 222
     // Elapsed print job time
220 223
     info.print_job_elapsed = print_job_timer.duration();
221 224
 
222
-    // SD file position
223
-    card.getAbsFilename(info.sd_filename);
224
-    info.sdpos = card.getIndex();
225
-
226 225
     write();
227
-
228
-    // KILL now if the power-loss pin was triggered
229
-    #if PIN_EXISTS(POWER_LOSS)
230
-      if (READ(POWER_LOSS_PIN) == POWER_LOSS_STATE) kill(PSTR(MSG_OUTAGE_RECOVERY));
231
-    #endif
232 226
   }
233 227
 }
234 228
 
229
+#if PIN_EXISTS(POWER_LOSS)
230
+  void PrintJobRecovery::_outage() {
231
+    save(true);
232
+    kill(PSTR(MSG_OUTAGE_RECOVERY));
233
+  }
234
+#endif
235
+
235 236
 /**
236 237
  * Save the recovery info the recovery file
237 238
  */
@@ -253,6 +254,8 @@ void PrintJobRecovery::resume() {
253 254
 
254 255
   #define RECOVERY_ZRAISE 2
255 256
 
257
+  const uint32_t resume_sdpos = info.sdpos; // Get here before the stepper ISR overwrites it
258
+
256 259
   #if HAS_LEVELING
257 260
     // Make sure leveling is off before any G92 and G28
258 261
     gcode.process_subcommands_now_P(PSTR("M420 S0 Z0"));
@@ -405,16 +408,11 @@ void PrintJobRecovery::resume() {
405 408
     }
406 409
   #endif
407 410
 
408
-  // Process commands from the old pending queue
409
-  uint8_t c = info.queue_length, r = info.queue_index_r;
410
-  for (; c--; r = (r + 1) % BUFSIZE)
411
-    gcode.process_subcommands_now(info.queue_buffer[r]);
412
-
413 411
   // Resume the SD file from the last position
414 412
   char *fn = info.sd_filename;
415 413
   sprintf_P(cmd, PSTR("M23 %s"), fn);
416 414
   gcode.process_subcommands_now(cmd);
417
-  sprintf_P(cmd, PSTR("M24 S%ld T%ld"), info.sdpos, info.print_job_elapsed);
415
+  sprintf_P(cmd, PSTR("M24 S%ld T%ld"), resume_sdpos, info.print_job_elapsed);
418 416
   gcode.process_subcommands_now(cmd);
419 417
 }
420 418
 
@@ -490,9 +488,6 @@ void PrintJobRecovery::resume() {
490 488
           DEBUG_EOL();
491 489
           DEBUG_ECHOLNPAIR("retract_hop: ", info.retract_hop);
492 490
         #endif
493
-        DEBUG_ECHOLNPAIR("queue_index_r: ", int(info.queue_index_r));
494
-        DEBUG_ECHOLNPAIR("queue_length: ", int(info.queue_length));
495
-        for (uint8_t i = 0; i < info.queue_length; i++) DEBUG_ECHOLNPAIR("> ", info.queue_buffer[i]);
496 491
         DEBUG_ECHOLNPAIR("sd_filename: ", info.sd_filename);
497 492
         DEBUG_ECHOLNPAIR("sdpos: ", info.sdpos);
498 493
         DEBUG_ECHOLNPAIR("print_job_elapsed: ", info.print_job_elapsed);

+ 21
- 5
Marlin/src/feature/power_loss_recovery.h 查看文件

@@ -92,13 +92,9 @@ typedef struct {
92 92
   // Relative mode
93 93
   bool relative_mode, relative_modes_e;
94 94
 
95
-  // Command queue
96
-  uint8_t queue_length, queue_index_r;
97
-  char queue_buffer[BUFSIZE][MAX_CMD_SIZE];
98
-
99 95
   // SD Filename and position
100 96
   char sd_filename[MAXPATHNAMELENGTH];
101
-  uint32_t sdpos;
97
+  volatile uint32_t sdpos;
102 98
 
103 99
   // Job elapsed time
104 100
   millis_t print_job_elapsed;
@@ -114,7 +110,12 @@ class PrintJobRecovery {
114 110
     static SdFile file;
115 111
     static job_recovery_info_t info;
116 112
 
113
+    static uint8_t queue_index_r;     //!< Queue index of the active command
114
+    static uint32_t cmd_sdpos,        //!< SD position of the next command
115
+                    sdpos[BUFSIZE];   //!< SD positions of queued commands
116
+
117 117
     static void init();
118
+    static void prepare();
118 119
 
119 120
     static inline void setup() {
120 121
       #if PIN_EXISTS(POWER_LOSS)
@@ -130,6 +131,10 @@ class PrintJobRecovery {
130 131
       #endif
131 132
     }
132 133
 
134
+    // Track each command's file offsets
135
+    static inline uint32_t command_sdpos() { return sdpos[queue_index_r]; }
136
+    static inline void commit_sdpos(const uint8_t index_w) { sdpos[index_w] = cmd_sdpos; }
137
+
133 138
     static bool enabled;
134 139
     static void enable(const bool onoff);
135 140
     static void changed();
@@ -152,6 +157,13 @@ class PrintJobRecovery {
152 157
       , const bool save_queue=true
153 158
     );
154 159
 
160
+  #if PIN_EXISTS(POWER_LOSS)
161
+    static inline void outage() {
162
+      if (enabled && IS_SD_PRINTING() && READ(POWER_LOSS_PIN) == POWER_LOSS_STATE)
163
+        _outage();
164
+    }
165
+  #endif
166
+
155 167
   static inline bool valid() { return info.valid_head && info.valid_head == info.valid_foot; }
156 168
 
157 169
   #if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
@@ -162,6 +174,10 @@ class PrintJobRecovery {
162 174
 
163 175
   private:
164 176
     static void write();
177
+
178
+  #if PIN_EXISTS(POWER_LOSS)
179
+    static void _outage();
180
+  #endif
165 181
 };
166 182
 
167 183
 extern PrintJobRecovery recovery;

+ 5
- 1
Marlin/src/gcode/gcode.cpp 查看文件

@@ -118,7 +118,7 @@ void GcodeSuite::get_destination_from_command() {
118 118
       destination[i] = current_position[i];
119 119
   }
120 120
 
121
-  #if ENABLED(POWER_LOSS_RECOVERY)
121
+  #if ENABLED(POWER_LOSS_RECOVERY) && !PIN_EXISTS(POWER_LOSS)
122 122
     // Only update power loss recovery on moves with E
123 123
     if (recovery.enabled && IS_SD_PRINTING() && seen[E_AXIS] && (seen[X_AXIS] || seen[Y_AXIS]))
124 124
       recovery.save();
@@ -823,6 +823,10 @@ void GcodeSuite::process_next_command() {
823 823
 
824 824
   PORT_REDIRECT(queue.port[queue.index_r]);
825 825
 
826
+  #if ENABLED(POWER_LOSS_RECOVERY)
827
+    recovery.queue_index_r = queue.index_r;
828
+  #endif
829
+
826 830
   if (DEBUGGING(ECHO)) {
827 831
     SERIAL_ECHO_START();
828 832
     SERIAL_ECHOLN(current_command);

+ 10
- 0
Marlin/src/gcode/queue.cpp 查看文件

@@ -43,6 +43,9 @@ GCodeQueue queue;
43 43
   #include "../feature/binary_protocol.h"
44 44
 #endif
45 45
 
46
+#if ENABLED(POWER_LOSS_RECOVERY)
47
+  #include "../feature/power_loss_recovery.h"
48
+#endif
46 49
 
47 50
 /**
48 51
  * GCode line number handling. Hosts may opt to include line numbers when
@@ -120,6 +123,9 @@ void GCodeQueue::_commit_command(bool say_ok
120 123
   #if NUM_SERIAL > 1
121 124
     port[index_w] = p;
122 125
   #endif
126
+  #if ENABLED(POWER_LOSS_RECOVERY)
127
+    recovery.commit_sdpos(index_w);
128
+  #endif
123 129
   if (++index_w >= BUFSIZE) index_w = 0;
124 130
   length++;
125 131
 }
@@ -557,6 +563,10 @@ void GCodeQueue::get_serial_commands() {
557 563
         sd_count = 0; // clear sd line buffer
558 564
 
559 565
         _commit_command(false);
566
+
567
+        #if ENABLED(POWER_LOSS_RECOVERY)
568
+          recovery.cmd_sdpos = card.getIndex(); // Prime for the next _commit_command
569
+        #endif
560 570
       }
561 571
       else if (sd_count >= MAX_CMD_SIZE - 1) {
562 572
         /**

+ 7
- 0
Marlin/src/gcode/sdcard/M24_M25.cpp 查看文件

@@ -38,6 +38,10 @@
38 38
   #include "../../feature/host_actions.h"
39 39
 #endif
40 40
 
41
+#if ENABLED(POWER_LOSS_RECOVERY)
42
+  #include "../../feature/power_loss_recovery.h"
43
+#endif
44
+
41 45
 /**
42 46
  * M24: Start or Resume SD Print
43 47
  */
@@ -58,6 +62,9 @@ void GcodeSuite::M24() {
58 62
   if (card.isFileOpen()) {
59 63
     card.startFileprint();
60 64
     print_job_timer.start();
65
+    #if ENABLED(POWER_LOSS_RECOVERY)
66
+      recovery.prepare();
67
+    #endif
61 68
   }
62 69
 
63 70
   #if ENABLED(HOST_ACTION_COMMANDS)

+ 8
- 0
Marlin/src/module/planner.cpp 查看文件

@@ -96,6 +96,10 @@
96 96
   #include "../feature/backlash.h"
97 97
 #endif
98 98
 
99
+#if ENABLED(POWER_LOSS_RECOVERY)
100
+  #include "../feature/power_loss_recovery.h"
101
+#endif
102
+
99 103
 // Delay for delivery of first block to the stepper ISR, if the queue contains 2 or
100 104
 // fewer movements. The delay is measured in milliseconds, and must be less than 250ms
101 105
 #define BLOCK_DELAY_FOR_1ST_MOVE 100
@@ -2507,6 +2511,10 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
2507 2511
     mixer.gradient_control(target_float[Z_AXIS]);
2508 2512
   #endif
2509 2513
 
2514
+  #if ENABLED(POWER_LOSS_RECOVERY)
2515
+    block->sdpos = recovery.command_sdpos();
2516
+  #endif
2517
+
2510 2518
   // Movement was accepted
2511 2519
   return true;
2512 2520
 } // _populate_block()

+ 4
- 0
Marlin/src/module/planner.h 查看文件

@@ -159,6 +159,10 @@ typedef struct block_t {
159 159
     uint32_t segment_time_us;
160 160
   #endif
161 161
 
162
+  #if ENABLED(POWER_LOSS_RECOVERY)
163
+    uint32_t sdpos;
164
+  #endif
165
+
162 166
 } block_t;
163 167
 
164 168
 #define HAS_POSITION_FLOAT ANY(LIN_ADVANCE, SCARA_FEEDRATE_SCALING, GRADIENT_MIX)

+ 8
- 0
Marlin/src/module/stepper.cpp 查看文件

@@ -121,6 +121,10 @@ Stepper stepper; // Singleton
121 121
   #include "../libs/L6470/L6470_Marlin.h"
122 122
 #endif
123 123
 
124
+#if ENABLED(POWER_LOSS_RECOVERY)
125
+  #include "../feature/power_loss_recovery.h"
126
+#endif
127
+
124 128
 // public:
125 129
 
126 130
 #if HAS_EXTRA_ENDSTOPS || ENABLED(Z_STEPPER_AUTO_ALIGN)
@@ -1663,6 +1667,10 @@ uint32_t Stepper::stepper_block_phase_isr() {
1663 1667
           return interval; // No more queued movements!
1664 1668
       }
1665 1669
 
1670
+      #if ENABLED(POWER_LOSS_RECOVERY)
1671
+        recovery.info.sdpos = current_block->sdpos;
1672
+      #endif
1673
+
1666 1674
       // Flag all moving axes for proper endstop handling
1667 1675
 
1668 1676
       #if IS_CORE

正在加载...
取消
保存