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:
parent
df75a606ff
commit
455ee23499
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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");
|
||||||
|
|
Loading…
Reference in a new issue