From e7bf7e603195e0a04c7a98f3771741c2eca05f84 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Thu, 4 Jan 2018 16:42:56 -0600 Subject: [PATCH] Make FWRetract class for 2.0.x parity --- Marlin/G26_Mesh_Validation_Tool.cpp | 1 - Marlin/Marlin.h | 22 ++-- Marlin/Marlin_main.cpp | 196 ++++------------------------ Marlin/configuration_store.cpp | 82 ++++++------ Marlin/fwretract.cpp | 196 ++++++++++++++++++++++++++++ Marlin/fwretract.h | 70 ++++++++++ Marlin/ultralcd.cpp | 23 ++-- 7 files changed, 352 insertions(+), 238 deletions(-) create mode 100644 Marlin/fwretract.cpp create mode 100644 Marlin/fwretract.h diff --git a/Marlin/G26_Mesh_Validation_Tool.cpp b/Marlin/G26_Mesh_Validation_Tool.cpp index 7c34b8813..e1d47a84a 100644 --- a/Marlin/G26_Mesh_Validation_Tool.cpp +++ b/Marlin/G26_Mesh_Validation_Tool.cpp @@ -136,7 +136,6 @@ #if ENABLED(ULTRA_LCD) extern char lcd_status_message[]; #endif - inline void sync_plan_position_e() { planner.set_e_position_mm(current_position[E_AXIS]); } // Private functions diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 1401aec82..f54668439 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -179,6 +179,16 @@ void disable_e_stepper(const uint8_t e); void disable_e_steppers(); void disable_all_steppers(); +void sync_plan_position(); +void sync_plan_position_e(); + +#if IS_KINEMATIC + void sync_plan_position_kinematic(); + #define SYNC_PLAN_POSITION_KINEMATIC() sync_plan_position_kinematic() +#else + #define SYNC_PLAN_POSITION_KINEMATIC() sync_plan_position() +#endif + void FlushSerialRequestResend(); void ok_to_send(); @@ -449,18 +459,6 @@ void report_current_position(); extern int lpq_len; #endif -#if ENABLED(FWRETRACT) - extern bool autoretract_enabled; // M209 S - Autoretract switch - extern float retract_length, // M207 S - G10 Retract length - retract_feedrate_mm_s, // M207 F - G10 Retract feedrate - retract_zlift, // M207 Z - G10 Retract hop size - retract_recover_length, // M208 S - G11 Recover length - retract_recover_feedrate_mm_s, // M208 F - G11 Recover feedrate - swap_retract_length, // M207 W - G10 Swap Retract length - swap_retract_recover_length, // M208 W - G11 Swap Recover length - swap_retract_recover_feedrate_mm_s; // M208 R - G11 Swap Recover feedrate -#endif - // Print job timer #if ENABLED(PRINTCOUNTER) extern PrintCounter print_job_timer; diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index 704f94b25..2592a8600 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -277,6 +277,10 @@ #include "planner_bezier.h" #endif +#if ENABLED(FWRETRACT) + #include "fwretract.h" +#endif + #if HAS_BUZZER && DISABLED(LCD_USE_I2C_BUZZER) #include "buzzer.h" #endif @@ -573,24 +577,6 @@ uint8_t target_extruder; baricuda_e_to_p_pressure = 0; #endif -#if ENABLED(FWRETRACT) // Initialized by settings.load()... - bool autoretract_enabled, // M209 S - Autoretract switch - retracted[EXTRUDERS] = { false }; // Which extruders are currently retracted - float retract_length, // M207 S - G10 Retract length - retract_feedrate_mm_s, // M207 F - G10 Retract feedrate - retract_zlift, // M207 Z - G10 Retract hop size - retract_recover_length, // M208 S - G11 Recover length - retract_recover_feedrate_mm_s, // M208 F - G11 Recover feedrate - swap_retract_length, // M207 W - G10 Swap Retract length - swap_retract_recover_length, // M208 W - G11 Swap Recover length - swap_retract_recover_feedrate_mm_s; // M208 R - G11 Swap Recover feedrate - #if EXTRUDERS > 1 - bool retracted_swap[EXTRUDERS] = { false }; // Which extruders are swap-retracted - #else - constexpr bool retracted_swap[1] = { false }; - #endif -#endif // FWRETRACT - #if HAS_POWER_SWITCH bool powersupply_on = #if ENABLED(PS_DEFAULT_OFF) @@ -782,22 +768,15 @@ void sync_plan_position() { #endif planner.set_position_mm(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); } -inline void sync_plan_position_e() { planner.set_e_position_mm(current_position[E_AXIS]); } +void sync_plan_position_e() { planner.set_e_position_mm(current_position[E_AXIS]); } #if IS_KINEMATIC - inline void sync_plan_position_kinematic() { #if ENABLED(DEBUG_LEVELING_FEATURE) if (DEBUGGING(LEVELING)) DEBUG_POS("sync_plan_position_kinematic", current_position); #endif planner.set_position_mm_kinematic(current_position); } - #define SYNC_PLAN_POSITION_KINEMATIC() sync_plan_position_kinematic() - -#else - - #define SYNC_PLAN_POSITION_KINEMATIC() sync_plan_position() - #endif #if ENABLED(SDSUPPORT) @@ -3099,129 +3078,6 @@ static void homeaxis(const AxisEnum axis) { #endif } // homeaxis() -#if ENABLED(FWRETRACT) - - /** - * Retract or recover according to firmware settings - * - * This function handles retract/recover moves for G10 and G11, - * plus auto-retract moves sent from G0/G1 when E-only moves are done. - * - * To simplify the logic, doubled retract/recover moves are ignored. - * - * Note: Z lift is done transparently to the planner. Aborting - * a print between G10 and G11 may corrupt the Z position. - * - * Note: Auto-retract will apply the set Z hop in addition to any Z hop - * included in the G-code. Use M207 Z0 to to prevent double hop. - */ - void retract(const bool retracting - #if EXTRUDERS > 1 - , bool swapping = false - #endif - ) { - - static float hop_amount = 0.0; // Total amount lifted, for use in recover - - // Prevent two retracts or recovers in a row - if (retracted[active_extruder] == retracting) return; - - // Prevent two swap-retract or recovers in a row - #if EXTRUDERS > 1 - // Allow G10 S1 only after G10 - if (swapping && retracted_swap[active_extruder] == retracting) return; - // G11 priority to recover the long retract if activated - if (!retracting) swapping = retracted_swap[active_extruder]; - #else - const bool swapping = false; - #endif - - /* // debugging - SERIAL_ECHOLNPAIR("retracting ", retracting); - SERIAL_ECHOLNPAIR("swapping ", swapping); - SERIAL_ECHOLNPAIR("active extruder ", active_extruder); - for (uint8_t i = 0; i < EXTRUDERS; ++i) { - SERIAL_ECHOPAIR("retracted[", i); - SERIAL_ECHOLNPAIR("] ", retracted[i]); - SERIAL_ECHOPAIR("retracted_swap[", i); - SERIAL_ECHOLNPAIR("] ", retracted_swap[i]); - } - SERIAL_ECHOLNPAIR("current_position[z] ", current_position[Z_AXIS]); - SERIAL_ECHOLNPAIR("hop_amount ", hop_amount); - //*/ - - const bool has_zhop = retract_zlift > 0.01; // Is there a hop set? - const float old_feedrate_mm_s = feedrate_mm_s; - - // The current position will be the destination for E and Z moves - set_destination_from_current(); - stepper.synchronize(); // Wait for buffered moves to complete - - const float renormalize = 1.0 / planner.e_factor[active_extruder]; - - if (retracting) { - // Retract by moving from a faux E position back to the current E position - feedrate_mm_s = retract_feedrate_mm_s; - current_position[E_AXIS] += (swapping ? swap_retract_length : retract_length) * renormalize; - sync_plan_position_e(); - prepare_move_to_destination(); - - // Is a Z hop set, and has the hop not yet been done? - if (has_zhop && !hop_amount) { - hop_amount += retract_zlift; // Carriage is raised for retraction hop - feedrate_mm_s = planner.max_feedrate_mm_s[Z_AXIS]; // Z feedrate to max - current_position[Z_AXIS] -= retract_zlift; // Pretend current pos is lower. Next move raises Z. - SYNC_PLAN_POSITION_KINEMATIC(); // Set the planner to the new position - prepare_move_to_destination(); // Raise up to the old current pos - feedrate_mm_s = retract_feedrate_mm_s; // Restore feedrate - } - } - else { - // If a hop was done and Z hasn't changed, undo the Z hop - if (hop_amount) { - current_position[Z_AXIS] += retract_zlift; // Pretend current pos is lower. Next move raises Z. - SYNC_PLAN_POSITION_KINEMATIC(); // Set the planner to the new position - feedrate_mm_s = planner.max_feedrate_mm_s[Z_AXIS]; // Z feedrate to max - prepare_move_to_destination(); // Raise up to the old current pos - hop_amount = 0.0; // Clear hop - } - - // A retract multiplier has been added here to get faster swap recovery - feedrate_mm_s = swapping ? swap_retract_recover_feedrate_mm_s : retract_recover_feedrate_mm_s; - - const float move_e = swapping ? swap_retract_length + swap_retract_recover_length : retract_length + retract_recover_length; - current_position[E_AXIS] -= move_e * renormalize; - sync_plan_position_e(); - prepare_move_to_destination(); // Recover E - } - - feedrate_mm_s = old_feedrate_mm_s; // Restore original feedrate - - retracted[active_extruder] = retracting; // Active extruder now retracted / recovered - - // If swap retract/recover update the retracted_swap flag too - #if EXTRUDERS > 1 - if (swapping) retracted_swap[active_extruder] = retracting; - #endif - - /* // debugging - SERIAL_ECHOLNPAIR("retracting ", retracting); - SERIAL_ECHOLNPAIR("swapping ", swapping); - SERIAL_ECHOLNPAIR("active_extruder ", active_extruder); - for (uint8_t i = 0; i < EXTRUDERS; ++i) { - SERIAL_ECHOPAIR("retracted[", i); - SERIAL_ECHOLNPAIR("] ", retracted[i]); - SERIAL_ECHOPAIR("retracted_swap[", i); - SERIAL_ECHOLNPAIR("] ", retracted_swap[i]); - } - SERIAL_ECHOLNPAIR("current_position[z] ", current_position[Z_AXIS]); - SERIAL_ECHOLNPAIR("hop_amount ", hop_amount); - //*/ - - } - -#endif // FWRETRACT - #if ENABLED(MIXING_EXTRUDER) void normalize_mix() { @@ -3355,14 +3211,14 @@ inline void gcode_G0_G1( #if ENABLED(FWRETRACT) if (MIN_AUTORETRACT <= MAX_AUTORETRACT) { - // When M209 Autoretract is enabled, convert E-only moves to firmware retract/recover moves - if (autoretract_enabled && parser.seen('E') && !(parser.seen('X') || parser.seen('Y') || parser.seen('Z'))) { + // When M209 Autoretract is enabled, convert E-only moves to firmware retract/prime moves + if (fwretract.autoretract_enabled && parser.seen('E') && !(parser.seen('X') || parser.seen('Y') || parser.seen('Z'))) { const float echange = destination[E_AXIS] - current_position[E_AXIS]; - // Is this a retract or recover move? - if (WITHIN(FABS(echange), MIN_AUTORETRACT, MAX_AUTORETRACT) && retracted[active_extruder] == (echange > 0.0)) { - current_position[E_AXIS] = destination[E_AXIS]; // Hide a G1-based retract/recover from calculations + // Is this a retract or prime move? + if (WITHIN(FABS(echange), MIN_AUTORETRACT, MAX_AUTORETRACT) && fwretract.retracted[active_extruder] == (echange > 0.0)) { + current_position[E_AXIS] = destination[E_AXIS]; // Hide a G1-based retract/prime from calculations sync_plan_position_e(); // AND from the planner - return retract(echange < 0.0); // Firmware-based retract/recover (double-retract ignored) + return fwretract.retract(echange < 0.0); // Firmware-based retract/prime (double-retract ignored) } } } @@ -3558,9 +3414,9 @@ inline void gcode_G4() { inline void gcode_G10() { #if EXTRUDERS > 1 const bool rs = parser.boolval('S'); - retracted_swap[active_extruder] = rs; // Use 'S' for swap, default to false + fwretract.retracted_swap[active_extruder] = rs; // Use 'S' for swap, default to false #endif - retract(true + fwretract.retract(true #if EXTRUDERS > 1 , rs #endif @@ -3570,7 +3426,7 @@ inline void gcode_G4() { /** * G11 - Recover filament according to settings of M208 */ - inline void gcode_G11() { retract(false); } + inline void gcode_G11() { fwretract.retract(false); } #endif // FWRETRACT @@ -6786,8 +6642,8 @@ inline void gcode_M17() { // Intelligent resuming #if ENABLED(FWRETRACT) // If retracted before goto pause - if (retracted[active_extruder]) - do_pause_e_move(-retract_length, retract_feedrate_mm_s); + if (fwretract.retracted[active_extruder]) + do_pause_e_move(-retract_length, fwretract.retract_feedrate_mm_s); #else // If resume_position negative if (resume_position[E_AXIS] < 0) do_pause_e_move(resume_position[E_AXIS], PAUSE_PARK_RETRACT_FEEDRATE); @@ -9029,10 +8885,10 @@ inline void gcode_M205() { * Z[units] retract_zlift */ inline void gcode_M207() { - if (parser.seen('S')) retract_length = parser.value_axis_units(E_AXIS); - if (parser.seen('F')) retract_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS)); - if (parser.seen('Z')) retract_zlift = parser.value_linear_units(); - if (parser.seen('W')) swap_retract_length = parser.value_axis_units(E_AXIS); + if (parser.seen('S')) fwretract.retract_length = parser.value_axis_units(E_AXIS); + if (parser.seen('F')) fwretract.retract_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS)); + if (parser.seen('Z')) fwretract.retract_zlift = parser.value_linear_units(); + if (parser.seen('W')) fwretract.swap_retract_length = parser.value_axis_units(E_AXIS); } /** @@ -9044,10 +8900,10 @@ inline void gcode_M205() { * R[units/min] swap_retract_recover_feedrate_mm_s */ inline void gcode_M208() { - if (parser.seen('S')) retract_recover_length = parser.value_axis_units(E_AXIS); - if (parser.seen('F')) retract_recover_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS)); - if (parser.seen('R')) swap_retract_recover_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS)); - if (parser.seen('W')) swap_retract_recover_length = parser.value_axis_units(E_AXIS); + if (parser.seen('S')) fwretract.retract_recover_length = parser.value_axis_units(E_AXIS); + if (parser.seen('F')) fwretract.retract_recover_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS)); + if (parser.seen('R')) fwretract.swap_retract_recover_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS)); + if (parser.seen('W')) fwretract.swap_retract_recover_length = parser.value_axis_units(E_AXIS); } /** @@ -9058,8 +8914,8 @@ inline void gcode_M205() { inline void gcode_M209() { if (MIN_AUTORETRACT <= MAX_AUTORETRACT) { if (parser.seen('S')) { - autoretract_enabled = parser.value_bool(); - for (uint8_t i = 0; i < EXTRUDERS; i++) retracted[i] = false; + fwretract.autoretract_enabled = parser.value_bool(); + for (uint8_t i = 0; i < EXTRUDERS; i++) fwretract.retracted[i] = false; } } } diff --git a/Marlin/configuration_store.cpp b/Marlin/configuration_store.cpp index 56100421d..89eb11667 100644 --- a/Marlin/configuration_store.cpp +++ b/Marlin/configuration_store.cpp @@ -215,6 +215,10 @@ MarlinSettings settings; #include "ubl.h" #endif +#if ENABLED(FWRETRACT) + #include "fwretract.h" +#endif + #if ENABLED(AUTO_BED_LEVELING_BILINEAR) extern void refresh_bed_level(); #endif @@ -555,24 +559,20 @@ void MarlinSettings::postprocess() { #if DISABLED(FWRETRACT) const bool autoretract_enabled = false; - const float retract_length = 3, - retract_feedrate_mm_s = 45, - retract_zlift = 0, - retract_recover_length = 0, - retract_recover_feedrate_mm_s = 0, - swap_retract_length = 13, - swap_retract_recover_length = 0, - swap_retract_recover_feedrate_mm_s = 8; + const float autoretract_defaults[] = { 3, 45, 0, 0, 0, 13, 0, 8 }; + EEPROM_WRITE(autoretract_enabled); + EEPROM_WRITE(autoretract_defaults); + #else + EEPROM_WRITE(fwretract.autoretract_enabled); + EEPROM_WRITE(fwretract.retract_length); + EEPROM_WRITE(fwretract.retract_feedrate_mm_s); + EEPROM_WRITE(fwretract.retract_zlift); + EEPROM_WRITE(fwretract.retract_recover_length); + EEPROM_WRITE(fwretract.retract_recover_feedrate_mm_s); + EEPROM_WRITE(fwretract.swap_retract_length); + EEPROM_WRITE(fwretract.swap_retract_recover_length); + EEPROM_WRITE(fwretract.swap_retract_recover_feedrate_mm_s); #endif - EEPROM_WRITE(autoretract_enabled); - EEPROM_WRITE(retract_length); - EEPROM_WRITE(retract_feedrate_mm_s); - EEPROM_WRITE(retract_zlift); - EEPROM_WRITE(retract_recover_length); - EEPROM_WRITE(retract_recover_feedrate_mm_s); - EEPROM_WRITE(swap_retract_length); - EEPROM_WRITE(swap_retract_recover_length); - EEPROM_WRITE(swap_retract_recover_feedrate_mm_s); // // Volumetric & Filament Size @@ -1070,15 +1070,15 @@ void MarlinSettings::postprocess() { // #if ENABLED(FWRETRACT) - EEPROM_READ(autoretract_enabled); - EEPROM_READ(retract_length); - EEPROM_READ(retract_feedrate_mm_s); - EEPROM_READ(retract_zlift); - EEPROM_READ(retract_recover_length); - EEPROM_READ(retract_recover_feedrate_mm_s); - EEPROM_READ(swap_retract_length); - EEPROM_READ(swap_retract_recover_length); - EEPROM_READ(swap_retract_recover_feedrate_mm_s); + EEPROM_READ(fwretract.autoretract_enabled); + EEPROM_READ(fwretract.retract_length); + EEPROM_READ(fwretract.retract_feedrate_mm_s); + EEPROM_READ(fwretract.retract_zlift); + EEPROM_READ(fwretract.retract_recover_length); + EEPROM_READ(fwretract.retract_recover_feedrate_mm_s); + EEPROM_READ(fwretract.swap_retract_length); + EEPROM_READ(fwretract.swap_retract_recover_length); + EEPROM_READ(fwretract.swap_retract_recover_feedrate_mm_s); #else EEPROM_READ(dummyb); for (uint8_t q=8; q--;) EEPROM_READ(dummy); @@ -1549,16 +1549,8 @@ void MarlinSettings::reset() { #endif #if ENABLED(FWRETRACT) - autoretract_enabled = false; - retract_length = RETRACT_LENGTH; - retract_feedrate_mm_s = RETRACT_FEEDRATE; - retract_zlift = RETRACT_ZLIFT; - retract_recover_length = RETRACT_RECOVER_LENGTH; - retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE; - swap_retract_length = RETRACT_LENGTH_SWAP; - swap_retract_recover_length = RETRACT_RECOVER_LENGTH_SWAP; - swap_retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE_SWAP; - #endif // FWRETRACT + fwretract.reset(); + #endif #if DISABLED(NO_VOLUMETRICS) @@ -2052,26 +2044,26 @@ void MarlinSettings::reset() { SERIAL_ECHOLNPGM("Retract: S F Z"); } CONFIG_ECHO_START; - SERIAL_ECHOPAIR(" M207 S", LINEAR_UNIT(retract_length)); - SERIAL_ECHOPAIR(" W", LINEAR_UNIT(swap_retract_length)); - SERIAL_ECHOPAIR(" F", MMS_TO_MMM(LINEAR_UNIT(retract_feedrate_mm_s))); - SERIAL_ECHOLNPAIR(" Z", LINEAR_UNIT(retract_zlift)); + SERIAL_ECHOPAIR(" M207 S", LINEAR_UNIT(fwretract.retract_length)); + SERIAL_ECHOPAIR(" W", LINEAR_UNIT(fwretract.swap_retract_length)); + SERIAL_ECHOPAIR(" F", MMS_TO_MMM(LINEAR_UNIT(fwretract.retract_feedrate_mm_s))); + SERIAL_ECHOLNPAIR(" Z", LINEAR_UNIT(fwretract.retract_zlift)); if (!forReplay) { CONFIG_ECHO_START; SERIAL_ECHOLNPGM("Recover: S F"); } CONFIG_ECHO_START; - SERIAL_ECHOPAIR(" M208 S", LINEAR_UNIT(retract_recover_length)); - SERIAL_ECHOPAIR(" W", LINEAR_UNIT(swap_retract_recover_length)); - SERIAL_ECHOLNPAIR(" F", MMS_TO_MMM(LINEAR_UNIT(retract_recover_feedrate_mm_s))); + SERIAL_ECHOPAIR(" M208 S", LINEAR_UNIT(fwretract.retract_recover_length)); + SERIAL_ECHOPAIR(" W", LINEAR_UNIT(fwretract.swap_retract_recover_length)); + SERIAL_ECHOLNPAIR(" F", MMS_TO_MMM(LINEAR_UNIT(fwretract.retract_recover_feedrate_mm_s))); if (!forReplay) { CONFIG_ECHO_START; SERIAL_ECHOLNPGM("Auto-Retract: S=0 to disable, 1 to interpret E-only moves as retract/recover"); } CONFIG_ECHO_START; - SERIAL_ECHOLNPAIR(" M209 S", autoretract_enabled ? 1 : 0); + SERIAL_ECHOLNPAIR(" M209 S", fwretract.autoretract_enabled ? 1 : 0); #endif // FWRETRACT @@ -2210,7 +2202,7 @@ void MarlinSettings::reset() { #if ENABLED(ADVANCED_PAUSE_FEATURE) if (!forReplay) { CONFIG_ECHO_START; - SERIAL_ECHOLNPGM("Filament load & unload lengths:"); + SERIAL_ECHOLNPGM("Filament load/unload lengths:"); } CONFIG_ECHO_START; #if EXTRUDERS == 1 diff --git a/Marlin/fwretract.cpp b/Marlin/fwretract.cpp new file mode 100644 index 000000000..42ee70395 --- /dev/null +++ b/Marlin/fwretract.cpp @@ -0,0 +1,196 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/** + * fwretract.cpp - Implement firmware-based retraction + */ + +#include "MarlinConfig.h" + +#if ENABLED(FWRETRACT) + +#include "fwretract.h" +#include "Marlin.h" +#include "planner.h" +#include "stepper.h" + +FWRetract fwretract; // Single instance - this calls the constructor + +// private: + +#if EXTRUDERS > 1 + bool FWRetract::retracted_swap[EXTRUDERS]; // Which extruders are swap-retracted +#endif + +// public: + +bool FWRetract::autoretract_enabled, // M209 S - Autoretract switch + FWRetract::retracted[EXTRUDERS]; // Which extruders are currently retracted +float FWRetract::retract_length, // M207 S - G10 Retract length + FWRetract::retract_feedrate_mm_s, // M207 F - G10 Retract feedrate + FWRetract::retract_zlift, // M207 Z - G10 Retract hop size + FWRetract::retract_recover_length, // M208 S - G11 Recover length + FWRetract::retract_recover_feedrate_mm_s, // M208 F - G11 Recover feedrate + FWRetract::swap_retract_length, // M207 W - G10 Swap Retract length + FWRetract::swap_retract_recover_length, // M208 W - G11 Swap Recover length + FWRetract::swap_retract_recover_feedrate_mm_s; // M208 R - G11 Swap Recover feedrate + +void FWRetract::reset() { + autoretract_enabled = false; + retract_length = RETRACT_LENGTH; + retract_feedrate_mm_s = RETRACT_FEEDRATE; + retract_zlift = RETRACT_ZLIFT; + retract_recover_length = RETRACT_RECOVER_LENGTH; + retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE; + swap_retract_length = RETRACT_LENGTH_SWAP; + swap_retract_recover_length = RETRACT_RECOVER_LENGTH_SWAP; + swap_retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE_SWAP; + + for (uint8_t i = 0; i < EXTRUDERS; ++i) { + retracted[i] = false; + #if EXTRUDERS > 1 + retracted_swap[i] = false; + #endif + } +} + +/** + * Retract or recover according to firmware settings + * + * This function handles retract/recover moves for G10 and G11, + * plus auto-retract moves sent from G0/G1 when E-only moves are done. + * + * To simplify the logic, doubled retract/recover moves are ignored. + * + * Note: Z lift is done transparently to the planner. Aborting + * a print between G10 and G11 may corrupt the Z position. + * + * Note: Auto-retract will apply the set Z hop in addition to any Z hop + * included in the G-code. Use M207 Z0 to to prevent double hop. + */ +void FWRetract::retract(const bool retracting + #if EXTRUDERS > 1 + , bool swapping /* =false */ + #endif +) { + + static float hop_amount = 0.0; // Total amount lifted, for use in recover + + // Prevent two retracts or recovers in a row + if (retracted[active_extruder] == retracting) return; + + // Prevent two swap-retract or recovers in a row + #if EXTRUDERS > 1 + // Allow G10 S1 only after G10 + if (swapping && retracted_swap[active_extruder] == retracting) return; + // G11 priority to recover the long retract if activated + if (!retracting) swapping = retracted_swap[active_extruder]; + #else + const bool swapping = false; + #endif + + /* // debugging + SERIAL_ECHOLNPAIR("retracting ", retracting); + SERIAL_ECHOLNPAIR("swapping ", swapping); + SERIAL_ECHOLNPAIR("active extruder ", active_extruder); + for (uint8_t i = 0; i < EXTRUDERS; ++i) { + SERIAL_ECHOPAIR("retracted[", i); + SERIAL_ECHOLNPAIR("] ", retracted[i]); + SERIAL_ECHOPAIR("retracted_swap[", i); + SERIAL_ECHOLNPAIR("] ", retracted_swap[i]); + } + SERIAL_ECHOLNPAIR("current_position[z] ", current_position[Z_AXIS]); + SERIAL_ECHOLNPAIR("hop_amount ", hop_amount); + //*/ + + const bool has_zhop = retract_zlift > 0.01; // Is there a hop set? + const float old_feedrate_mm_s = feedrate_mm_s; + + // The current position will be the destination for E and Z moves + set_destination_from_current(); + stepper.synchronize(); // Wait for buffered moves to complete + + const float renormalize = 1.0 / planner.e_factor[active_extruder]; + + if (retracting) { + // Retract by moving from a faux E position back to the current E position + feedrate_mm_s = retract_feedrate_mm_s; + current_position[E_AXIS] += (swapping ? swap_retract_length : retract_length) * renormalize; + sync_plan_position_e(); + prepare_move_to_destination(); + + // Is a Z hop set, and has the hop not yet been done? + // No double zlifting + // Feedrate to the max + if (has_zhop && !hop_amount) { + hop_amount += retract_zlift; // Carriage is raised for retraction hop + feedrate_mm_s = planner.max_feedrate_mm_s[Z_AXIS]; // Z feedrate to max + current_position[Z_AXIS] -= retract_zlift; // Pretend current pos is lower. Next move raises Z. + SYNC_PLAN_POSITION_KINEMATIC(); // Set the planner to the new position + prepare_move_to_destination(); // Raise up to the old current pos + } + } + else { + // If a hop was done and Z hasn't changed, undo the Z hop + if (hop_amount) { + current_position[Z_AXIS] += retract_zlift; // Pretend current pos is lower. Next move raises Z. + SYNC_PLAN_POSITION_KINEMATIC(); // Set the planner to the new position + feedrate_mm_s = planner.max_feedrate_mm_s[Z_AXIS]; // Z feedrate to max + prepare_move_to_destination(); // Raise up to the old current pos + hop_amount = 0.0; // Clear hop + } + + // A retract multiplier has been added here to get faster swap recovery + feedrate_mm_s = swapping ? swap_retract_recover_feedrate_mm_s : retract_recover_feedrate_mm_s; + + const float move_e = swapping ? swap_retract_length + swap_retract_recover_length : retract_length + retract_recover_length; + current_position[E_AXIS] -= move_e * renormalize; + sync_plan_position_e(); + prepare_move_to_destination(); // Recover E + } + + feedrate_mm_s = old_feedrate_mm_s; // Restore original feedrate + + retracted[active_extruder] = retracting; // Active extruder now retracted / recovered + + // If swap retract/recover update the retracted_swap flag too + #if EXTRUDERS > 1 + if (swapping) retracted_swap[active_extruder] = retracting; + #endif + + /* // debugging + SERIAL_ECHOLNPAIR("retracting ", retracting); + SERIAL_ECHOLNPAIR("swapping ", swapping); + SERIAL_ECHOLNPAIR("active_extruder ", active_extruder); + for (uint8_t i = 0; i < EXTRUDERS; ++i) { + SERIAL_ECHOPAIR("retracted[", i); + SERIAL_ECHOLNPAIR("] ", retracted[i]); + SERIAL_ECHOPAIR("retracted_swap[", i); + SERIAL_ECHOLNPAIR("] ", retracted_swap[i]); + } + SERIAL_ECHOLNPAIR("current_position[z] ", current_position[Z_AXIS]); + SERIAL_ECHOLNPAIR("hop_amount ", hop_amount); + //*/ + +} + +#endif // FWRETRACT diff --git a/Marlin/fwretract.h b/Marlin/fwretract.h new file mode 100644 index 000000000..a36885789 --- /dev/null +++ b/Marlin/fwretract.h @@ -0,0 +1,70 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/** + * fwretract.h - Define firmware-based retraction interface + */ + +#ifndef FWRETRACT_H +#define FWRETRACT_H + +#include "MarlinConfig.h" + +class FWRetract { +public: + static bool autoretract_enabled, // M209 S - Autoretract switch + retracted[EXTRUDERS]; // Which extruders are currently retracted + #if EXTRUDERS > 1 + static bool retracted_swap[EXTRUDERS]; // Which extruders are swap-retracted + #endif + static float retract_length, // M207 S - G10 Retract length + retract_feedrate_mm_s, // M207 F - G10 Retract feedrate + retract_zlift, // M207 Z - G10 Retract hop size + retract_recover_length, // M208 S - G11 Recover length + retract_recover_feedrate_mm_s, // M208 F - G11 Recover feedrate + swap_retract_length, // M207 W - G10 Swap Retract length + swap_retract_recover_length, // M208 W - G11 Swap Recover length + swap_retract_recover_feedrate_mm_s; // M208 R - G11 Swap Recover feedrate + + FWRetract() { reset(); } + + static void reset(); + + static void refresh_autoretract() { + for (uint8_t i = 0; i < EXTRUDERS; i++) retracted[i] = false; + } + + static void enable_autoretract(const bool enable) { + autoretract_enabled = enable; + refresh_autoretract(); + } + + static void retract(const bool retracting + #if EXTRUDERS > 1 + , bool swapping = false + #endif + ); +}; + +extern FWRetract fwretract; + +#endif // FWRETRACT_H diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp index 32a67646a..7d14983ac 100644 --- a/Marlin/ultralcd.cpp +++ b/Marlin/ultralcd.cpp @@ -56,6 +56,10 @@ #include "mesh_bed_leveling.h" #endif +#if ENABLED(FWRETRACT) + #include "fwretract.h" +#endif + #if ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(G26_MESH_VALIDATION) bool lcd_external_control; // = false #endif @@ -2348,7 +2352,6 @@ void kill_screen(const char* lcd_msg) { * UBL LCD "radar" map */ void set_current_from_steppers_for_axis(const AxisEnum axis); - void sync_plan_position(); void _lcd_do_nothing() {} void _lcd_hard_stop() { @@ -3748,20 +3751,20 @@ void kill_screen(const char* lcd_msg) { void lcd_control_retract_menu() { START_MENU(); MENU_BACK(MSG_CONTROL); - MENU_ITEM_EDIT(bool, MSG_AUTORETRACT, &autoretract_enabled); - MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT, &retract_length, 0, 100); + MENU_ITEM_EDIT(bool, MSG_AUTORETRACT, &fwretract.autoretract_enabled); + MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT, &fwretract.retract_length, 0, 100); #if EXTRUDERS > 1 - MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_SWAP, &swap_retract_length, 0, 100); + MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_SWAP, &fwretract.swap_retract_length, 0, 100); #endif - MENU_ITEM_EDIT(float3, MSG_CONTROL_RETRACTF, &retract_feedrate_mm_s, 1, 999); - MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_ZLIFT, &retract_zlift, 0, 999); - MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_RECOVER, &retract_recover_length, -100, 100); + MENU_ITEM_EDIT(float3, MSG_CONTROL_RETRACTF, &fwretract.retract_feedrate_mm_s, 1, 999); + MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_ZLIFT, &fwretract.retract_zlift, 0, 999); + MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_RECOVER, &fwretract.retract_recover_length, -100, 100); #if EXTRUDERS > 1 - MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_RECOVER_SWAP, &swap_retract_recover_length, -100, 100); + MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_RECOVER_SWAP, &fwretract.swap_retract_recover_length, -100, 100); #endif - MENU_ITEM_EDIT(float3, MSG_CONTROL_RETRACT_RECOVERF, &retract_recover_feedrate_mm_s, 1, 999); + MENU_ITEM_EDIT(float3, MSG_CONTROL_RETRACT_RECOVERF, &fwretract.retract_recover_feedrate_mm_s, 1, 999); #if EXTRUDERS > 1 - MENU_ITEM_EDIT(float3, MSG_CONTROL_RETRACT_RECOVER_SWAPF, &swap_retract_recover_feedrate_mm_s, 1, 999); + MENU_ITEM_EDIT(float3, MSG_CONTROL_RETRACT_RECOVER_SWAPF, &fwretract.swap_retract_recover_feedrate_mm_s, 1, 999); #endif END_MENU(); }