Browse Source

Improve Power-loss Recovery (#15135)

Scott Lahteine 5 years ago
parent
commit
c590e8ac05
No account linked to committer's email address

+ 3
- 0
Marlin/src/Marlin.cpp View File

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

+ 21
- 26
Marlin/src/feature/power_loss_recovery.cpp View File

36
 SdFile PrintJobRecovery::file;
36
 SdFile PrintJobRecovery::file;
37
 job_recovery_info_t PrintJobRecovery::info;
37
 job_recovery_info_t PrintJobRecovery::info;
38
 const char PrintJobRecovery::filename[5] = "/PLR";
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
 #include "../sd/cardreader.h"
43
 #include "../sd/cardreader.h"
41
 #include "../lcd/ultralcd.h"
44
 #include "../lcd/ultralcd.h"
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
  * Save the current machine state to the power-loss recovery file
139
  * Save the current machine state to the power-loss recovery file
129
  */
140
  */
130
 void PrintJobRecovery::save(const bool force/*=false*/, const bool save_queue/*=true*/) {
141
 void PrintJobRecovery::save(const bool force/*=false*/, const bool save_queue/*=true*/) {
141
   // Did Z change since the last call?
152
   // Did Z change since the last call?
142
   if (force
153
   if (force
143
     #if DISABLED(SAVE_EACH_CMD_MODE)      // Always save state when enabled
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
       #if SAVE_INFO_INTERVAL_MS > 0       // Save if interval is elapsed
155
       #if SAVE_INFO_INTERVAL_MS > 0       // Save if interval is elapsed
148
         || ELAPSED(ms, next_save_ms)
156
         || ELAPSED(ms, next_save_ms)
149
       #endif
157
       #endif
211
     info.relative_mode = relative_mode;
219
     info.relative_mode = relative_mode;
212
     info.relative_modes_e = gcode.axis_relative_modes[E_AXIS];
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
     // Elapsed print job time
222
     // Elapsed print job time
220
     info.print_job_elapsed = print_job_timer.duration();
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
     write();
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
  * Save the recovery info the recovery file
237
  * Save the recovery info the recovery file
237
  */
238
  */
253
 
254
 
254
   #define RECOVERY_ZRAISE 2
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
   #if HAS_LEVELING
259
   #if HAS_LEVELING
257
     // Make sure leveling is off before any G92 and G28
260
     // Make sure leveling is off before any G92 and G28
258
     gcode.process_subcommands_now_P(PSTR("M420 S0 Z0"));
261
     gcode.process_subcommands_now_P(PSTR("M420 S0 Z0"));
405
     }
408
     }
406
   #endif
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
   // Resume the SD file from the last position
411
   // Resume the SD file from the last position
414
   char *fn = info.sd_filename;
412
   char *fn = info.sd_filename;
415
   sprintf_P(cmd, PSTR("M23 %s"), fn);
413
   sprintf_P(cmd, PSTR("M23 %s"), fn);
416
   gcode.process_subcommands_now(cmd);
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
   gcode.process_subcommands_now(cmd);
416
   gcode.process_subcommands_now(cmd);
419
 }
417
 }
420
 
418
 
490
           DEBUG_EOL();
488
           DEBUG_EOL();
491
           DEBUG_ECHOLNPAIR("retract_hop: ", info.retract_hop);
489
           DEBUG_ECHOLNPAIR("retract_hop: ", info.retract_hop);
492
         #endif
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
         DEBUG_ECHOLNPAIR("sd_filename: ", info.sd_filename);
491
         DEBUG_ECHOLNPAIR("sd_filename: ", info.sd_filename);
497
         DEBUG_ECHOLNPAIR("sdpos: ", info.sdpos);
492
         DEBUG_ECHOLNPAIR("sdpos: ", info.sdpos);
498
         DEBUG_ECHOLNPAIR("print_job_elapsed: ", info.print_job_elapsed);
493
         DEBUG_ECHOLNPAIR("print_job_elapsed: ", info.print_job_elapsed);

+ 21
- 5
Marlin/src/feature/power_loss_recovery.h View File

92
   // Relative mode
92
   // Relative mode
93
   bool relative_mode, relative_modes_e;
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
   // SD Filename and position
95
   // SD Filename and position
100
   char sd_filename[MAXPATHNAMELENGTH];
96
   char sd_filename[MAXPATHNAMELENGTH];
101
-  uint32_t sdpos;
97
+  volatile uint32_t sdpos;
102
 
98
 
103
   // Job elapsed time
99
   // Job elapsed time
104
   millis_t print_job_elapsed;
100
   millis_t print_job_elapsed;
114
     static SdFile file;
110
     static SdFile file;
115
     static job_recovery_info_t info;
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
     static void init();
117
     static void init();
118
+    static void prepare();
118
 
119
 
119
     static inline void setup() {
120
     static inline void setup() {
120
       #if PIN_EXISTS(POWER_LOSS)
121
       #if PIN_EXISTS(POWER_LOSS)
130
       #endif
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
     static bool enabled;
138
     static bool enabled;
134
     static void enable(const bool onoff);
139
     static void enable(const bool onoff);
135
     static void changed();
140
     static void changed();
152
       , const bool save_queue=true
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
   static inline bool valid() { return info.valid_head && info.valid_head == info.valid_foot; }
167
   static inline bool valid() { return info.valid_head && info.valid_head == info.valid_foot; }
156
 
168
 
157
   #if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
169
   #if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
162
 
174
 
163
   private:
175
   private:
164
     static void write();
176
     static void write();
177
+
178
+  #if PIN_EXISTS(POWER_LOSS)
179
+    static void _outage();
180
+  #endif
165
 };
181
 };
166
 
182
 
167
 extern PrintJobRecovery recovery;
183
 extern PrintJobRecovery recovery;

+ 5
- 1
Marlin/src/gcode/gcode.cpp View File

118
       destination[i] = current_position[i];
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
     // Only update power loss recovery on moves with E
122
     // Only update power loss recovery on moves with E
123
     if (recovery.enabled && IS_SD_PRINTING() && seen[E_AXIS] && (seen[X_AXIS] || seen[Y_AXIS]))
123
     if (recovery.enabled && IS_SD_PRINTING() && seen[E_AXIS] && (seen[X_AXIS] || seen[Y_AXIS]))
124
       recovery.save();
124
       recovery.save();
823
 
823
 
824
   PORT_REDIRECT(queue.port[queue.index_r]);
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
   if (DEBUGGING(ECHO)) {
830
   if (DEBUGGING(ECHO)) {
827
     SERIAL_ECHO_START();
831
     SERIAL_ECHO_START();
828
     SERIAL_ECHOLN(current_command);
832
     SERIAL_ECHOLN(current_command);

+ 10
- 0
Marlin/src/gcode/queue.cpp View File

43
   #include "../feature/binary_protocol.h"
43
   #include "../feature/binary_protocol.h"
44
 #endif
44
 #endif
45
 
45
 
46
+#if ENABLED(POWER_LOSS_RECOVERY)
47
+  #include "../feature/power_loss_recovery.h"
48
+#endif
46
 
49
 
47
 /**
50
 /**
48
  * GCode line number handling. Hosts may opt to include line numbers when
51
  * GCode line number handling. Hosts may opt to include line numbers when
120
   #if NUM_SERIAL > 1
123
   #if NUM_SERIAL > 1
121
     port[index_w] = p;
124
     port[index_w] = p;
122
   #endif
125
   #endif
126
+  #if ENABLED(POWER_LOSS_RECOVERY)
127
+    recovery.commit_sdpos(index_w);
128
+  #endif
123
   if (++index_w >= BUFSIZE) index_w = 0;
129
   if (++index_w >= BUFSIZE) index_w = 0;
124
   length++;
130
   length++;
125
 }
131
 }
557
         sd_count = 0; // clear sd line buffer
563
         sd_count = 0; // clear sd line buffer
558
 
564
 
559
         _commit_command(false);
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
       else if (sd_count >= MAX_CMD_SIZE - 1) {
571
       else if (sd_count >= MAX_CMD_SIZE - 1) {
562
         /**
572
         /**

+ 7
- 0
Marlin/src/gcode/sdcard/M24_M25.cpp View File

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

+ 8
- 0
Marlin/src/module/planner.cpp View File

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

+ 4
- 0
Marlin/src/module/planner.h View File

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

+ 8
- 0
Marlin/src/module/stepper.cpp View File

121
   #include "../libs/L6470/L6470_Marlin.h"
121
   #include "../libs/L6470/L6470_Marlin.h"
122
 #endif
122
 #endif
123
 
123
 
124
+#if ENABLED(POWER_LOSS_RECOVERY)
125
+  #include "../feature/power_loss_recovery.h"
126
+#endif
127
+
124
 // public:
128
 // public:
125
 
129
 
126
 #if HAS_EXTRA_ENDSTOPS || ENABLED(Z_STEPPER_AUTO_ALIGN)
130
 #if HAS_EXTRA_ENDSTOPS || ENABLED(Z_STEPPER_AUTO_ALIGN)
1663
           return interval; // No more queued movements!
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
       // Flag all moving axes for proper endstop handling
1674
       // Flag all moving axes for proper endstop handling
1667
 
1675
 
1668
       #if IS_CORE
1676
       #if IS_CORE

Loading…
Cancel
Save