Fix, improve Power Loss Recovery (#13703)

- Save and restore workspace offsets
- Add retract and purge (hidden) options
- Always restore axis relative modes
- Use added `G92.9` to do position restores
2.0.x
Msq001 6 years ago committed by Scott Lahteine
parent df75a606ff
commit 455ee23499

@ -151,6 +151,12 @@ void PrintJobRecovery::save(const bool force/*=false*/, const bool save_queue/*=
// Machine state
COPY(info.current_position, current_position);
#if HAS_HOME_OFFSET
COPY(info.home_offset, home_offset);
#endif
#if HAS_POSITION_SHIFT
COPY(info.position_shift, position_shift);
#endif
info.feedrate = uint16_t(feedrate_mm_s * 60.0f);
#if HOTENDS > 1
@ -187,7 +193,7 @@ void PrintJobRecovery::save(const bool force/*=false*/, const bool save_queue/*=
info.retract_hop = fwretract.current_hop;
#endif
//relative mode
// Relative mode
info.relative_mode = relative_mode;
info.relative_modes_e = gcode.axis_relative_modes[E_AXIS];
@ -239,9 +245,9 @@ void PrintJobRecovery::resume() {
gcode.process_subcommands_now_P(PSTR("M420 S0 Z0"));
#endif
// Set Z to 0, raise Z by 2mm, and Home (XY only for Cartesian) with no raise
// (Only do simulated homing in Marlin Dev Mode.)
gcode.process_subcommands_now_P(PSTR("G92.0 Z0\nG1 Z" STRINGIFY(RECOVERY_ZRAISE) "\nG28 R0"
// 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.)
gcode.process_subcommands_now_P(PSTR("G92.9 E0 Z0\nG1 Z" STRINGIFY(RECOVERY_ZRAISE) "\nG28 R0"
#if ENABLED(MARLIN_DEV_MODE)
" S"
#elif !IS_KINEMATIC
@ -252,7 +258,7 @@ void PrintJobRecovery::resume() {
// Pretend that all axes are homed
axis_homed = axis_known_position = xyz_bits;
char cmd[40], str_1[16], str_2[16];
char cmd[50], str_1[16], str_2[16];
// Select the previously active tool (with no_move)
#if EXTRUDERS > 1
@ -315,16 +321,16 @@ void PrintJobRecovery::resume() {
memcpy(&mixer.gradient, &info.gradient, sizeof(info.gradient));
#endif
// Restore Z (plus raise) and E positions with G92.0
dtostrf(info.current_position[Z_AXIS] + RECOVERY_ZRAISE, 1, 3, str_1);
dtostrf(info.current_position[E_AXIS]
#if ENABLED(SAVE_EACH_CMD_MODE)
- 5 // Extra extrusion on restart
#endif
, 1, 3, str_2
);
sprintf_P(cmd, PSTR("G92.0 Z%s E%s"), str_1, str_2);
gcode.process_subcommands_now(cmd);
// 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"));
#endif
#if POWER_LOSS_RETRACT_LEN
sprintf_P(cmd, PSTR("G1 E%d F3000"), POWER_LOSS_PURGE_LEN - POWER_LOSS_RETRACT_LEN);
gcode.process_subcommands_now(cmd);
#endif
// Move back to the saved XY
dtostrf(info.current_position[X_AXIS], 1, 3, str_1);
@ -337,13 +343,37 @@ void PrintJobRecovery::resume() {
sprintf_P(cmd, PSTR("G1 Z%s F200"), str_1);
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);
//relative mode
if (info.relative_mode) relative_mode = true;
if (info.relative_modes_e) gcode.axis_relative_modes[E_AXIS] = true;
// Restore E position with G92.9
dtostrf(info.current_position[E_AXIS], 1, 3, str_1);
sprintf_P(cmd, PSTR("G92.9 E%s"), str_1);
gcode.process_subcommands_now(cmd);
// Relative mode
relative_mode = info.relative_mode;
gcode.axis_relative_modes[E_AXIS] = info.relative_modes_e;
#if HAS_HOME_OFFSET || HAS_POSITION_SHIFT
LOOP_XYZ(i) {
#if HAS_HOME_OFFSET
home_offset[i] = info.home_offset[i];
#endif
#if HAS_POSITION_SHIFT
position_shift[i] = info.position_shift[i];
#endif
update_workspace_offset((AxisEnum)i);
}
#endif
// Process commands from the old pending queue
uint8_t c = info.commands_in_queue, r = info.cmd_queue_index_r;
@ -372,6 +402,25 @@ void PrintJobRecovery::resume() {
DEBUG_ECHO(info.current_position[i]);
}
DEBUG_EOL();
#if HAS_HOME_OFFSET
DEBUG_ECHOPGM("home_offset: ");
LOOP_XYZ(i) {
if (i) DEBUG_CHAR(',');
DEBUG_ECHO(info.home_offset[i]);
}
DEBUG_EOL();
#endif
#if HAS_POSITION_SHIFT
DEBUG_ECHOPGM("position_shift: ");
LOOP_XYZ(i) {
if (i) DEBUG_CHAR(',');
DEBUG_ECHO(info.position_shift[i]);
}
DEBUG_EOL();
#endif
DEBUG_ECHOLNPAIR("feedrate: ", info.feedrate);
#if HOTENDS > 1

@ -35,6 +35,8 @@
#define SAVE_INFO_INTERVAL_MS 0
//#define SAVE_EACH_CMD_MODE
//#define DEBUG_POWER_LOSS_RECOVERY
#define POWER_LOSS_PURGE_LEN 20
#define POWER_LOSS_RETRACT_LEN 10
typedef struct {
uint8_t valid_head;
@ -42,6 +44,13 @@ typedef struct {
// Machine state
float current_position[NUM_AXIS];
#if HAS_HOME_OFFSET
float home_offset[XYZ];
#endif
#if HAS_POSITION_SHIFT
float position_shift[XYZ];
#endif
uint16_t feedrate;
#if HOTENDS > 1

@ -33,9 +33,23 @@
*/
void GcodeSuite::G92() {
#if ENABLED(CNC_COORDINATE_SYSTEMS)
switch (parser.subcode) {
case 1:
bool didE = false;
#if IS_SCARA || !HAS_POSITION_SHIFT
bool didXYZ = false;
#else
constexpr bool didXYZ = false;
#endif
#if USE_GCODE_SUBCODES
const uint8_t subcode_G92 = parser.subcode;
#else
constexpr uint8_t subcode_G92 = 0;
#endif
switch (subcode_G92) {
default: break;
#if ENABLED(CNC_COORDINATE_SYSTEMS)
case 1: {
// Zero the G92 values and restore current position
#if !IS_SCARA
LOOP_XYZ(i) {
@ -46,44 +60,42 @@ void GcodeSuite::G92() {
}
}
#endif // Not SCARA
return;
}
#endif
#if ENABLED(CNC_COORDINATE_SYSTEMS)
#define IS_G92_0 (parser.subcode == 0)
#else
#define IS_G92_0 true
#endif
bool didE = false;
#if IS_SCARA || !HAS_POSITION_SHIFT
bool didXYZ = false;
#else
constexpr bool didXYZ = false;
#endif
if (IS_G92_0) LOOP_XYZE(i) {
if (parser.seenval(axis_codes[i])) {
const float l = parser.value_axis_units((AxisEnum)i),
v = i == E_AXIS ? l : LOGICAL_TO_NATIVE(l, i),
d = v - current_position[i];
if (!NEAR_ZERO(d)) {
#if IS_SCARA || !HAS_POSITION_SHIFT
if (i == E_AXIS) didE = true; else didXYZ = true;
current_position[i] = v; // Without workspaces revert to Marlin 1.0 behavior
#elif HAS_POSITION_SHIFT
if (i == E_AXIS) {
didE = true;
current_position[E_AXIS] = v; // When using coordinate spaces, only E is set directly
} return;
#endif
#if ENABLED(POWER_LOSS_RECOVERY)
case 9: {
LOOP_XYZE(i) {
if (parser.seenval(axis_codes[i])) {
current_position[i] = parser.value_axis_units((AxisEnum)i);
if (i == E_AXIS) didE = true; else didXYZ = true;
}
else {
position_shift[i] += d; // Other axes simply offset the coordinate space
update_workspace_offset((AxisEnum)i);
}
} break;
#endif
case 0: {
LOOP_XYZE(i) {
if (parser.seenval(axis_codes[i])) {
const float l = parser.value_axis_units((AxisEnum)i),
v = i == E_AXIS ? l : LOGICAL_TO_NATIVE(l, i),
d = v - current_position[i];
if (!NEAR_ZERO(d)) {
#if IS_SCARA || !HAS_POSITION_SHIFT
if (i == E_AXIS) didE = true; else didXYZ = true;
current_position[i] = v; // Without workspaces revert to Marlin 1.0 behavior
#elif HAS_POSITION_SHIFT
if (i == E_AXIS) {
didE = true;
current_position[E_AXIS] = v; // When using coordinate spaces, only E is set directly
}
else {
position_shift[i] += d; // Other axes simply offset the coordinate space
update_workspace_offset((AxisEnum)i);
}
#endif
}
#endif
}
}
}
} break;
}
#if ENABLED(CNC_COORDINATE_SYSTEMS)

@ -31,9 +31,6 @@
* M23: Open a file
*/
void GcodeSuite::M23() {
#if ENABLED(POWER_LOSS_RECOVERY)
card.removeJobRecoveryFile();
#endif
// Simplify3D includes the size, so zero out all spaces (#7227)
for (char *fn = parser.string_arg; *fn; ++fn) if (*fn == ' ') *fn = '\0';
card.openFile(parser.string_arg, true);

@ -1030,6 +1030,7 @@ void CardReader::printingHasFinished() {
// be zeroed and written instead of deleted.
void CardReader::removeJobRecoveryFile() {
if (jobRecoverFileExists()) {
recovery.init();
removeFile(job_recovery_file_name);
#if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
SERIAL_ECHOPGM("Power-loss file delete");

Loading…
Cancel
Save