Skip to content

Commit c8cd824

Browse files
SwiftNickthinkyhead
authored andcommitted
Safe Z homing for Power Loss Recovery (#16909)
1 parent 854ab04 commit c8cd824

6 files changed

Lines changed: 39 additions & 21 deletions

File tree

Marlin/Configuration_adv.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1256,7 +1256,6 @@
12561256
#if ENABLED(POWER_LOSS_RECOVERY)
12571257
#define PLR_ENABLED_DEFAULT false // Power Loss Recovery enabled by default. (Set with 'M413 Sn' & M500)
12581258
//#define BACKUP_POWER_SUPPLY // Backup power / UPS to move the steppers on power loss
1259-
//#define POWER_LOSS_RECOVER_ZHOME // Z homing is needed for proper recovery. 99.9% of the time this should be disabled!
12601259
//#define POWER_LOSS_ZRAISE 2 // (mm) Z axis raise on resume (on power loss with UPS)
12611260
//#define POWER_LOSS_PIN 44 // Pin to detect power loss. Set to -1 to disable default pin on boards without module.
12621261
//#define POWER_LOSS_STATE HIGH // State of pin indicating power loss
@@ -1268,6 +1267,12 @@
12681267
// Without a POWER_LOSS_PIN the following option helps reduce wear on the SD card,
12691268
// especially with "vase mode" printing. Set too high and vases cannot be continued.
12701269
#define POWER_LOSS_MIN_Z_CHANGE 0.05 // (mm) Minimum Z change before saving power-loss data
1270+
1271+
// Enable if Z homing is needed for proper recovery. 99.9% of the time this should be disabled!
1272+
//#define POWER_LOSS_RECOVER_ZHOME
1273+
#if ENABLED(POWER_LOSS_RECOVER_ZHOME)
1274+
//#define POWER_LOSS_ZHOME_POS { 0, 0 } // Safe XY position to home Z while avoiding objects on the bed
1275+
#endif
12711276
#endif
12721277

12731278
/**

Marlin/src/feature/powerloss.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -384,18 +384,25 @@ void PrintJobRecovery::resume() {
384384
// Home safely with no Z raise
385385
gcode.process_subcommands_now_P(PSTR(
386386
"G28R0" // No raise during G28
387-
#if IS_CARTESIAN && DISABLED(POWER_LOSS_RECOVER_ZHOME)
387+
#if IS_CARTESIAN && (DISABLED(POWER_LOSS_RECOVER_ZHOME) || defined(POWER_LOSS_ZHOME_POS))
388388
"XY" // Don't home Z on Cartesian unless overridden
389389
#endif
390390
));
391391

392392
#endif
393393

394-
// Pretend that all axes are homed
394+
#ifdef POWER_LOSS_ZHOME_POS
395+
// If defined move to a safe Z homing position that avoids the print
396+
constexpr xy_pos_t homepos = POWER_LOSS_ZHOME_POS;
397+
sprintf_P(cmd, PSTR("G1 X%s Y%s F1000\nG28Z", dtostrf(homepos.x, 1, 3, str_1), dtostrf(homepos.y, 1, 3, str_2)));
398+
gcode.process_subcommands_now(cmd);
399+
#endif
400+
401+
// Ensure that all axes are marked as homed
395402
set_all_homed();
396403

397404
#if ENABLED(POWER_LOSS_RECOVER_ZHOME)
398-
// Z has been homed so restore Z to ZsavedPos + POWER_LOSS_ZRAISE
405+
// Now move to ZsavedPos + POWER_LOSS_ZRAISE
399406
sprintf_P(cmd, PSTR("G1 F500 Z%s"), dtostrf(info.current_position.z + POWER_LOSS_ZRAISE, 1, 3, str_1));
400407
gcode.process_subcommands_now(cmd);
401408
#endif
@@ -467,7 +474,7 @@ void PrintJobRecovery::resume() {
467474

468475
// Additional purge if configured
469476
#if POWER_LOSS_PURGE_LEN
470-
sprintf_P(cmd, PSTR("G1 E%d F200"), (POWER_LOSS_PURGE_LEN) + (POWER_LOSS_RETRACT_LEN));
477+
sprintf_P(cmd, PSTR("G1 E%d F3000"), (POWER_LOSS_PURGE_LEN) + (POWER_LOSS_RETRACT_LEN));
471478
gcode.process_subcommands_now(cmd);
472479
#endif
473480

@@ -485,7 +492,7 @@ void PrintJobRecovery::resume() {
485492
// Move back to the saved Z
486493
dtostrf(info.current_position.z, 1, 3, str_1);
487494
#if Z_HOME_DIR > 0 || ENABLED(POWER_LOSS_RECOVER_ZHOME)
488-
sprintf_P(cmd, PSTR("G1 Z%s F200"), str_1);
495+
sprintf_P(cmd, PSTR("G1 Z%s F500"), str_1);
489496
#else
490497
gcode.process_subcommands_now_P(PSTR("G1 Z0 F200"));
491498
sprintf_P(cmd, PSTR("G92.9 Z%s"), str_1);

Marlin/src/inc/SanityCheck.h

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,7 +1641,7 @@ static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal
16411641
* Allen Key
16421642
* Deploying the Allen Key probe uses big moves in z direction. Too dangerous for an unhomed z-axis.
16431643
*/
1644-
#if BOTH(Z_PROBE_ALLEN_KEY, Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN) && (Z_HOME_DIR < 0)
1644+
#if BOTH(Z_PROBE_ALLEN_KEY, Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN) && Z_HOME_DIR < 0
16451645
#error "You can't home to a Z min endstop with a Z_PROBE_ALLEN_KEY."
16461646
#endif
16471647

@@ -2913,12 +2913,16 @@ static_assert( _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2)
29132913
#endif
29142914
#endif
29152915

2916-
#if ENABLED(BACKUP_POWER_SUPPLY) && !PIN_EXISTS(POWER_LOSS)
2917-
#error "BACKUP_POWER_SUPPLY requires a POWER_LOSS_PIN."
2918-
#endif
2919-
2920-
#if BOTH(POWER_LOSS_PULLUP, POWER_LOSS_PULLDOWN)
2921-
#error "You can't enable POWER_LOSS_PULLUP and POWER_LOSS_PULLDOWN at the same time."
2916+
#if ENABLED(POWER_LOSS_RECOVERY)
2917+
#if ENABLED(BACKUP_POWER_SUPPLY) && !PIN_EXISTS(POWER_LOSS)
2918+
#error "BACKUP_POWER_SUPPLY requires a POWER_LOSS_PIN."
2919+
#elif BOTH(POWER_LOSS_RECOVER_ZHOME, Z_SAFE_HOMING)
2920+
#error "POWER_LOSS_RECOVER_ZHOME cannot be used with Z_SAFE_HOMING."
2921+
#elif BOTH(POWER_LOSS_PULLUP, POWER_LOSS_PULLDOWN)
2922+
#error "You can't enable POWER_LOSS_PULLUP and POWER_LOSS_PULLDOWN at the same time."
2923+
#elif BOTH(IS_CARTESIAN, POWER_LOSS_RECOVER_ZHOME) && Z_HOME_DIR < 0 && !defined(POWER_LOSS_ZHOME_POS)
2924+
#error "POWER_LOSS_RECOVER_ZHOME requires POWER_LOSS_ZHOME_POS for a Cartesian that homes to ZMIN."
2925+
#endif
29222926
#endif
29232927

29242928
#if ENABLED(Z_STEPPER_AUTO_ALIGN)

Marlin/src/module/probe.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ FORCE_INLINE void probe_specific_action(const bool deploy) {
340340
* - If a preheat input is higher than the current target, raise the target temperature.
341341
* - If a preheat input is higher than the current temperature, wait for stabilization.
342342
*/
343-
void Probe::preheat_for_probing(const uint16_t hotend_temp, const uint16_t bed_temp) {
343+
void Probe::preheat_for_probing(const int16_t hotend_temp, const int16_t bed_temp) {
344344
#if HAS_HOTEND && (PROBING_NOZZLE_TEMP || LEVELING_NOZZLE_TEMP)
345345
#define WAIT_FOR_NOZZLE_HEAT
346346
#endif
@@ -351,17 +351,17 @@ FORCE_INLINE void probe_specific_action(const bool deploy) {
351351
DEBUG_ECHOPGM("Preheating ");
352352

353353
#if ENABLED(WAIT_FOR_NOZZLE_HEAT)
354-
const uint16_t hotendPreheat = hotend_temp > thermalManager.degTargetHotend(0) ? hotend_temp : 0;
354+
const int16_t hotendPreheat = hotend_temp > thermalManager.degTargetHotend(0) ? hotend_temp : 0;
355355
if (hotendPreheat) {
356356
DEBUG_ECHOPAIR("hotend (", hotendPreheat, ")");
357357
thermalManager.setTargetHotend(hotendPreheat, 0);
358358
}
359359
#elif ENABLED(WAIT_FOR_BED_HEAT)
360-
constexpr uint16_t hotendPreheat = 0;
360+
constexpr int16_t hotendPreheat = 0;
361361
#endif
362362

363363
#if ENABLED(WAIT_FOR_BED_HEAT)
364-
const uint16_t bedPreheat = bed_temp > thermalManager.degTargetBed() ? bed_temp : 0;
364+
const int16_t bedPreheat = bed_temp > thermalManager.degTargetBed() ? bed_temp : 0;
365365
if (bedPreheat) {
366366
if (hotendPreheat) DEBUG_ECHOPGM(" and ");
367367
DEBUG_ECHOPAIR("bed (", bedPreheat, ")");

Marlin/src/module/probe.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class Probe {
6161
static xyz_pos_t offset;
6262

6363
#if EITHER(PREHEAT_BEFORE_PROBING, PREHEAT_BEFORE_LEVELING)
64-
static void preheat_for_probing(const uint16_t hotend_temp, const uint16_t bed_temp);
64+
static void preheat_for_probing(const int16_t hotend_temp, const int16_t bed_temp);
6565
#endif
6666

6767
static bool set_deployed(const bool deploy);

buildroot/tests/rambo-tests

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@ opt_add TEMP_CHAMBER_PIN 3
2222
opt_add HEATER_CHAMBER_PIN 45
2323
opt_set GRID_MAX_POINTS_X 16
2424
opt_set FANMUX0_PIN 53
25-
opt_disable USE_WATCHDOG
25+
opt_set Z_HOME_DIR 1
26+
opt_enable USE_ZMAX_PLUG
27+
opt_disable USE_ZMIN_PLUG Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN USE_WATCHDOG
2628
opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER LCD_PROGRESS_BAR LCD_PROGRESS_BAR_TEST \
27-
FIX_MOUNTED_PROBE Z_SAFE_HOMING CODEPENDENT_XY_HOMING PIDTEMPBED PROBE_TEMP_COMPENSATION \
29+
FIX_MOUNTED_PROBE CODEPENDENT_XY_HOMING PIDTEMPBED PROBE_TEMP_COMPENSATION \
2830
PREHEAT_BEFORE_PROBING PROBING_HEATERS_OFF PROBING_FANS_OFF PROBING_STEPPERS_OFF WAIT_FOR_BED_HEATER \
2931
EEPROM_SETTINGS SDSUPPORT SD_REPRINT_LAST_SELECTED_FILE BINARY_FILE_TRANSFER \
3032
BLINKM PCA9533 PCA9632 RGB_LED RGB_LED_R_PIN RGB_LED_G_PIN RGB_LED_B_PIN LED_CONTROL_MENU \
@@ -38,7 +40,7 @@ opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER LCD_PROGRESS_BAR LCD_PROGRESS_BAR_TE
3840
SKEW_CORRECTION SKEW_CORRECTION_FOR_Z SKEW_CORRECTION_GCODE \
3941
BACKLASH_COMPENSATION BACKLASH_GCODE BAUD_RATE_GCODE BEZIER_CURVE_SUPPORT \
4042
FWRETRACT ARC_P_CIRCLES CNC_WORKSPACE_PLANES CNC_COORDINATE_SYSTEMS \
41-
PSU_CONTROL AUTO_POWER_CONTROL POWER_LOSS_RECOVERY POWER_LOSS_PIN POWER_LOSS_STATE \
43+
PSU_CONTROL AUTO_POWER_CONTROL POWER_LOSS_RECOVERY POWER_LOSS_PIN POWER_LOSS_STATE POWER_LOSS_RECOVER_ZHOME \
4244
SLOW_PWM_HEATERS THERMAL_PROTECTION_CHAMBER LIN_ADVANCE EXTRA_LIN_ADVANCE_K \
4345
HOST_ACTION_COMMANDS HOST_PROMPT_SUPPORT PINS_DEBUGGING MAX7219_DEBUG M114_DETAIL
4446
opt_add DEBUG_POWER_LOSS_RECOVERY

0 commit comments

Comments
 (0)