🚸 Fix, Improve Power-Loss Recovery (#22828)

Co-authored-by: Scott Lahteine <github@thinkyhead.com>
This commit is contained in:
MOHAMMAD RASIM 2022-02-09 21:29:34 +03:00 committed by Scott Lahteine
parent 11071c7472
commit 3e18cf2b6a
8 changed files with 51 additions and 28 deletions

View file

@ -54,6 +54,10 @@ uint32_t PrintJobRecovery::cmd_sdpos, // = 0
#include "../module/temperature.h" #include "../module/temperature.h"
#include "../core/serial.h" #include "../core/serial.h"
#if HOMING_Z_WITH_PROBE
#include "../module/probe.h"
#endif
#if ENABLED(FWRETRACT) #if ENABLED(FWRETRACT)
#include "fwretract.h" #include "fwretract.h"
#endif #endif
@ -178,7 +182,8 @@ void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=POW
info.valid_foot = info.valid_head; info.valid_foot = info.valid_head;
// Machine state // 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.feedrate = uint16_t(MMS_TO_MMM(feedrate_mm_s));
info.zraise = zraise; info.zraise = zraise;
info.flag.raised = raised; // Was Z raised before power-off? 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
#endif #endif
#endif // POWER_LOSS_PIN
#if PIN_EXISTS(POWER_LOSS) || ENABLED(DEBUG_POWER_LOSS_RECOVERY)
/** /**
* An outage was detected by a sensor pin. * An outage was detected by a sensor pin.
* - If not SD printing, let the machine turn off on its own with no "KILL" screen * - 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
* - If backup power is available Retract E and Raise Z * - If backup power is available Retract E and Raise Z
* - Go to the KILL screen * - 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) #if ENABLED(BACKUP_POWER_SUPPLY)
static bool lock = false; static bool lock = false;
if (lock) return; // No re-entrance from idle() during retract_and_lift() 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
retract_and_lift(zraise); retract_and_lift(zraise);
#endif #endif
kill(GET_TEXT_F(MSG_OUTAGE_RECOVERY)); if (TERN0(DEBUG_POWER_LOSS_RECOVERY, simulated)) {
card.fileHasFinished();
current_position.reset();
sync_plan_position();
}
else
kill(GET_TEXT_F(MSG_OUTAGE_RECOVERY));
} }
#endif #endif // POWER_LOSS_PIN || DEBUG_POWER_LOSS_RECOVERY
/** /**
* Save the recovery info the recovery file * Save the recovery info the recovery file
@ -390,14 +405,12 @@ void PrintJobRecovery::resume() {
#if ENABLED(POWER_LOSS_RECOVER_ZHOME) && defined(POWER_LOSS_ZHOME_POS) #if ENABLED(POWER_LOSS_RECOVER_ZHOME) && defined(POWER_LOSS_ZHOME_POS)
#define HOMING_Z_DOWN 1 #define HOMING_Z_DOWN 1
#else
#define HOME_XY_ONLY 1
#endif #endif
float z_now = info.flag.raised ? z_raised : z_print; float z_now = info.flag.raised ? z_raised : z_print;
// Reset E to 0 and set Z to the real position #if !HOMING_Z_DOWN
#if HOME_XY_ONLY // Set Z to the real position
sprintf_P(cmd, PSTR("G92.9Z%s"), dtostrf(z_now, 1, 3, str_1)); sprintf_P(cmd, PSTR("G92.9Z%s"), dtostrf(z_now, 1, 3, str_1));
gcode.process_subcommands_now(cmd); gcode.process_subcommands_now(cmd);
#endif #endif
@ -409,15 +422,15 @@ void PrintJobRecovery::resume() {
gcode.process_subcommands_now(cmd); gcode.process_subcommands_now(cmd);
} }
// Home XY with no Z raise, and also home Z here if Z isn't homing down below. // Home XY with no Z raise
gcode.process_subcommands_now(F("G28R0" TERN_(HOME_XY_ONLY, "XY"))); // No raise during G28 gcode.process_subcommands_now(F("G28R0XY")); // No raise during G28
#endif #endif
#if HOMING_Z_DOWN #if HOMING_Z_DOWN
// Move to a safe XY position and home Z while avoiding the print. // Move to a safe XY position and home Z while avoiding the print.
constexpr xy_pos_t p = POWER_LOSS_ZHOME_POS; const xy_pos_t p = xy_pos_t(POWER_LOSS_ZHOME_POS) TERN_(HOMING_Z_WITH_PROBE, - probe.offset_xy);
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));
gcode.process_subcommands_now(cmd); gcode.process_subcommands_now(cmd);
#endif #endif
@ -431,7 +444,7 @@ void PrintJobRecovery::resume() {
sprintf_P(cmd, PSTR("M420S%cZ%s"), '0' + (char)info.flag.leveling, dtostrf(info.fade, 1, 1, str_1)); sprintf_P(cmd, PSTR("M420S%cZ%s"), '0' + (char)info.flag.leveling, dtostrf(info.fade, 1, 1, str_1));
gcode.process_subcommands_now(cmd); 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. // 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)); sprintf_P(cmd, PSTR("G92.9Z%s"), dtostrf(z_now, 1, 1, str_1));
gcode.process_subcommands_now(cmd); gcode.process_subcommands_now(cmd);
@ -513,12 +526,12 @@ void PrintJobRecovery::resume() {
// Un-retract if there was a retract at outage // Un-retract if there was a retract at outage
#if ENABLED(BACKUP_POWER_SUPPLY) && POWER_LOSS_RETRACT_LEN > 0 #if ENABLED(BACKUP_POWER_SUPPLY) && POWER_LOSS_RETRACT_LEN > 0
gcode.process_subcommands_now(F("G1E" STRINGIFY(POWER_LOSS_RETRACT_LEN) "F3000")); gcode.process_subcommands_now(F("G1F3000E" STRINGIFY(POWER_LOSS_RETRACT_LEN)));
#endif #endif
// Additional purge on resume if configured // Additional purge on resume if configured
#if POWER_LOSS_PURGE_LEN #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); gcode.process_subcommands_now(cmd);
#endif #endif

View file

@ -216,9 +216,9 @@ class PrintJobRecovery {
static void retract_and_lift(const_float_t zraise); static void retract_and_lift(const_float_t zraise);
#endif #endif
#if PIN_EXISTS(POWER_LOSS) #if PIN_EXISTS(POWER_LOSS) || ENABLED(DEBUG_POWER_LOSS_RECOVERY)
friend class GcodeSuite; friend class GcodeSuite;
static void _outage(); static void _outage(TERN_(DEBUG_POWER_LOSS_RECOVERY, const bool simulated=false));
#endif #endif
}; };

View file

@ -395,9 +395,10 @@ void GcodeSuite::G28() {
TERN_(HOME_Z_FIRST, if (doZ) homeaxis(Z_AXIS)); 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) // 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); if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Raise Z (before homing) by ", z_homing_height);
do_z_clearance(z_homing_height); do_z_clearance(z_homing_height);
@ -451,7 +452,11 @@ void GcodeSuite::G28() {
stepper.set_separate_multi_axis(false); stepper.set_separate_multi_axis(false);
#endif #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(); probe.move_z_after_homing();
} }
#endif #endif

View file

@ -48,9 +48,8 @@ void GcodeSuite::M413() {
if (parser.seen_test('W')) recovery.save(true); if (parser.seen_test('W')) recovery.save(true);
if (parser.seen_test('P')) recovery.purge(); if (parser.seen_test('P')) recovery.purge();
if (parser.seen_test('D')) recovery.debug(F("M413")); if (parser.seen_test('D')) recovery.debug(F("M413"));
#if PIN_EXISTS(POWER_LOSS) if (parser.seen_test('O')) recovery._outage(true);
if (parser.seen_test('O')) recovery._outage(); if (parser.seen_test('C')) recovery.check();
#endif
if (parser.seen_test('E')) SERIAL_ECHOF(recovery.exists() ? F("PLR Exists\n") : F("No PLR\n")); if (parser.seen_test('E')) SERIAL_ECHOF(recovery.exists() ? F("PLR Exists\n") : F("No PLR\n"));
if (parser.seen_test('V')) SERIAL_ECHOF(recovery.valid() ? F("Valid\n") : F("Invalid\n")); if (parser.seen_test('V')) SERIAL_ECHOF(recovery.valid() ? F("Valid\n") : F("Invalid\n"));
#endif #endif

View file

@ -3440,8 +3440,6 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive.");
#if ENABLED(POWER_LOSS_RECOVERY) #if ENABLED(POWER_LOSS_RECOVERY)
#if ENABLED(BACKUP_POWER_SUPPLY) && !PIN_EXISTS(POWER_LOSS) #if ENABLED(BACKUP_POWER_SUPPLY) && !PIN_EXISTS(POWER_LOSS)
#error "BACKUP_POWER_SUPPLY requires a POWER_LOSS_PIN." #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) #elif BOTH(POWER_LOSS_PULLUP, POWER_LOSS_PULLDOWN)
#error "You can't enable POWER_LOSS_PULLUP and POWER_LOSS_PULLDOWN at the same time." #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 #elif ENABLED(POWER_LOSS_RECOVER_ZHOME) && Z_HOME_TO_MAX

View file

@ -2809,9 +2809,13 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
position = target; // Update the position position = target; // Update the position
#if ENABLED(POWER_LOSS_RECOVERY)
block->sdpos = recovery.command_sdpos();
block->start_position = position_float.asLogical();
#endif
TERN_(HAS_POSITION_FLOAT, position_float = target_float); TERN_(HAS_POSITION_FLOAT, position_float = target_float);
TERN_(GRADIENT_MIX, mixer.gradient_control(target_float.z)); TERN_(GRADIENT_MIX, mixer.gradient_control(target_float.z));
TERN_(POWER_LOSS_RECOVERY, block->sdpos = recovery.command_sdpos());
return true; // Movement was accepted return true; // Movement was accepted

View file

@ -244,6 +244,7 @@ typedef struct block_t {
#if ENABLED(POWER_LOSS_RECOVERY) #if ENABLED(POWER_LOSS_RECOVERY)
uint32_t sdpos; uint32_t sdpos;
xyze_pos_t start_position;
#endif #endif
#if ENABLED(LASER_POWER_INLINE) #if ENABLED(LASER_POWER_INLINE)
@ -252,7 +253,7 @@ typedef struct block_t {
} 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 #define HAS_POSITION_FLOAT 1
#endif #endif

View file

@ -2151,7 +2151,10 @@ uint32_t Stepper::block_phase_isr() {
cutter.apply_power(current_block->cutter_power); cutter.apply_power(current_block->cutter_power);
#endif #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 ENABLED(DIRECT_STEPPING)
if (IS_PAGE(current_block)) { if (IS_PAGE(current_block)) {