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
This commit is contained in:
Msq001 2019-04-16 07:53:39 +08:00 committed by Scott Lahteine
parent df75a606ff
commit 455ee23499
5 changed files with 127 additions and 59 deletions

View file

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

View file

@ -35,6 +35,8 @@
#define SAVE_INFO_INTERVAL_MS 0 #define SAVE_INFO_INTERVAL_MS 0
//#define SAVE_EACH_CMD_MODE //#define SAVE_EACH_CMD_MODE
//#define DEBUG_POWER_LOSS_RECOVERY //#define DEBUG_POWER_LOSS_RECOVERY
#define POWER_LOSS_PURGE_LEN 20
#define POWER_LOSS_RETRACT_LEN 10
typedef struct { typedef struct {
uint8_t valid_head; uint8_t valid_head;
@ -42,6 +44,13 @@ typedef struct {
// Machine state // Machine state
float current_position[NUM_AXIS]; 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; uint16_t feedrate;
#if HOTENDS > 1 #if HOTENDS > 1

View file

@ -33,9 +33,23 @@
*/ */
void GcodeSuite::G92() { void GcodeSuite::G92() {
#if ENABLED(CNC_COORDINATE_SYSTEMS) bool didE = false;
switch (parser.subcode) { #if IS_SCARA || !HAS_POSITION_SHIFT
case 1: 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 // Zero the G92 values and restore current position
#if !IS_SCARA #if !IS_SCARA
LOOP_XYZ(i) { LOOP_XYZ(i) {
@ -46,44 +60,42 @@ void GcodeSuite::G92() {
} }
} }
#endif // Not SCARA #endif // Not SCARA
return; } return;
} #endif
#endif #if ENABLED(POWER_LOSS_RECOVERY)
case 9: {
#if ENABLED(CNC_COORDINATE_SYSTEMS) LOOP_XYZE(i) {
#define IS_G92_0 (parser.subcode == 0) if (parser.seenval(axis_codes[i])) {
#else current_position[i] = parser.value_axis_units((AxisEnum)i);
#define IS_G92_0 true if (i == E_AXIS) didE = true; else didXYZ = 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
} }
else { }
position_shift[i] += d; // Other axes simply offset the coordinate space } break;
update_workspace_offset((AxisEnum)i); #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) #if ENABLED(CNC_COORDINATE_SYSTEMS)

View file

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

View file

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