From 455ee23499042b17132405934d3aa932d9713ab3 Mon Sep 17 00:00:00 2001 From: Msq001 <760675063@qq.com> Date: Tue, 16 Apr 2019 07:53:39 +0800 Subject: [PATCH] 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 --- Marlin/src/feature/power_loss_recovery.cpp | 85 ++++++++++++++++----- Marlin/src/feature/power_loss_recovery.h | 9 +++ Marlin/src/gcode/geometry/G92.cpp | 88 ++++++++++++---------- Marlin/src/gcode/sdcard/M23.cpp | 3 - Marlin/src/sd/cardreader.cpp | 1 + 5 files changed, 127 insertions(+), 59 deletions(-) diff --git a/Marlin/src/feature/power_loss_recovery.cpp b/Marlin/src/feature/power_loss_recovery.cpp index 17ba4a101..5e3ef6fb5 100644 --- a/Marlin/src/feature/power_loss_recovery.cpp +++ b/Marlin/src/feature/power_loss_recovery.cpp @@ -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 diff --git a/Marlin/src/feature/power_loss_recovery.h b/Marlin/src/feature/power_loss_recovery.h index 45b057e75..68554dc60 100644 --- a/Marlin/src/feature/power_loss_recovery.h +++ b/Marlin/src/feature/power_loss_recovery.h @@ -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 diff --git a/Marlin/src/gcode/geometry/G92.cpp b/Marlin/src/gcode/geometry/G92.cpp index b01daf348..75a0c03ae 100644 --- a/Marlin/src/gcode/geometry/G92.cpp +++ b/Marlin/src/gcode/geometry/G92.cpp @@ -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) diff --git a/Marlin/src/gcode/sdcard/M23.cpp b/Marlin/src/gcode/sdcard/M23.cpp index 92899a217..7cdc97669 100644 --- a/Marlin/src/gcode/sdcard/M23.cpp +++ b/Marlin/src/gcode/sdcard/M23.cpp @@ -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); diff --git a/Marlin/src/sd/cardreader.cpp b/Marlin/src/sd/cardreader.cpp index 95527a9b8..7ac21b975 100644 --- a/Marlin/src/sd/cardreader.cpp +++ b/Marlin/src/sd/cardreader.cpp @@ -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");