Skip to content

Commit a6179ef

Browse files
moham96thinkyhead
authored andcommitted
🚸 Fix, Improve Power-Loss Recovery (MarlinFirmware#22828)
Co-authored-by: Scott Lahteine <[email protected]>
1 parent 918b211 commit a6179ef

File tree

8 files changed

+51
-28
lines changed

8 files changed

+51
-28
lines changed

Marlin/src/feature/powerloss.cpp

+28-15
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ uint32_t PrintJobRecovery::cmd_sdpos, // = 0
5454
#include "../module/temperature.h"
5555
#include "../core/serial.h"
5656

57+
#if HOMING_Z_WITH_PROBE
58+
#include "../module/probe.h"
59+
#endif
60+
5761
#if ENABLED(FWRETRACT)
5862
#include "fwretract.h"
5963
#endif
@@ -178,7 +182,8 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW
178182
info.valid_foot = info.valid_head;
179183

180184
// Machine state
181-
info.current_position = current_position;
185+
// info.sdpos and info.current_position are pre-filled from the Stepper ISR
186+
182187
info.feedrate = uint16_t(MMS_TO_MMM(feedrate_mm_s));
183188
info.zraise = zraise;
184189
info.flag.raised = raised; // Was Z raised before power-off?
@@ -265,6 +270,10 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW
265270

266271
#endif
267272

273+
#endif // POWER_LOSS_PIN
274+
275+
#if PIN_EXISTS(POWER_LOSS) || ENABLED(DEBUG_POWER_LOSS_RECOVERY)
276+
268277
/**
269278
* An outage was detected by a sensor pin.
270279
* - If not SD printing, let the machine turn off on its own with no "KILL" screen
@@ -273,7 +282,7 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW
273282
* - If backup power is available Retract E and Raise Z
274283
* - Go to the KILL screen
275284
*/
276-
void PrintJobRecovery::_outage() {
285+
void PrintJobRecovery::_outage(TERN_(DEBUG_POWER_LOSS_RECOVERY, const bool simulated/*=false*/)) {
277286
#if ENABLED(BACKUP_POWER_SUPPLY)
278287
static bool lock = false;
279288
if (lock) return; // No re-entrance from idle() during retract_and_lift()
@@ -301,10 +310,16 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW
301310
retract_and_lift(zraise);
302311
#endif
303312

304-
kill(GET_TEXT_F(MSG_OUTAGE_RECOVERY));
313+
if (TERN0(DEBUG_POWER_LOSS_RECOVERY, simulated)) {
314+
card.fileHasFinished();
315+
current_position.reset();
316+
sync_plan_position();
317+
}
318+
else
319+
kill(GET_TEXT_F(MSG_OUTAGE_RECOVERY));
305320
}
306321

307-
#endif
322+
#endif // POWER_LOSS_PIN || DEBUG_POWER_LOSS_RECOVERY
308323

309324
/**
310325
* Save the recovery info the recovery file
@@ -390,14 +405,12 @@ void PrintJobRecovery::resume() {
390405

391406
#if ENABLED(POWER_LOSS_RECOVER_ZHOME) && defined(POWER_LOSS_ZHOME_POS)
392407
#define HOMING_Z_DOWN 1
393-
#else
394-
#define HOME_XY_ONLY 1
395408
#endif
396409

397410
float z_now = info.flag.raised ? z_raised : z_print;
398411

399-
// Reset E to 0 and set Z to the real position
400-
#if HOME_XY_ONLY
412+
#if !HOMING_Z_DOWN
413+
// Set Z to the real position
401414
sprintf_P(cmd, PSTR("G92.9Z%s"), dtostrf(z_now, 1, 3, str_1));
402415
gcode.process_subcommands_now(cmd);
403416
#endif
@@ -409,15 +422,15 @@ void PrintJobRecovery::resume() {
409422
gcode.process_subcommands_now(cmd);
410423
}
411424

412-
// Home XY with no Z raise, and also home Z here if Z isn't homing down below.
413-
gcode.process_subcommands_now(F("G28R0" TERN_(HOME_XY_ONLY, "XY"))); // No raise during G28
425+
// Home XY with no Z raise
426+
gcode.process_subcommands_now(F("G28R0XY")); // No raise during G28
414427

415428
#endif
416429

417430
#if HOMING_Z_DOWN
418431
// Move to a safe XY position and home Z while avoiding the print.
419-
constexpr xy_pos_t p = POWER_LOSS_ZHOME_POS;
420-
sprintf_P(cmd, PSTR("G1X%sY%sF1000\nG28Z"), dtostrf(p.x, 1, 3, str_1), dtostrf(p.y, 1, 3, str_2));
432+
const xy_pos_t p = xy_pos_t(POWER_LOSS_ZHOME_POS) TERN_(HOMING_Z_WITH_PROBE, - probe.offset_xy);
433+
sprintf_P(cmd, PSTR("G1X%sY%sF1000\nG28HZ"), dtostrf(p.x, 1, 3, str_1), dtostrf(p.y, 1, 3, str_2));
421434
gcode.process_subcommands_now(cmd);
422435
#endif
423436

@@ -431,7 +444,7 @@ void PrintJobRecovery::resume() {
431444
sprintf_P(cmd, PSTR("M420S%cZ%s"), '0' + (char)info.flag.leveling, dtostrf(info.fade, 1, 1, str_1));
432445
gcode.process_subcommands_now(cmd);
433446

434-
#if HOME_XY_ONLY
447+
#if !HOMING_Z_DOWN
435448
// The physical Z was adjusted at power-off so undo the M420S1 correction to Z with G92.9.
436449
sprintf_P(cmd, PSTR("G92.9Z%s"), dtostrf(z_now, 1, 1, str_1));
437450
gcode.process_subcommands_now(cmd);
@@ -513,12 +526,12 @@ void PrintJobRecovery::resume() {
513526

514527
// Un-retract if there was a retract at outage
515528
#if ENABLED(BACKUP_POWER_SUPPLY) && POWER_LOSS_RETRACT_LEN > 0
516-
gcode.process_subcommands_now(F("G1E" STRINGIFY(POWER_LOSS_RETRACT_LEN) "F3000"));
529+
gcode.process_subcommands_now(F("G1F3000E" STRINGIFY(POWER_LOSS_RETRACT_LEN)));
517530
#endif
518531

519532
// Additional purge on resume if configured
520533
#if POWER_LOSS_PURGE_LEN
521-
sprintf_P(cmd, PSTR("G1 E%d F3000"), (POWER_LOSS_PURGE_LEN) + (POWER_LOSS_RETRACT_LEN));
534+
sprintf_P(cmd, PSTR("G1F3000E%d"), (POWER_LOSS_PURGE_LEN) + (POWER_LOSS_RETRACT_LEN));
522535
gcode.process_subcommands_now(cmd);
523536
#endif
524537

Marlin/src/feature/powerloss.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,9 @@ class PrintJobRecovery {
216216
static void retract_and_lift(const_float_t zraise);
217217
#endif
218218

219-
#if PIN_EXISTS(POWER_LOSS)
219+
#if PIN_EXISTS(POWER_LOSS) || ENABLED(DEBUG_POWER_LOSS_RECOVERY)
220220
friend class GcodeSuite;
221-
static void _outage();
221+
static void _outage(TERN_(DEBUG_POWER_LOSS_RECOVERY, const bool simulated=false));
222222
#endif
223223
};
224224

Marlin/src/gcode/calibrate/G28.cpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -395,9 +395,10 @@ void GcodeSuite::G28() {
395395

396396
TERN_(HOME_Z_FIRST, if (doZ) homeaxis(Z_AXIS));
397397

398-
const float z_homing_height = parser.seenval('R') ? parser.value_linear_units() : Z_HOMING_HEIGHT;
398+
const bool seenR = parser.seenval('R');
399+
const float z_homing_height = seenR ? parser.value_linear_units() : Z_HOMING_HEIGHT;
399400

400-
if (z_homing_height && (LINEAR_AXIS_GANG(doX, || doY, || TERN0(Z_SAFE_HOMING, doZ), || doI, || doJ, || doK))) {
401+
if (z_homing_height && (seenR || LINEAR_AXIS_GANG(doX, || doY, || TERN0(Z_SAFE_HOMING, doZ), || doI, || doJ, || doK))) {
401402
// Raise Z before homing any other axes and z is not already high enough (never lower z)
402403
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Raise Z (before homing) by ", z_homing_height);
403404
do_z_clearance(z_homing_height);
@@ -451,7 +452,11 @@ void GcodeSuite::G28() {
451452
stepper.set_separate_multi_axis(false);
452453
#endif
453454

454-
TERN(Z_SAFE_HOMING, home_z_safely(), homeaxis(Z_AXIS));
455+
#if ENABLED(Z_SAFE_HOMING)
456+
if (TERN1(POWER_LOSS_RECOVERY, !parser.seen_test('H'))) home_z_safely(); else homeaxis(Z_AXIS);
457+
#else
458+
homeaxis(Z_AXIS);
459+
#endif
455460
probe.move_z_after_homing();
456461
}
457462
#endif

Marlin/src/gcode/feature/powerloss/M413.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,8 @@ void GcodeSuite::M413() {
4848
if (parser.seen_test('W')) recovery.save(true);
4949
if (parser.seen_test('P')) recovery.purge();
5050
if (parser.seen_test('D')) recovery.debug(F("M413"));
51-
#if PIN_EXISTS(POWER_LOSS)
52-
if (parser.seen_test('O')) recovery._outage();
53-
#endif
51+
if (parser.seen_test('O')) recovery._outage(true);
52+
if (parser.seen_test('C')) recovery.check();
5453
if (parser.seen_test('E')) SERIAL_ECHOF(recovery.exists() ? F("PLR Exists\n") : F("No PLR\n"));
5554
if (parser.seen_test('V')) SERIAL_ECHOF(recovery.valid() ? F("Valid\n") : F("Invalid\n"));
5655
#endif

Marlin/src/inc/SanityCheck.h

-2
Original file line numberDiff line numberDiff line change
@@ -3451,8 +3451,6 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive.");
34513451
#if ENABLED(POWER_LOSS_RECOVERY)
34523452
#if ENABLED(BACKUP_POWER_SUPPLY) && !PIN_EXISTS(POWER_LOSS)
34533453
#error "BACKUP_POWER_SUPPLY requires a POWER_LOSS_PIN."
3454-
#elif BOTH(POWER_LOSS_RECOVER_ZHOME, Z_SAFE_HOMING)
3455-
#error "POWER_LOSS_RECOVER_ZHOME cannot be used with Z_SAFE_HOMING."
34563454
#elif BOTH(POWER_LOSS_PULLUP, POWER_LOSS_PULLDOWN)
34573455
#error "You can't enable POWER_LOSS_PULLUP and POWER_LOSS_PULLDOWN at the same time."
34583456
#elif ENABLED(POWER_LOSS_RECOVER_ZHOME) && Z_HOME_TO_MAX

Marlin/src/module/planner.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -2809,9 +2809,13 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
28092809

28102810
position = target; // Update the position
28112811

2812+
#if ENABLED(POWER_LOSS_RECOVERY)
2813+
block->sdpos = recovery.command_sdpos();
2814+
block->start_position = position_float.asLogical();
2815+
#endif
2816+
28122817
TERN_(HAS_POSITION_FLOAT, position_float = target_float);
28132818
TERN_(GRADIENT_MIX, mixer.gradient_control(target_float.z));
2814-
TERN_(POWER_LOSS_RECOVERY, block->sdpos = recovery.command_sdpos());
28152819

28162820
return true; // Movement was accepted
28172821

Marlin/src/module/planner.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ typedef struct block_t {
244244

245245
#if ENABLED(POWER_LOSS_RECOVERY)
246246
uint32_t sdpos;
247+
xyze_pos_t start_position;
247248
#endif
248249

249250
#if ENABLED(LASER_POWER_INLINE)
@@ -252,7 +253,7 @@ typedef struct block_t {
252253

253254
} block_t;
254255

255-
#if ANY(LIN_ADVANCE, SCARA_FEEDRATE_SCALING, GRADIENT_MIX, LCD_SHOW_E_TOTAL)
256+
#if ANY(LIN_ADVANCE, SCARA_FEEDRATE_SCALING, GRADIENT_MIX, LCD_SHOW_E_TOTAL, POWER_LOSS_RECOVERY)
256257
#define HAS_POSITION_FLOAT 1
257258
#endif
258259

Marlin/src/module/stepper.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -2151,7 +2151,10 @@ uint32_t Stepper::block_phase_isr() {
21512151
cutter.apply_power(current_block->cutter_power);
21522152
#endif
21532153

2154-
TERN_(POWER_LOSS_RECOVERY, recovery.info.sdpos = current_block->sdpos);
2154+
#if ENABLED(POWER_LOSS_RECOVERY)
2155+
recovery.info.sdpos = current_block->sdpos;
2156+
recovery.info.current_position = current_block->start_position;
2157+
#endif
21552158

21562159
#if ENABLED(DIRECT_STEPPING)
21572160
if (IS_PAGE(current_block)) {

0 commit comments

Comments
 (0)