Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix, Improve Power-Loss Recovery #22828

Merged
merged 13 commits into from
Feb 9, 2022
41 changes: 25 additions & 16 deletions Marlin/src/feature/powerloss.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,8 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW
info.valid_foot = info.valid_head;

// Machine state
info.current_position = current_position;
// info.sdpos and info.current_position are pre-filled from the Stepper ISR

info.feedrate = uint16_t(MMS_TO_MMM(feedrate_mm_s));
info.zraise = zraise;
info.flag.raised = raised; // Was Z raised before power-off?
Expand Down Expand Up @@ -265,6 +266,10 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW

#endif

#endif // POWER_LOSS_PIN

#if PIN_EXISTS(POWER_LOSS) || ENABLED(DEBUG_POWER_LOSS_RECOVERY)

/**
* An outage was detected by a sensor pin.
* - If not SD printing, let the machine turn off on its own with no "KILL" screen
Expand All @@ -273,7 +278,7 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW
* - If backup power is available Retract E and Raise Z
* - Go to the KILL screen
*/
void PrintJobRecovery::_outage() {
void PrintJobRecovery::_outage(TERN_(DEBUG_POWER_LOSS_RECOVERY, const bool simulated/*=false*/)) {
#if ENABLED(BACKUP_POWER_SUPPLY)
static bool lock = false;
if (lock) return; // No re-entrance from idle() during retract_and_lift()
Expand Down Expand Up @@ -301,10 +306,16 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW
retract_and_lift(zraise);
#endif

kill(GET_TEXT(MSG_OUTAGE_RECOVERY));
if (TERN0(DEBUG_POWER_LOSS_RECOVERY, simulated)) {
card.fileHasFinished();
current_position.reset();
sync_plan_position();
}
else
kill(GET_TEXT(MSG_OUTAGE_RECOVERY));
}

#endif
#endif // POWER_LOSS_PIN || DEBUG_POWER_LOSS_RECOVERY

/**
* Save the recovery info the recovery file
Expand Down Expand Up @@ -373,10 +384,10 @@ void PrintJobRecovery::resume() {
// establish the current position as best we can.
//

gcode.process_subcommands_now_P(PSTR("G92.9E0")); // Reset E to 0

#if Z_HOME_TO_MAX

gcode.process_subcommands_now_P(PSTR("G92.9E0")); // Reset E to 0

float z_now = z_raised;

// If Z homing goes to max then just move back to the "raised" position
Expand All @@ -390,15 +401,13 @@ void PrintJobRecovery::resume() {

#if ENABLED(POWER_LOSS_RECOVER_ZHOME) && defined(POWER_LOSS_ZHOME_POS)
#define HOMING_Z_DOWN 1
#else
#define HOME_XY_ONLY 1
#endif

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

// Reset E to 0 and set Z to the real position
thinkyhead marked this conversation as resolved.
Show resolved Hide resolved
#if HOME_XY_ONLY
sprintf_P(cmd, PSTR("G92.9Z%s"), dtostrf(z_now, 1, 3, str_1));
#if !HOMING_Z_DOWN
sprintf_P(cmd, PSTR("G92.9E0Z%s"), dtostrf(z_now, 1, 3, str_1));
gcode.process_subcommands_now(cmd);
#endif

Expand All @@ -409,15 +418,15 @@ void PrintJobRecovery::resume() {
gcode.process_subcommands_now(cmd);
}

// Home XY with no Z raise, and also home Z here if Z isn't homing down below.
gcode.process_subcommands_now_P(PSTR("G28R0" TERN_(HOME_XY_ONLY, "XY"))); // No raise during G28
// Home XY with no Z raise
gcode.process_subcommands_now_P(PSTR("G28R0XY")); // No raise during G28

#endif

#if HOMING_Z_DOWN
// Move to a safe XY position and home Z while avoiding the print.
constexpr xy_pos_t p = POWER_LOSS_ZHOME_POS;
sprintf_P(cmd, PSTR("G1X%sY%sF1000\nG28Z"), dtostrf(p.x, 1, 3, str_1), dtostrf(p.y, 1, 3, str_2));
sprintf_P(cmd, PSTR("G1X%sY%sF1000\nG28HZ"), dtostrf(p.x, 1, 3, str_1), dtostrf(p.y, 1, 3, str_2));
thinkyhead marked this conversation as resolved.
Show resolved Hide resolved
gcode.process_subcommands_now(cmd);
#endif

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

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

// Un-retract if there was a retract at outage
#if ENABLED(BACKUP_POWER_SUPPLY) && POWER_LOSS_RETRACT_LEN > 0
gcode.process_subcommands_now_P(PSTR("G1E" STRINGIFY(POWER_LOSS_RETRACT_LEN) "F3000"));
gcode.process_subcommands_now_P(PSTR("G1F3000E" STRINGIFY(POWER_LOSS_RETRACT_LEN)));
#endif

// Additional purge on resume if configured
#if POWER_LOSS_PURGE_LEN
sprintf_P(cmd, PSTR("G1 E%d F3000"), (POWER_LOSS_PURGE_LEN) + (POWER_LOSS_RETRACT_LEN));
sprintf_P(cmd, PSTR("G1F3000E%d"), (POWER_LOSS_PURGE_LEN) + (POWER_LOSS_RETRACT_LEN));
gcode.process_subcommands_now(cmd);
#endif

Expand Down
4 changes: 2 additions & 2 deletions Marlin/src/feature/powerloss.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,9 @@ class PrintJobRecovery {
static void retract_and_lift(const_float_t zraise);
#endif

#if PIN_EXISTS(POWER_LOSS)
#if PIN_EXISTS(POWER_LOSS) || ENABLED(DEBUG_POWER_LOSS_RECOVERY)
friend class GcodeSuite;
static void _outage();
static void _outage(TERN_(DEBUG_POWER_LOSS_RECOVERY, const bool simulated=false));
#endif
};

Expand Down
11 changes: 8 additions & 3 deletions Marlin/src/gcode/calibrate/G28.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,9 +367,10 @@ void GcodeSuite::G28() {

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

const float z_homing_height = parser.seenval('R') ? parser.value_linear_units() : Z_HOMING_HEIGHT;
const bool seenR = parser.seenval('R');
const float z_homing_height = seenR ? parser.value_linear_units() : Z_HOMING_HEIGHT;

if (z_homing_height && (LINEAR_AXIS_GANG(doX, || doY, || TERN0(Z_SAFE_HOMING, doZ), || doI, || doJ, || doK))) {
if (z_homing_height && (seenR || LINEAR_AXIS_GANG(doX, || doY, || TERN0(Z_SAFE_HOMING, doZ), || doI, || doJ, || doK))) {
// Raise Z before homing any other axes and z is not already high enough (never lower z)
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Raise Z (before homing) by ", z_homing_height);
do_z_clearance(z_homing_height);
Expand Down Expand Up @@ -423,7 +424,11 @@ void GcodeSuite::G28() {
stepper.set_separate_multi_axis(false);
#endif

TERN(Z_SAFE_HOMING, home_z_safely(), homeaxis(Z_AXIS));
#if ENABLED(Z_SAFE_HOMING)
if (TERN1(POWER_LOSS_RECOVERY, !parser.seen_test('H'))) home_z_safely(); else homeaxis(Z_AXIS);
#else
homeaxis(Z_AXIS);
#endif
probe.move_z_after_homing();
}
#endif
Expand Down
5 changes: 2 additions & 3 deletions Marlin/src/gcode/feature/powerloss/M413.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,8 @@ void GcodeSuite::M413() {
if (parser.seen_test('W')) recovery.save(true);
if (parser.seen_test('P')) recovery.purge();
if (parser.seen_test('D')) recovery.debug(PSTR("M413"));
#if PIN_EXISTS(POWER_LOSS)
if (parser.seen_test('O')) recovery._outage();
#endif
if (parser.seen_test('O')) recovery._outage();
thinkyhead marked this conversation as resolved.
Show resolved Hide resolved
if (parser.seen_test('C')) recovery.check();
if (parser.seen_test('E')) SERIAL_ECHOPGM_P(recovery.exists() ? PSTR("PLR Exists\n") : PSTR("No PLR\n"));
if (parser.seen_test('V')) SERIAL_ECHOPGM_P(recovery.valid() ? PSTR("Valid\n") : PSTR("Invalid\n"));
#endif
Expand Down
2 changes: 0 additions & 2 deletions Marlin/src/inc/SanityCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -3364,8 +3364,6 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive.");
#if ENABLED(POWER_LOSS_RECOVERY)
#if ENABLED(BACKUP_POWER_SUPPLY) && !PIN_EXISTS(POWER_LOSS)
#error "BACKUP_POWER_SUPPLY requires a POWER_LOSS_PIN."
#elif BOTH(POWER_LOSS_RECOVER_ZHOME, Z_SAFE_HOMING)
#error "POWER_LOSS_RECOVER_ZHOME cannot be used with Z_SAFE_HOMING."
#elif BOTH(POWER_LOSS_PULLUP, POWER_LOSS_PULLDOWN)
#error "You can't enable POWER_LOSS_PULLUP and POWER_LOSS_PULLDOWN at the same time."
#elif ENABLED(POWER_LOSS_RECOVER_ZHOME) && Z_HOME_TO_MAX
Expand Down
6 changes: 5 additions & 1 deletion Marlin/src/module/planner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2816,9 +2816,13 @@ bool Planner::_populate_block(block_t * const block, bool split_move,

position = target; // Update the position

#if ENABLED(POWER_LOSS_RECOVERY)
block->sdpos = recovery.command_sdpos();
block->start_position = position_float;
#endif

TERN_(HAS_POSITION_FLOAT, position_float = target_float);
TERN_(GRADIENT_MIX, mixer.gradient_control(target_float.z));
TERN_(POWER_LOSS_RECOVERY, block->sdpos = recovery.command_sdpos());

return true; // Movement was accepted

Expand Down
3 changes: 2 additions & 1 deletion Marlin/src/module/planner.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ typedef struct block_t {

#if ENABLED(POWER_LOSS_RECOVERY)
uint32_t sdpos;
xyze_pos_t start_position;
#endif

#if ENABLED(LASER_POWER_INLINE)
Expand All @@ -248,7 +249,7 @@ typedef struct block_t {

} block_t;

#if ANY(LIN_ADVANCE, SCARA_FEEDRATE_SCALING, GRADIENT_MIX, LCD_SHOW_E_TOTAL)
#if ANY(LIN_ADVANCE, SCARA_FEEDRATE_SCALING, GRADIENT_MIX, LCD_SHOW_E_TOTAL, POWER_LOSS_RECOVERY)
#define HAS_POSITION_FLOAT 1
#endif

Expand Down
5 changes: 4 additions & 1 deletion Marlin/src/module/stepper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2070,7 +2070,10 @@ uint32_t Stepper::block_phase_isr() {
cutter.apply_power(current_block->cutter_power);
#endif

TERN_(POWER_LOSS_RECOVERY, recovery.info.sdpos = current_block->sdpos);
#if ENABLED(POWER_LOSS_RECOVERY)
recovery.info.sdpos = current_block->sdpos;
recovery.info.current_position = current_block->start_position;
#endif

#if ENABLED(DIRECT_STEPPING)
if (IS_PAGE(current_block)) {
Expand Down