diff --git a/Firmware/Marlin.h b/Firmware/Marlin.h index 2b8d16862..66abdaf12 100755 --- a/Firmware/Marlin.h +++ b/Firmware/Marlin.h @@ -391,6 +391,8 @@ extern void print_mesh_bed_leveling_table(); void save_print_file_state(); void restore_print_file_state(); void save_planner_global_state(); +void refresh_print_state_in_ram(); +void clear_print_state_in_ram(); extern void stop_and_save_print_to_ram(float z_move, float e_move); void restore_extruder_temperature_from_ram(); extern void restore_print_from_ram_and_continue(float e_move); @@ -402,6 +404,7 @@ extern void cancel_saved_printing(); #define SAVED_START_POSITION_UNSET X_COORD_INVALID extern float saved_start_position[NUM_AXIS]; extern uint16_t saved_segment_idx; +extern bool isPartialBackupAvailable; //estimated time to end of the print diff --git a/Firmware/Marlin_main.cpp b/Firmware/Marlin_main.cpp index 1c4256be4..8763b45dc 100644 --- a/Firmware/Marlin_main.cpp +++ b/Firmware/Marlin_main.cpp @@ -247,6 +247,7 @@ const char echomagic[] PROGMEM = "echo:"; float saved_start_position[NUM_AXIS] = {SAVED_START_POSITION_UNSET, 0, 0, 0}; uint16_t saved_segment_idx = 0; +bool isPartialBackupAvailable; // storing estimated time to end of print counted by slicer uint8_t print_percent_done_normal = PRINT_PERCENT_DONE_INIT; @@ -7624,6 +7625,10 @@ Sigma_Exit: { st_synchronize(); + // In case a power panic happens while waiting for the user + // take a partial back up of print state into RAM (current position, etc.) + refresh_print_state_in_ram(); + float x_position = FILAMENTCHANGE_XPOS; float y_position = FILAMENTCHANGE_YPOS; float z_shift = MIN_Z_FOR_SWAP; @@ -10479,6 +10484,29 @@ void save_planner_global_state() { } } +/// Take a backup of the current state of variables +/// e.g. feedrate, Z-axis position etc. +/// This function should backup variables which may be lost +/// For example a power panic in M600 or during MMU error +void refresh_print_state_in_ram() +{ + if (saved_printing) return; + memcpy(saved_pos, current_position, sizeof(saved_pos)); + saved_feedmultiply2 = feedmultiply; //save feedmultiply + saved_extruder_temperature = (uint16_t)degTargetHotend(active_extruder); + saved_bed_temperature = (uint8_t)degTargetBed(); + saved_extruder_relative_mode = axis_relative_modes & E_AXIS_MASK; + saved_fan_speed = fanSpeed; + isPartialBackupAvailable = true; +} + +void clear_print_state_in_ram() +{ + // Set flag to false in order to avoid using + // the saved values during power panic + isPartialBackupAvailable = false; +} + //! @brief Immediately stop print moves //! //! Immediately stop print moves, save current extruder temperature and position to RAM. diff --git a/Firmware/mmu2.cpp b/Firmware/mmu2.cpp index 961917461..6969bb5c5 100644 --- a/Firmware/mmu2.cpp +++ b/Firmware/mmu2.cpp @@ -627,6 +627,10 @@ void MMU2::SaveAndPark(bool move_axes) { Disable_E0(); planner_synchronize(); + // In case a power panic happens while waiting for the user + // take a partial back up of print state into RAM (current position, etc.) + refresh_print_state_in_ram(); + if (move_axes) { mmu_print_saved |= SavedState::ParkExtruder; resume_position = planner_current_position(); // save current pos @@ -681,6 +685,11 @@ void MMU2::ResumeUnpark() { // Move Z_AXIS to saved position motion_do_blocking_move_to_z(resume_position.xyz[2], feedRate_t(NOZZLE_PARK_Z_FEEDRATE)); + // From this point forward, power panic should not use + // the partial backup in RAM since the extruder is no + // longer in parking position + clear_print_state_in_ram(); + mmu_print_saved &= ~(SavedState::ParkExtruder); } } diff --git a/Firmware/power_panic.cpp b/Firmware/power_panic.cpp index 7e9685796..1e2ebf8fd 100644 --- a/Firmware/power_panic.cpp +++ b/Firmware/power_panic.cpp @@ -66,12 +66,14 @@ void uvlo_() { tmc2130_set_current_r(E_AXIS, 20); #endif //TMC2130 - if (!sd_print_saved_in_ram) + if (!sd_print_saved_in_ram && !isPartialBackupAvailable) { saved_bed_temperature = target_temperature_bed; saved_extruder_temperature = target_temperature[active_extruder]; saved_extruder_relative_mode = axis_relative_modes & E_AXIS_MASK; saved_fan_speed = fanSpeed; + memcpy(saved_pos, current_position, sizeof(saved_pos)); + if (pos_invalid) saved_pos[X_AXIS] = X_COORD_INVALID; } // Stop all heaters before continuing @@ -84,9 +86,6 @@ void uvlo_() { // save the global state at planning time save_planner_global_state(); - - memcpy(saved_pos, current_position, sizeof(saved_pos)); - if (pos_invalid) saved_pos[X_AXIS] = X_COORD_INVALID; } // From this point on and up to the print recovery, Z should not move during X/Y travels and