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 some Power Loss Recovery behaviors #18558

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f247ace
Fix power-loss retract and purge behavior
sjasonsmith Jul 6, 2020
f64d5bb
Update powerloss.cpp
thinkyhead Jul 7, 2020
a863d5d
Merge remote-tracking branch 'upstream/bugfix-2.0.x' into PR/powerlos…
sjasonsmith Jul 7, 2020
b6836dc
Rearrange Unretract, purge, and add clean
thinkyhead Jul 7, 2020
0102edf
Merge remote-tracking branch 'upstream/bugfix-2.0.x' into pr/18558
thinkyhead Jul 7, 2020
a73d295
Move tool-change after heatup
thinkyhead Jul 7, 2020
9503011
No move for heatup Tn
thinkyhead Jul 7, 2020
9a29823
Prevent too much Z raise
thinkyhead Jul 9, 2020
5770a7d
Merge remote-tracking branch 'upstream/bugfix-2.0.x' into pr/18558
thinkyhead Jul 9, 2020
3acc744
fade is a float
thinkyhead Jul 9, 2020
0d7538c
Don't retract twice
thinkyhead Jul 10, 2020
c016329
Clean up a little
thinkyhead Jul 10, 2020
2d3c0d7
Run _outage with no print job
thinkyhead Jul 11, 2020
9b504d4
Ignore power-loss when idle
thinkyhead Jul 12, 2020
2c50a16
Add simulated outage
thinkyhead Jul 12, 2020
29dbe72
Update rambo-tests
thinkyhead Jul 12, 2020
2fc400a
Fix access
thinkyhead Jul 12, 2020
5a77362
Merge remote-tracking branch 'upstream/bugfix-2.0.x' into PR/powerlos…
sjasonsmith Jul 15, 2020
0563675
Add zraise to powerloss debug print
sjasonsmith Jul 15, 2020
537ab2b
Do not disable heaters until after saving thermal manager settings to SD
sjasonsmith Jul 15, 2020
423c35b
Update temperature.cpp
thinkyhead Jul 15, 2020
ede6676
Merge remote-tracking branch 'upstream/bugfix-2.0.x' into pr/18558
thinkyhead Jul 15, 2020
564115a
Easy patch
thinkyhead Jul 15, 2020
2f6a049
Merge branch 'PR/powerloss_retract_purge' of https://github.com/sjaso…
thinkyhead Jul 15, 2020
25d3e47
Clean up disable_all_heaters
thinkyhead Jul 15, 2020
f3d593e
quickie
thinkyhead Jul 15, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Marlin/src/MarlinCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,13 @@ void disable_all_steppers() {
constexpr bool did_pause_print = false;
#endif

/**
* A Print Job exists when the timer is running or SD printing
*/
bool printJobOngoing() {
return print_job_timer.isRunning() || IS_SD_PRINTING();
}

/**
* Printing is active when the print job timer is running
*/
Expand Down Expand Up @@ -690,7 +697,7 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) {

// Handle Power-Loss Recovery
#if ENABLED(POWER_LOSS_RECOVERY) && PIN_EXISTS(POWER_LOSS)
recovery.outage();
if (printJobOngoing()) recovery.outage();
#endif

// Run StallGuard endstop checks
Expand Down
185 changes: 116 additions & 69 deletions Marlin/src/feature/powerloss.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,16 @@ PrintJobRecovery recovery;
#ifndef POWER_LOSS_PURGE_LEN
#define POWER_LOSS_PURGE_LEN 0
#endif
#ifndef POWER_LOSS_ZRAISE
#define POWER_LOSS_ZRAISE 2 // Move on loss with backup power, or on resume without it
#endif

#if DISABLED(BACKUP_POWER_SUPPLY)
#undef POWER_LOSS_RETRACT_LEN // No retract at outage without backup power
#endif
#ifndef POWER_LOSS_RETRACT_LEN
#define POWER_LOSS_RETRACT_LEN 0
#endif
#ifndef POWER_LOSS_ZRAISE
#define POWER_LOSS_ZRAISE 2
#endif

/**
* Clear the recovery info
Expand Down Expand Up @@ -144,7 +148,7 @@ void PrintJobRecovery::prepare() {
/**
* Save the current machine state to the power-loss recovery file
*/
void PrintJobRecovery::save(const bool force/*=false*/) {
void PrintJobRecovery::save(const bool force/*=false*/, const float zraise/*=0*/) {

#if SAVE_INFO_INTERVAL_MS > 0
static millis_t next_save_ms; // = 0
Expand Down Expand Up @@ -177,6 +181,7 @@ void PrintJobRecovery::save(const bool force/*=false*/) {

// Machine state
info.current_position = current_position;
info.zraise = zraise;
TERN_(HAS_HOME_OFFSET, info.home_offset = home_offset);
TERN_(HAS_POSITION_SHIFT, info.position_shift = position_shift);
info.feedrate = uint16_t(feedrate_mm_s * 60.0f);
Expand Down Expand Up @@ -228,30 +233,73 @@ void PrintJobRecovery::save(const bool force/*=false*/) {

#if PIN_EXISTS(POWER_LOSS)

#if ENABLED(BACKUP_POWER_SUPPLY)

void PrintJobRecovery::retract_and_lift(const float &zraise) {
#if POWER_LOSS_RETRACT_LEN || POWER_LOSS_ZRAISE

gcode.set_relative_mode(true); // Use relative coordinates

#if POWER_LOSS_RETRACT_LEN
// Retract filament now
gcode.process_subcommands_now_P(PSTR("G1 F3000 E-" STRINGIFY(POWER_LOSS_RETRACT_LEN)));
#endif

#if POWER_LOSS_ZRAISE
// Raise the Z axis now
if (zraise) {
char cmd[20], str_1[16];
sprintf_P(cmd, PSTR("G0 Z%s"), dtostrf(zraise, 1, 3, str_1));
gcode.process_subcommands_now(cmd);
}
#else
UNUSED(zraise);
#endif

//gcode.axis_relative = info.axis_relative;
planner.synchronize();
#endif
}

#endif

/**
* An outage was detected by a sensor pin.
* - If not SD printing, let the machine turn off on its own with no "KILL" screen
* - Disable all heaters first to save energy
* - Save the recovery data for the current instant
* - If backup power is available Retract E and Raise Z
* - Go to the KILL screen
*/
void PrintJobRecovery::_outage() {
#if ENABLED(BACKUP_POWER_SUPPLY)
static bool lock = false;
if (lock) return; // No re-entrance from idle() during raise_z()
if (lock) return; // No re-entrance from idle() during retract_and_lift()
lock = true;
#endif
if (IS_SD_PRINTING()) save(true);
TERN_(BACKUP_POWER_SUPPLY, raise_z());

kill(GET_TEXT(MSG_OUTAGE_RECOVERY));
}
#if POWER_LOSS_ZRAISE
// Get the limited Z-raise to do now or on resume
const float zraise = _MAX(0, _MIN(current_position.z + POWER_LOSS_ZRAISE, Z_MAX_POS - 1) - current_position.z);
#else
constexpr float zraise = 0;
#endif

#if ENABLED(BACKUP_POWER_SUPPLY)
// Save, including the limited Z raise
if (IS_SD_PRINTING()) save(true, zraise);

// Disable all heaters to reduce power loss
thermalManager.disable_all_heaters();

void PrintJobRecovery::raise_z() {
// Disable all heaters to reduce power loss
thermalManager.disable_all_heaters();
#if ENABLED(BACKUP_POWER_SUPPLY)
// Do a hard-stop of the steppers (with possibly a loud thud)
quickstop_stepper();
// Raise Z axis
gcode.process_subcommands_now_P(PSTR("G91\nG0 Z" STRINGIFY(POWER_LOSS_ZRAISE)));
planner.synchronize();
}
// With backup power a retract and raise can be done now
retract_and_lift(zraise);
#endif

#endif
kill(GET_TEXT(MSG_OUTAGE_RECOVERY));
}

#endif

Expand All @@ -274,6 +322,8 @@ void PrintJobRecovery::write() {
*/
void PrintJobRecovery::resume() {

char cmd[MAX_CMD_SIZE+16], str_1[16], str_2[16];

const uint32_t resume_sdpos = info.sdpos; // Get here before the stepper ISR overwrites it

#if HAS_LEVELING
Expand All @@ -282,52 +332,46 @@ void PrintJobRecovery::resume() {
#endif

// Reset E, raise Z, home XY...
gcode.process_subcommands_now_P(PSTR("G92.9 E0"
#if Z_HOME_DIR > 0
#if Z_HOME_DIR > 0

// If Z homing goes to max, just reset E and home all
"\n"
"G28R0"
TERN_(MARLIN_DEV_MODE, "S")
// If Z homing goes to max, just reset E and home all
gcode.process_subcommands_now_P(PSTR(
"G92.9 E0\n"
"G28R0" TERN_(MARLIN_DEV_MODE, "S")
));

#else // "G92.9 E0 ..."
#else // "G92.9 E0 ..."

// Set Z to 0, raise Z by RECOVERY_ZRAISE, and Home (XY only for Cartesian)
// with no raise. (Only do simulated homing in Marlin Dev Mode.)
#if ENABLED(BACKUP_POWER_SUPPLY)
"Z" STRINGIFY(POWER_LOSS_ZRAISE) // Z-axis was already raised at outage
#else
"Z0\n" // Set Z=0
"G1Z" STRINGIFY(POWER_LOSS_ZRAISE) // Raise Z
#endif
"\n"
// Set Z to 0, raise Z by info.zraise, and Home (XY only for Cartesian)
// with no raise. (Only do simulated homing in Marlin Dev Mode.)

"G28R0"
#if ENABLED(MARLIN_DEV_MODE)
"S"
#elif !IS_KINEMATIC
"XY"
#endif
#endif
));

// Pretend that all axes are homed
axis_homed = axis_known_position = xyz_bits;
sprintf_P(cmd, PSTR("G92.9 E0 "
#if ENABLED(BACKUP_POWER_SUPPLY)
"Z%s" // Z was already raised at outage
#else
"Z0\nG1Z%s" // Set Z=0 and Raise Z now
#endif
),
dtostrf(info.zraise, 1, 3, str_1)
);
gcode.process_subcommands_now(cmd);

char cmd[MAX_CMD_SIZE+16], str_1[16], str_2[16];
gcode.process_subcommands_now_P(PSTR(
"G28R0" // No raise during G28
TERN_(MARLIN_DEV_MODE, "S") // Simulated Homing
TERN_(IS_CARTESIAN, "XY") // Don't home Z on Cartesian
));

// Select the previously active tool (with no_move)
#if EXTRUDERS > 1
sprintf_P(cmd, PSTR("T%i S"), info.active_extruder);
gcode.process_subcommands_now(cmd);
#endif

// Pretend that all axes are homed
axis_homed = axis_known_position = xyz_bits;

// Recover volumetric extrusion state
#if DISABLED(NO_VOLUMETRICS)
#if EXTRUDERS > 1
for (int8_t e = 0; e < EXTRUDERS; e++) {
dtostrf(info.filament_size[e], 1, 3, str_1);
sprintf_P(cmd, PSTR("M200 T%i D%s"), e, str_1);
sprintf_P(cmd, PSTR("M200 T%i D%s"), e, dtostrf(info.filament_size[e], 1, 3, str_1));
gcode.process_subcommands_now(cmd);
}
if (!info.volumetric_enabled) {
Expand All @@ -336,8 +380,7 @@ void PrintJobRecovery::resume() {
}
#else
if (info.volumetric_enabled) {
dtostrf(info.filament_size[0], 1, 3, str_1);
sprintf_P(cmd, PSTR("M200 D%s"), str_1);
sprintf_P(cmd, PSTR("M200 D%s"), dtostrf(info.filament_size[0], 1, 3, str_1));
gcode.process_subcommands_now(cmd);
}
#endif
Expand All @@ -358,7 +401,7 @@ void PrintJobRecovery::resume() {
const int16_t et = info.target_temperature[e];
if (et) {
#if HAS_MULTI_HOTEND
sprintf_P(cmd, PSTR("T%i"), e);
sprintf_P(cmd, PSTR("T%i S"), e);
gcode.process_subcommands_now(cmd);
#endif
sprintf_P(cmd, PSTR("M109 S%i"), et);
Expand All @@ -367,6 +410,12 @@ void PrintJobRecovery::resume() {
}
#endif

// Select the previously active tool (with no_move)
#if EXTRUDERS > 1
sprintf_P(cmd, PSTR("T%i S"), info.active_extruder);
gcode.process_subcommands_now(cmd);
#endif

// Restore print cooling fan speeds
FANS_LOOP(i) {
uint8_t f = info.fan_speed[i];
Expand Down Expand Up @@ -400,18 +449,21 @@ void PrintJobRecovery::resume() {
memcpy(&mixer.gradient, &info.gradient, sizeof(info.gradient));
#endif

// Extrude and retract to clean the nozzle
#if POWER_LOSS_PURGE_LEN
//sprintf_P(cmd, PSTR("G1 E%d F200"), POWER_LOSS_PURGE_LEN);
//gcode.process_subcommands_now(cmd);
gcode.process_subcommands_now_P(PSTR("G1 E" STRINGIFY(POWER_LOSS_PURGE_LEN) " F200"));
// Un-retract if there was a retract at outage
#if POWER_LOSS_RETRACT_LEN
gcode.process_subcommands_now_P(PSTR("G1 E" STRINGIFY(POWER_LOSS_RETRACT_LEN) " F3000"));
#endif

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

#if ENABLED(NOZZLE_CLEAN_FEATURE)
gcode.process_subcommands_now_P(PSTR("G12"));
#endif

// Move back to the saved XY
sprintf_P(cmd, PSTR("G1 X%s Y%s F3000"),
dtostrf(info.current_position.x, 1, 3, str_1),
Expand All @@ -429,13 +481,6 @@ void PrintJobRecovery::resume() {
#endif
gcode.process_subcommands_now(cmd);

// Un-retract
#if POWER_LOSS_PURGE_LEN
//sprintf_P(cmd, PSTR("G1 E%d F3000"), POWER_LOSS_PURGE_LEN);
//gcode.process_subcommands_now(cmd);
gcode.process_subcommands_now_P(PSTR("G1 E" STRINGIFY(POWER_LOSS_PURGE_LEN) " F3000"));
#endif

// Restore the feedrate
sprintf_P(cmd, PSTR("G1 F%d"), info.feedrate);
gcode.process_subcommands_now(cmd);
Expand Down Expand Up @@ -476,6 +521,8 @@ void PrintJobRecovery::resume() {
}
DEBUG_EOL();

DEBUG_ECHOLNPAIR("zraise: ", info.zraise);

#if HAS_HOME_OFFSET
DEBUG_ECHOPGM("home_offset: ");
LOOP_XYZ(i) {
Expand Down
42 changes: 23 additions & 19 deletions Marlin/src/feature/powerloss.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
*/

#include "../sd/cardreader.h"
#include "../gcode/gcode.h"

#include "../inc/MarlinConfig.h"

#if ENABLED(MIXING_EXTRUDER)
Expand All @@ -45,6 +47,7 @@ typedef struct {

// Machine state
xyze_pos_t current_position;
float zraise;

#if HAS_HOME_OFFSET
xyz_pos_t home_offset;
Expand Down Expand Up @@ -161,33 +164,34 @@ class PrintJobRecovery {
static inline void cancel() { purge(); card.autostart_index = 0; }

static void load();
static void save(const bool force=ENABLED(SAVE_EACH_CMD_MODE));
static void save(const bool force=ENABLED(SAVE_EACH_CMD_MODE), const float zraise=0);

#if PIN_EXISTS(POWER_LOSS)
static inline void outage() {
if (enabled && READ(POWER_LOSS_PIN) == POWER_LOSS_STATE)
_outage();
}
#endif
#if PIN_EXISTS(POWER_LOSS)
static inline void outage() {
if (enabled && READ(POWER_LOSS_PIN) == POWER_LOSS_STATE)
_outage();
}
#endif

static inline bool valid() { return info.valid(); }
static inline bool valid() { return info.valid(); }

#if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
static void debug(PGM_P const prefix);
#else
static inline void debug(PGM_P const) {}
#endif
#if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
static void debug(PGM_P const prefix);
#else
static inline void debug(PGM_P const) {}
#endif

private:
static void write();

#if ENABLED(BACKUP_POWER_SUPPLY)
static void raise_z();
#endif
#if ENABLED(BACKUP_POWER_SUPPLY)
static void retract_and_lift(const float &zraise);
#endif

#if PIN_EXISTS(POWER_LOSS)
static void _outage();
#endif
#if PIN_EXISTS(POWER_LOSS)
friend class GcodeSuite;
static void _outage();
#endif
};

extern PrintJobRecovery recovery;
Loading