diff --git a/README.md b/README.md index f00ea4b23..1879415c8 100644 --- a/README.md +++ b/README.md @@ -42,13 +42,15 @@ Features merged into the master branch: - [virtual_sdcard: scanning of subdirectories](https://github.com/DangerKlippers/danger-klipper/pull/68) ([klipper#6327](https://github.com/Klipper3d/klipper/pull/6327)) +- [retraction: z_hop while retracting](https://github.com/DangerKlippers/danger-klipper/pull/83) ([klipper#6311](https://github.com/Klipper3d/klipper/pull/6311)) + - [core: git-untracked folder, plugins for user-plugins](https://github.com/DangerKlippers/danger-klipper/pull/82) - [danger_options: allow plugins to override conflicting extras](https://github.com/DangerKlippers/danger-klipper/pull/82) If you're feeling adventurous, take a peek at the extra features in the bleeding-edge branch: -- [dmbutyugin's advanced-features branch](https://github.com/DangerKlippers/danger-klipper/pull/69) [dmbutyugin/advanced-features](https://github.com/dmbutyugin/klipper/commits/advanced-features) + - [dmbutyugin's advanced-features branch](https://github.com/DangerKlippers/danger-klipper/pull/69) [dmbutyugin/advanced-features](https://github.com/dmbutyugin/klipper/commits/advanced-features) - [stepper: high precision stepping protocol](https://github.com/DangerKlippers/danger-klipper/pull/69) diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index 5a5f36e87..90a48d8b0 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -1581,17 +1581,35 @@ allowing per-filament settings and runtime tuning. ``` [firmware_retraction] -#retract_length: 0 -# The length of filament (in mm) to retract when G10 is activated, -# and to unretract when G11 is activated (but see -# unretract_extra_length below). The default is 0 mm. -#retract_speed: 20 -# The speed of retraction, in mm/s. The default is 20 mm/s. -#unretract_extra_length: 0 -# The length (in mm) of *additional* filament to add when -# unretracting. -#unretract_speed: 10 -# The speed of unretraction, in mm/s. The default is 10 mm/s. +#retract_length: 0.0 +# The length of filament (in mm) to retract when a G10 command is +# executed. When a G11 command is executed, the unretract_length +# is the sum of the retract_length and the unretract_extra_length +# (see below). The minimum value and default are 0 mm, which +# disables firmware retraction. +#retract_speed: 20.0 +# The speed of filament retraction moves (in mm/s). +# This value is typically set relatively high (>40 mm/s), +# except for soft and/oozy filaments like TPU and PETG +# (20 to 30 mm/s). The minimum value is 1 mm/s, the default value +# is 20 mm/s. +#unretract_extra_length: 0.0 +# The *additional* length (in mm) to add or the length to subtract +# from the filament move when unretracting compared to the retract +# move length. This allows priming the nozzle (positive extra length) +# or delaying extrusion after unretracting (negative length). The +# latter may help reduce blobbing. The minimum value is -1 mm +# (2.41 mm3 volume for 1.75 mm filament), the default value is 0 mm. +#unretract_speed: 10.0 +# The speed of filament unretraction moves (in mm/s). +# This parameter is not particularly critical, although often lower +# than retract_speed. The minimum value is 1 mm/s, the default value +# is 10 mm/s. +#z_hop_height: 0.0 +# The vertical height by which the nozzle is lifted from the print to +# prevent collisions with the print during travel moves when retracted. +# The minimum value is 0 mm, the default value is 0 mm, which disables +# zhop moves. ``` ### [gcode_arcs] diff --git a/docs/G-Codes.md b/docs/G-Codes.md index c4820944e..d066b6c7b 100644 --- a/docs/G-Codes.md +++ b/docs/G-Codes.md @@ -509,35 +509,70 @@ will be disabled, if set to 1 it is enabled. The following standard G-Code commands are available when the [firmware_retraction config section](Config_Reference.md#firmware_retraction) -is enabled. These commands allow you to utilize the firmware -retraction feature available in many slicers, to reduce stringing -during non-extrusion moves from one part of the print to another. -Appropriately configuring pressure advance reduces the length of -retraction required. -- `G10`: Retracts the extruder using the currently configured - parameters. -- `G11`: Unretracts the extruder using the currently configured - parameters. +is enabled. These commands allow utilizing the firmware +retraction feature available in many slicers. Retraction is a strategy to +reduce stringing during travel moves (non-extrusion) from one part of the +print to another. Note that pressure advance should be properly configured +before retraction parameters are tuned to ensure optimal results. +- `G10`: Retracts the filament using the currently configured + parameters. If z_hop_height is set to a value greater zero, + besides retracting the filament, the nozzle is lifted by set value. +- `G11`: Unretracts the filament using the currently configured + parameters. If z_hop_height is set to a value greater zero, + besides unretracting the filament, the nozzle is lowered back on the print + with a vertical movement. The following additional commands are also available. #### SET_RETRACTION `SET_RETRACTION [RETRACT_LENGTH=] [RETRACT_SPEED=] -[UNRETRACT_EXTRA_LENGTH=] [UNRETRACT_SPEED=]`: Adjust the -parameters used by firmware retraction. RETRACT_LENGTH determines the -length of filament to retract and unretract. The speed of retraction -is adjusted via RETRACT_SPEED, and is typically set relatively -high. The speed of unretraction is adjusted via UNRETRACT_SPEED, and -is not particularly critical, although often lower than RETRACT_SPEED. -In some cases it is useful to add a small amount of additional length -on unretraction, and this is set via UNRETRACT_EXTRA_LENGTH. -SET_RETRACTION is commonly set as part of slicer per-filament -configuration, as different filaments require different parameter -settings. +[UNRETRACT_EXTRA_LENGTH=] [UNRETRACT_SPEED=] [Z_HOP_HEIGHT=]`: +Adjust the parameters used by firmware retraction. RETRACT_LENGTH determines the +length of filament to retract (the minimum as well as standard value is 0 mm). +RETRACT_SPEED determines the speed of the filament retraction move (the minimum +value is 1 mm/s, the standard value is 20 mm/s). This value is typically set +relatively high (>40 mm/s), except for soft and/or oozy filaments like TPU and +PETG (20 to 30 mm/s). +UNRETRACT_SPEED sets the speed of the filament unretract move (the minimum value +is 1 mm/s, the standard value is 10 mm/s). This parameter is not particularly +critical, although often lower than RETRACT_SPEED. +UNRETRACT_EXTRA_LENGTH allows to add a small amount of length to the filament +unretract move to prime the nozzle or to subtract a small amount of length from +the filament unretract move to reduce blobbing at seams (the minimum value is +-1 mm (2.41 mm3 volume for 1.75 mm filament), the standard value is 0 mm). +Z_HOP_HEIGHT determines the vertical height by which the nozzle is lifted from +the print to prevent collisions with the print during travel moves (the +minimum value is 0 mm, the standard value is 0 mm, which disables Z-Hop moves). +SET_RETRACTION is commonly set as part of slicer per-filament configuration, as +different filaments require different parameter settings. The command can be +issued at runtime. #### GET_RETRACTION -`GET_RETRACTION`: Queries the current parameters used by firmware -retraction and displays them on the terminal. +`GET_RETRACTION`: Queries the current parameters used by the firmware retraction +module as well as the retract state. RETRACT_LENGTH, RETRACT_SPEED, +UNRETRACT_EXTRA_LENGTH, UNRETRACT_SPEED, Z_HOP_HEIGHT and RETRACTED (True, if +retracted) are displayed on the terminal. + +#### CLEAR_RETRACTION +`CLEAR_RETRACTION`: Clears the current retract state without extruder or +motion system movement. All flags related to the retract state are reset to +False and all changes to retraction parameters made via previous SET_RETRACTION +commands are reset to config values. +NOTE: The Module contains a lot of redundancy for safety to prevent undesired +behavior. When printing from virtual SD Card, the printer state is monitored and +retraction state is cleared if a print is started, canceled or finished or if a +virtual SD card file is reset. When printing via GCode streaming (e.g. using +OctoPrint), the retract state is cleared when the steppers are disabled (M84, +typically part of end gcode and standard behavior of OctoPrint if a print is +canceled) or the printer is homed (G28, typically part of start gcode). Hence, +upon ending or canceling a print as well as starting a new print via GCode +streaming or virtual SD card, the printer should always be in unretracted state. +Nevertheless, it is recommended to add `CLEAR_RETRACTION` to your start and end +gcode to make sure the retract state is reset before and after each print. If a +print is finished or canceled while retracted and the retract state is not +cleared, either via `CLEAR_RETRACTION` without filament or motion system +movement or G11, the nozzle will stay above the requested z coordinate by the +set z_hop_height. ### [force_move] diff --git a/docs/Status_Reference.md b/docs/Status_Reference.md index c17eb2924..ce39cf0c4 100644 --- a/docs/Status_Reference.md +++ b/docs/Status_Reference.md @@ -173,10 +173,20 @@ objects: The following information is available in the [firmware_retraction](Config_Reference.md#firmware_retraction) object: -- `retract_length`, `retract_speed`, `unretract_extra_length`, - `unretract_speed`: The current settings for the firmware_retraction - module. These settings may differ from the config file if a - `SET_RETRACTION` command alters them. +- `retract_length`: Current setting for length of filament retract moves. +- `retract_speed`: Current setting for speed of filament retract moves. +- `unretract_extra_length`: Current setting for additional length of filament + unretract moves (positive values will result in filament extrusion, while + negative values up to 1 mm (2.41 mm3 for 1.75 mm filament) will result in + lagging extrusion of filament). +- `unretract_speed`: Current setting for speed of unretract moves of filament. +- `unretract_length`: Unretract move length (sum of retract and extra unretract + length). +- `z_hop_height`: Current setting for the height of nozzle lifting move (Z-Hop). +- Above settings for the firmware_retraction module may differ from the + config file if a `SET_RETRACTION` command altered them. Additional information + available is as follows. +- `retract_state`: Returns 'True' if filament is retracted. ## gcode_button diff --git a/klippy/extras/firmware_retraction.py b/klippy/extras/firmware_retraction.py index 960a9532f..909e1f291 100644 --- a/klippy/extras/firmware_retraction.py +++ b/klippy/extras/firmware_retraction.py @@ -1,26 +1,68 @@ # Support for Marlin/Smoothie/Reprap style firmware retraction via G10/G11 +# Zhop funtionality includes: +# - Standard zhop (vertical move up, travel, vertical move down) # +# Copyright (C) 2023 Florian-Patrice Nagel # Copyright (C) 2019 Len Trigg # # This file may be distributed under the terms of the GNU GPLv3 license. +# Constants +ZHOP_MOVE_SPEED_FRACTION = 0.8 + class FirmwareRetraction: + # Class init def __init__(self, config): + self.config_ref = config self.printer = config.get_printer() - self.retract_length = config.getfloat("retract_length", 0.0, minval=0.0) - self.retract_speed = config.getfloat("retract_speed", 20.0, minval=1) - self.unretract_extra_length = config.getfloat( + # Get retraction params from config, used also in clear retraction + self._get_config_params() + # Initialize variables + self.unretract_length = ( + self.retract_length + self.unretract_extra_length + ) + self.currentPos = [] + self.currentZ = 0.0 + self.z_hop_Z = 0.0 # Z coordinate of zhop move + + self.is_retracted = False # Retract state flag + self.vsdcard_paused = False # VSDCard pause flag + self.G1_toggle_state = False # G1 toggle state flag + + # Get maximum printer move velocity for zhop moves + printer_config = config.getsection("printer") + self.max_vel = printer_config.getfloat("max_velocity") + + self.printer.register_event_handler("klippy:ready", self._handle_ready) + + # Helper method to get retraction parameters from config + def _get_config_params(self): + self.retract_length = self.config_ref.getfloat( + "retract_length", 0.0, minval=0.0 + ) + self.retract_speed = self.config_ref.getfloat( + "retract_speed", 20.0, minval=1 + ) + self.unretract_extra_length = self.config_ref.getfloat( "unretract_extra_length", 0.0, minval=0.0 ) - self.unretract_speed = config.getfloat( + self.unretract_speed = self.config_ref.getfloat( "unretract_speed", 10.0, minval=1 ) - self.unretract_length = ( - self.retract_length + self.unretract_extra_length + # Zero min. and stand. zhop valueto ensure compatibility with macros + self.z_hop_height = self.config_ref.getfloat( + "z_hop_height", 0.0, minval=0.0 ) - self.is_retracted = False + + # Helper method to register commands and instantiate required objects + def _handle_ready(self): self.gcode = self.printer.lookup_object("gcode") + self.gcode_move = self.printer.lookup_object("gcode_move") + self.toolhead = self.printer.lookup_object("toolhead") + + # Register new G-code commands for setting/retrieving retraction + # parameters as well as clearing retraction state self.gcode.register_command( "SET_RETRACTION", self.cmd_SET_RETRACTION, @@ -31,72 +73,334 @@ def __init__(self, config): self.cmd_GET_RETRACTION, desc=self.cmd_GET_RETRACTION_help, ) + self.gcode.register_command( + "CLEAR_RETRACTION", + self.cmd_CLEAR_RETRACTION, + desc=self.cmd_CLEAR_RETRACTION_help, + ) + + # Register new G-code commands for firmware retraction/unretraction self.gcode.register_command("G10", self.cmd_G10) self.gcode.register_command("G11", self.cmd_G11) + # Register Events to clear retraction when a new print is started, an + # ongoing print is canceled or a print is finished + # GCode streaming mode (most commonly done via OctoPrint) + self.printer.register_event_handler( + "homing:homing_move_begin", self._evaluate_retraction + ) + self.printer.register_event_handler( + "stepper_enable:motor_off", self._evaluate_retraction + ) + + # Virtual SD card mode (Mainsail, Fluidd and DWC2-to-Klipper default) + # Only register events if Virtual SD Card enabled + if self.config_ref.has_section("virtual_sdcard"): + self.vsdcard = self.printer.lookup_object("virtual_sdcard") + self.printer.register_event_handler( + "virtual_sdcard:reset_file", self._reset_pause_flag + ) + self.printer.register_event_handler( + "print_stats:start_printing", self._evaluate_retraction + ) + self.printer.register_event_handler( + "print_stats:complete_printing", self._evaluate_retraction + ) + self.printer.register_event_handler( + "print_stats:cancelled_printing\ + ", + self._reset_pause_flag, + ) + self.printer.register_event_handler( + "print_stats:paused_printing", self._set_pause_flag + ) + + # Helper method to evaluate to clear retraction if certain events occur + # (must accept all arguments passed from event handlers) + def _evaluate_retraction(self, *args): + if self.is_retracted: # Check if retracted + if self.vsdcard_paused: # Check if VSDCard print paused + # Reset paused flag and hence do not clear retraction on + # resume command. + self.vsdcard_paused = False + else: + # If cancel command triggered pause event, clear retraction. + self._execute_clear_retraction() + + # Helper method to return the current retraction parameters def get_status(self, eventtime): return { "retract_length": self.retract_length, "retract_speed": self.retract_speed, "unretract_extra_length": self.unretract_extra_length, "unretract_speed": self.unretract_speed, + "z_hop_height": self.z_hop_height, + "unretract_length": self.unretract_length, + "retract_state": self.is_retracted, } + # Helper method to reset pause flags and force evaluate retraction + def _reset_pause_flag(self, *args): + self.vsdcard_paused = False + self._evaluate_retraction() + + # Helper method to set pause flag + def _set_pause_flag(self, *args): + self.vsdcard_paused = True + + # Command to set the firmware retraction parameters cmd_SET_RETRACTION_help = "Set firmware retraction parameters" def cmd_SET_RETRACTION(self, gcmd): + if not self.is_retracted: # Only execute command when unretracted + self._execute_set_retraction(gcmd) # Execute command immediately + else: + self.gcode.respond_info( + "WARNING: Printer in retract state. SET_RETRACTION will not be\ + executed!" + ) + + # Helper to set retraction parameters if command is called + def _execute_set_retraction(self, gcmd): self.retract_length = gcmd.get_float( "RETRACT_LENGTH", self.retract_length, minval=0.0 ) self.retract_speed = gcmd.get_float( - "RETRACT_SPEED", self.retract_speed, minval=1 + "RETRACT_SPEED", self.retract_speed, minval=1.0 ) self.unretract_extra_length = gcmd.get_float( - "UNRETRACT_EXTRA_LENGTH", self.unretract_extra_length, minval=0.0 + "UNRETRACT_EXTRA_LENGTH", self.unretract_extra_length, minval=-1.0 ) self.unretract_speed = gcmd.get_float( - "UNRETRACT_SPEED", self.unretract_speed, minval=1 + "UNRETRACT_SPEED", self.unretract_speed, minval=1.0 ) + self.z_hop_height = gcmd.get_float( + "Z_HOP_HEIGHT", self.z_hop_height, minval=0.0 + ) # z_hop_height with 0mm min. to prevent nozzle crash self.unretract_length = ( self.retract_length + self.unretract_extra_length ) - self.is_retracted = False + # Command to report the current firmware retraction parameters cmd_GET_RETRACTION_help = "Report firmware retraction paramters" def cmd_GET_RETRACTION(self, gcmd): gcmd.respond_info( - "RETRACT_LENGTH=%.5f RETRACT_SPEED=%.5f" - " UNRETRACT_EXTRA_LENGTH=%.5f UNRETRACT_SPEED=%.5f" + "RETRACT_LENGTH=%.5f RETRACT_SPEED=%.5f " + "UNRETRACT_EXTRA_LENGTH=%.5f UNRETRACT_SPEED=%.5f " + " Z_HOP_HEIGHT=%.5f " + " RETRACTED=%s " % ( self.retract_length, self.retract_speed, self.unretract_extra_length, self.unretract_speed, + self.z_hop_height, + self.is_retracted, ) ) + # Command to clear FW retraction (add to CANCEL macros at the beginning) + cmd_CLEAR_RETRACTION_help = "Clear retraction state without retract move \ + or zhop, if enabled" + + def cmd_CLEAR_RETRACTION(self, gcmd): + if self.is_retracted: + self._execute_clear_retraction() + gcmd.respond_info( + "Retraction was cleared and reset to config \ + values. zhop is undone on next move." + ) + else: + gcmd.respond_info( + "WARNING: Printer is not retracted. \ + Command has been ignored!" + ) + + # Helper to clear retraction + def _execute_clear_retraction(self): + if self.z_hop_height > 0.0: + # Re-establish regular G1 command if zhop enabled. + # zhop will be reversed on next move with z coordinate + self._re_register_G1() + self.G1_toggle_state = False # Prevent repeat re-register + self.is_retracted = False # Reset retract flag to enable G10 command + self._get_config_params() # Reset retraction parameters to config values + + # Gcode Command G10 to perform firmware retraction def cmd_G10(self, gcmd): - if not self.is_retracted: - self.gcode.run_script_from_command( + retract_gcode = "" # Reset retract string + zhop_gcode = "" # Reset zhop move string + + if self.retract_length == 0.0: # Check if FW retraction enabled + gcmd.respond_info( + "Retraction length zero. Firmware retraction \ + disabled. Command ignored!" + ) + elif not self.is_retracted: # If filament isn't retracted, build G-Code + # Incl move command if z_hop_height > 0 + if self.z_hop_height > 0.0: + # Determine z coordinate for zhop move + self._set_zhop_move_params() + # Set zhop gcode move + zhop_gcode = ("G1 Z{:.5f} F{}\n").format( + self.z_hop_Z, + int(ZHOP_MOVE_SPEED_FRACTION * self.max_vel * 60), + ) + + retract_gcode = ( "SAVE_GCODE_STATE NAME=_retract_state\n" "G91\n" - "G1 E-%.5f F%d\n" + "G1 E-{:.5f} F{}\n" # Retract filament at retract speed + "G90\n" # Switch to absolute mode (just in case) + "{}" "RESTORE_GCODE_STATE NAME=_retract_state" - % (self.retract_length, self.retract_speed * 60) + ).format( + self.retract_length, int(self.retract_speed * 60), zhop_gcode ) + + self.gcode.run_script_from_command(retract_gcode) self.is_retracted = True + if self.z_hop_height > 0.0: + # Swap original G1 handlers if z_hop enabled to offset following + # moves in eiter absolute or relative mode + self._unregister_G1() + self.G1_toggle_state = ( + True # Prevent repeat unregister with flag + ) + + else: + gcmd.respond_info("Printer is already retracted. Command ignored!") + + # Helper to determine zhop coordinate + def _set_zhop_move_params(self): + self.currentPos = self._get_gcode_pos() + self.currentZ = self.currentPos[2] + self.z_hop_Z = self.currentZ + self.z_hop_height + + # Helper to get current gcode position + def _get_gcode_pos(self): + # Get current gcode position for z_hop move if enabled + gcodestatus = self.gcode_move.get_status() + currentPos = gcodestatus["gcode_position"] + return currentPos + + # GCode Command G11 to perform filament unretraction def cmd_G11(self, gcmd): - if self.is_retracted: - self.gcode.run_script_from_command( - "SAVE_GCODE_STATE NAME=_retract_state\n" + unretract_gcode = "" # Reset unretract string + unzhop_gcode = "" # Reset un-zhop move string + + if self.retract_length == 0.0: # Check if FW retraction enabled + gcmd.respond_info( + "Retraction length zero. Firmware retraction \ + disabled. Command ignored!" + ) + elif self.is_retracted: # Check if the filament is retracted + if self.z_hop_height > 0.0: + self._re_register_G1() # Restore G1 handlers if z_hop on + self.G1_toggle_state = False # Prevent repeat re-register + # Set unzhop gcode move + unzhop_gcode = ("G1 Z-{:.5f} F{}\n").format( + self.z_hop_height, + int(ZHOP_MOVE_SPEED_FRACTION * self.max_vel * 60), + ) + + unretract_gcode = ( + "SAVE_GCODE_STATE NAME=_unretract_state\n" "G91\n" - "G1 E%.5f F%d\n" - "RESTORE_GCODE_STATE NAME=_retract_state" - % (self.unretract_length, self.unretract_speed * 60) + "{}" + "G1 E{:.5f} F{}\n" # Unretract filament + "RESTORE_GCODE_STATE NAME=_unretract_state" + ).format( + unzhop_gcode, + self.unretract_length, + int(self.unretract_speed * 60), + ) + + self.gcode.run_script_from_command(unretract_gcode) + self.is_retracted = False # Set the flag to filament unretracted + else: + gcmd.respond_info("Printer is not retracted. Command ignored!") + + # Register new G1 command handler + def _unregister_G1(self): + # Change handler only if G1 command has not been toggled before + if not self.G1_toggle_state: + self._toggle_gcode_comms( + "G1.20140114", + "G1", + self._G1_zhop, + "G1 command that accounts for z hop when retracted", + self.G1_toggle_state, + ) + self._toggle_gcode_comms( + "G0.20140114", + "G0", + self._G1_zhop, + "G0 command that accounts for z hop when retracted", + self.G1_toggle_state, + ) + + # Helper to toggle/untoggle command handlers and methods + def _toggle_gcode_comms( + self, + new_cmd_name, + old_cmd_name, + new_cmd_func, + new_cmd_desc, + toggle_state, + ): + # Unregister current method from current handler and store in prev_cmd + prev_cmd = self.gcode.register_command(old_cmd_name, None) + pdesc = 'Renamed builtin of "%s"' % old_cmd_name + if not toggle_state: + # Register prev method to toggled handler, indicate built-in command + self.gcode.register_command(new_cmd_name, prev_cmd, desc=pdesc) + self.gcode.register_command( + old_cmd_name, new_cmd_func, desc=new_cmd_desc + ) # Register toggled method to command handler + else: + # Unregister toggled command from the untoggled handler + self.gcode.register_command(new_cmd_name, new_cmd_func) + self.gcode.register_command( + new_cmd_name, prev_cmd, desc=new_cmd_desc + ) # Register untoggled method to untog handler + + # G1 method that accounts for z-hop by altering the z-coordinates + # Offsets are not touched to prevent incompatibility issues with user macros + def _G1_zhop(self, gcmd): + params = gcmd.get_command_parameters() + is_relative = self._toolhead_is_relative() + + if "Z" in params and not is_relative: + # In absolute, adjust Z param to account for Z-hop offset + params["Z"] = str(float(params["Z"]) + self.z_hop_height) + # In relative, don't adjust as Z-hop offset considered before + + new_g1_command = "G1.20140114" + for key, value in params.items(): + new_g1_command += " {0}{1}".format(key, value) + + # Run originl G1 (renamed G1.20140114) with adjusted parameters + self.gcode.run_script_from_command(new_g1_command) + + # Helper to get absolute/relative mode + def _toolhead_is_relative(self): + gcodestatus = self.gcode_move.get_status() + movemode = gcodestatus["absolute_coordinates"] + return not movemode + + # Re-register old G1 command handler + def _re_register_G1(self): + # Change handler only if G1 command has been toggled before + if self.G1_toggle_state: + self._toggle_gcode_comms( + "G1", "G1.20140114", None, "cmd_G1_help", self.G1_toggle_state + ) + self._toggle_gcode_comms( + "G0", "G0.20140114", None, "cmd_G1_help", self.G1_toggle_state ) - self.is_retracted = False def load_config(config): diff --git a/klippy/extras/print_stats.py b/klippy/extras/print_stats.py index b75cfcbb9..cf02c0df8 100644 --- a/klippy/extras/print_stats.py +++ b/klippy/extras/print_stats.py @@ -7,12 +7,12 @@ class PrintStats: def __init__(self, config): - printer = config.get_printer() - self.gcode_move = printer.load_object(config, "gcode_move") - self.reactor = printer.get_reactor() + self.printer = config.get_printer() + self.gcode_move = self.printer.load_object(config, "gcode_move") + self.reactor = self.printer.get_reactor() self.reset() # Register commands - self.gcode = printer.lookup_object("gcode") + self.gcode = self.printer.lookup_object("gcode") self.gcode.register_command( "SET_PRINT_STATS_INFO", self.cmd_SET_PRINT_STATS_INFO, @@ -44,6 +44,7 @@ def note_start(self): gc_status = self.gcode_move.get_status(curtime) self.last_epos = gc_status["position"].e self.state = "printing" + self.printer.send_event("print_stats:start_printing") self.error_message = "" def note_pause(self): @@ -54,15 +55,18 @@ def note_pause(self): self._update_filament_usage(curtime) if self.state != "error": self.state = "paused" + self.printer.send_event("print_stats:paused_printing") def note_complete(self): self._note_finish("complete") + self.printer.send_event("print_stats:complete_printing") def note_error(self, message): self._note_finish("error", message) def note_cancel(self): self._note_finish("cancelled") + self.printer.send_event("print_stats:cancelled_printing") def _note_finish(self, state, error_message=""): if self.print_start_time is None: diff --git a/test/klippy/firmware_retraction_with_VSDCard.cfg b/test/klippy/firmware_retraction_with_VSDCard.cfg new file mode 100644 index 000000000..6bd527fa5 --- /dev/null +++ b/test/klippy/firmware_retraction_with_VSDCard.cfg @@ -0,0 +1,120 @@ +# Config for firmware_retraction testing with Virtual SD Card module enabled +[virtual_sdcard] +path: test/klippy/sdcard_loop + +[display_status] + +[respond] +default_type: command + +[firmware_retraction] +retract_length: 3.0 +retract_speed: 45.0 +unretract_extra_length: 0.0 +unretract_speed: 45.0 +z_hop_height: 0.4 + +[stepper_x] +step_pin: PF0 +dir_pin: PF1 +enable_pin: !PD7 +microsteps: 16 +rotation_distance: 40 +endstop_pin: ^PE5 +position_endstop: 0 +position_max: 224 +homing_speed: 50 + +[stepper_y] +step_pin: PF6 +dir_pin: !PF7 +enable_pin: !PF2 +microsteps: 16 +rotation_distance: 40 +endstop_pin: ^PJ1 +position_endstop: 0 +position_max: 220 +homing_speed: 50 + +[stepper_z] +step_pin: PL3 +dir_pin: PL1 +enable_pin: !PK0 +microsteps: 16 +rotation_distance: 8 +endstop_pin: ^PD3 +position_endstop: 0 +position_max: 200 + +[extruder] +step_pin: PA4 +dir_pin: PA6 +enable_pin: !PA2 +microsteps: 16 +rotation_distance: 33.5 +nozzle_diameter: 0.400 +filament_diameter: 1.750 +heater_pin: PB4 +sensor_type: EPCOS 100K B57560G104F +sensor_pin: PK5 +control: pid +pid_Kp: 22.2 +pid_Ki: 1.08 +pid_Kd: 114 +min_temp: 0 +max_temp: 210 +min_extrude_temp: 0 + +[heater_bed] +heater_pin: PH5 +sensor_type: EPCOS 100K B57560G104F +sensor_pin: PK6 +control: watermark +min_temp: 0 +max_temp: 110 + +[mcu] +serial: /dev/ttyACM0 + +[printer] +kinematics: cartesian +max_velocity: 300 +max_accel: 3000 +max_z_velocity: 5 +max_z_accel: 100 + +[gcode_arcs] +resolution: 0.1 + +[homing_override] +gcode: + G28 X0 + G28 Y0 + G1 X112 Y110 + G28 Z0 + G1 Z8 + +[gcode_macro VERIFY_AXIS_POSITION] +gcode: + {% set axis_name = params.AXIS %} + {% set expected_position = params.EXPECTED|float %} + {% set axisstate_verbose = False %} + + {% set current_axis_position = printer.gcode_move.position[axis_name] %} + + {% if current_axis_position != expected_position %} + {action_raise_error("Wrong axis position for %s. Expected %f, got %f" + % (axis_name, expected_position, current_axis_position))} + {% else %} + {% if axisstate_verbose %} + M118 Axis {axis_name} OK! + {% endif %} + {% endif %} + +[gcode_macro CHECK_RECTRACTION_CLEARED] +gcode: + {% set retract_state = False %} + {% set retract_state = printer.firmware_retraction.retract_state %} + {% if retract_state == True %} + {action_raise_error("Retraction should be cleared!")} + {% endif%} diff --git a/test/klippy/firmware_retraction_with_VSDCard.test b/test/klippy/firmware_retraction_with_VSDCard.test new file mode 100644 index 000000000..45100cde4 --- /dev/null +++ b/test/klippy/firmware_retraction_with_VSDCard.test @@ -0,0 +1,212 @@ +# Tests Firmware retraction G10 and G11 with Virtual SD Card ENABLED + +DICTIONARY atmega2560.dict +CONFIG firmware_retraction_with_VSDCard.cfg + +CLEAR_RETRACTION +G90 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=0.0 + +################################### CHECK DISABLED RETRACTION WITH ZHOP DISABLED +G28 +SET_RETRACTION RETRACT_LENGTH=0.0 UNRETRACT_EXTRA_LENGTH=0.0 Z_HOP_HEIGHT=0.0 +G10 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=0.0 +G11 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=0.0 + +############# CHECK RETRACTION CLEAR ON STEPPER DISABLE EVENT WITH ZHOP DISABLED +SET_RETRACTION RETRACT_LENGTH=2.5 UNRETRACT_EXTRA_LENGTH=1.0 Z_HOP_HEIGHT=0.0 +G10 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-2.5 +M84 +CHECK_RECTRACTION_CLEARED + +###################### CHECK RETRACTION CLEAR ON HOMING EVENT WITH ZHOP DISABLED +G28 +SET_RETRACTION RETRACT_LENGTH=2.5 UNRETRACT_EXTRA_LENGTH=1.0 Z_HOP_HEIGHT=0.0 +G10 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-5.0 +G28 +CHECK_RECTRACTION_CLEARED + +############## CHECK RETRACTION CLEAR ON STEPPER DISABLE EVENT WITH ZHOP ENABLED +SET_RETRACTION RETRACT_LENGTH=2.5 UNRETRACT_EXTRA_LENGTH=1.0 Z_HOP_HEIGHT=2.0 +G10 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-7.5 +M84 +CHECK_RECTRACTION_CLEARED + +####################### CHECK RETRACTION CLEAR ON HOMING EVENT WITH ZHOP ENABLED +G28 +SET_RETRACTION RETRACT_LENGTH=2.5 UNRETRACT_EXTRA_LENGTH=1.0 Z_HOP_HEIGHT=2.0 +G10 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-10.0 +G28 +CHECK_RECTRACTION_CLEARED + +############################################## SET PRINTER UP FOR MOVEMENT TESTS +SET_RETRACTION RETRACT_LENGTH=2.5 UNRETRACT_EXTRA_LENGTH=1.0 Z_HOP_HEIGHT=0.0 +G1 X100.0 Y100.0 Z20.0 +G91 +G1 E10.0 +G90 + +####################################################### TESTING FW WITHOUT Z_HOP + +# Unretract in unretract state +G11 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=0.0 + +# Retract in unretract state +G10 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-2.5 + +# Repeat Retract +G10 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-2.5 + +# Unretract in retract state +G11 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=1.0 + +# Second round: Retract in unretract state +G10 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +# Second round: Unretract in retract state +G11 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=2.0 +# Compensate for second round +G91 +G1 E-1.0 +G90 + +###################################################### TESTING FW Z_HOP STANDARD + +SET_RETRACTION UNRETRACT_EXTRA_LENGTH=0.0 +SET_RETRACTION Z_HOP_HEIGHT=2.0 + +# Retract with Standard zhop +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +# Repeat retract with Standard zhop +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +# Unretract with Standard zhop in retract state +G11 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=20.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=1.0 + +# Second round: Retract with Standard zhop +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +# Second round: Unretract with Standard zhop in retract state +G11 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=20.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=1.0 + +#################################### TESTING CHANGE Z_HOP_HEIGHT WHILE RETRACTED + +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 +SET_RETRACTION Z_HOP_HEIGHT=3.0 +G11 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=20.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=1.0 + +################ TESTING MOVE Z WHILE RETRACTED WITH SWITCH TO RELATIVE AND BACK + +SET_RETRACTION Z_HOP_HEIGHT=2.0 +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +# Switch to relative mode while retracted +G91 +G1 Z-10.0 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=12.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +# Switch back to absolute mode +G90 +G11 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=10.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=1.0 + +################################################ TESTING MOVE XY WHILE RETRACTED + +# Test XY Move in Standard +G1 Z20.0 +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +G1 X90.0 Y90.0 +VERIFY_AXIS_POSITION AXIS=x EXPECTED=90.0 +VERIFY_AXIS_POSITION AXIS=y EXPECTED=90.0 + +G11 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=20.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=1.0 + +G1 X100.0 Y100.0 +VERIFY_AXIS_POSITION AXIS=x EXPECTED=100.0 +VERIFY_AXIS_POSITION AXIS=y EXPECTED=100.0 + +####################################################### TESTING CLEAR RETRACTION +G1 X90.0 Y90.0 Z20.0 + +# Test CLEAR_RETRACTION while unretracted +CLEAR_RETRACTION + +# Test CLEAR_RETRACTION while retracted +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 +CLEAR_RETRACTION +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +# Unretract after clearing retraction +G11 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +# Test CLEAR_RETRACTION while retracted, 2nd go +SET_RETRACTION Z_HOP_HEIGHT=2.0 +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=24.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-4.5 +CLEAR_RETRACTION +VERIFY_AXIS_POSITION AXIS=z EXPECTED=24.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-4.5 + +# Unretract after clearing retraction and retracting +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=24.4 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-7.5 +G11 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=24.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-4.5 +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=24.4 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-7.5 + +# Test first move with z coordinate after retraction was cleared +G1 X100.0 Y100.0 Z28.0 +VERIFY_AXIS_POSITION AXIS=x EXPECTED=100.0 +VERIFY_AXIS_POSITION AXIS=y EXPECTED=100.0 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=28.4 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-7.5 +G11 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=28.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-4.5 +M118 Test successful! diff --git a/test/klippy/firmware_retraction_without_VSDCard.cfg b/test/klippy/firmware_retraction_without_VSDCard.cfg new file mode 100644 index 000000000..7364eec9b --- /dev/null +++ b/test/klippy/firmware_retraction_without_VSDCard.cfg @@ -0,0 +1,117 @@ +# Config for firmware_retraction testing with Virtual SD Card module disabled +[display_status] + +[respond] +default_type: command + +[firmware_retraction] +retract_length: 3.0 +retract_speed: 45.0 +unretract_extra_length: 0.0 +unretract_speed: 45.0 +z_hop_height: 0.4 + +[stepper_x] +step_pin: PF0 +dir_pin: PF1 +enable_pin: !PD7 +microsteps: 16 +rotation_distance: 40 +endstop_pin: ^PE5 +position_endstop: 0 +position_max: 224 +homing_speed: 50 + +[stepper_y] +step_pin: PF6 +dir_pin: !PF7 +enable_pin: !PF2 +microsteps: 16 +rotation_distance: 40 +endstop_pin: ^PJ1 +position_endstop: 0 +position_max: 220 +homing_speed: 50 + +[stepper_z] +step_pin: PL3 +dir_pin: PL1 +enable_pin: !PK0 +microsteps: 16 +rotation_distance: 8 +endstop_pin: ^PD3 +position_endstop: 0 +position_max: 200 + +[extruder] +step_pin: PA4 +dir_pin: PA6 +enable_pin: !PA2 +microsteps: 16 +rotation_distance: 33.5 +nozzle_diameter: 0.400 +filament_diameter: 1.750 +heater_pin: PB4 +sensor_type: EPCOS 100K B57560G104F +sensor_pin: PK5 +control: pid +pid_Kp: 22.2 +pid_Ki: 1.08 +pid_Kd: 114 +min_temp: 0 +max_temp: 210 +min_extrude_temp: 0 + +[heater_bed] +heater_pin: PH5 +sensor_type: EPCOS 100K B57560G104F +sensor_pin: PK6 +control: watermark +min_temp: 0 +max_temp: 110 + +[mcu] +serial: /dev/ttyACM0 + +[printer] +kinematics: cartesian +max_velocity: 300 +max_accel: 3000 +max_z_velocity: 5 +max_z_accel: 100 + +[gcode_arcs] +resolution: 0.1 + +[homing_override] +gcode: + G28 X0 + G28 Y0 + G1 X112 Y110 + G28 Z0 + G1 X112 Y110 Z8 + +[gcode_macro VERIFY_AXIS_POSITION] +gcode: + {% set axis_name = params.AXIS %} + {% set expected_position = params.EXPECTED|float %} + {% set axisstate_verbose = False %} + + {% set current_axis_position = printer.gcode_move.position[axis_name] %} + + {% if current_axis_position != expected_position %} + {action_raise_error("Wrong axis position for %s. Expected %f, got %f" + % (axis_name, expected_position, current_axis_position))} + {% else %} + {% if axisstate_verbose %} + M118 Axis {axis_name} OK! + {% endif %} + {% endif %} + +[gcode_macro CHECK_RECTRACTION_CLEARED] +gcode: + {% set retract_state = False %} + {% set retract_state = printer.firmware_retraction.retract_state %} + {% if retract_state == True %} + {action_raise_error("Retraction should be cleared!")} + {% endif%} diff --git a/test/klippy/firmware_retraction_without_VSDCard.test b/test/klippy/firmware_retraction_without_VSDCard.test new file mode 100644 index 000000000..bea144032 --- /dev/null +++ b/test/klippy/firmware_retraction_without_VSDCard.test @@ -0,0 +1,212 @@ +# Tests Firmware retraction G10 and G11 with Virtual SD Card DISABLED + +DICTIONARY atmega2560.dict +CONFIG firmware_retraction_without_VSDCard.cfg + +CLEAR_RETRACTION +G90 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=0.0 + +################################### CHECK DISABLED RETRACTION WITH ZHOP DISABLED +G28 +SET_RETRACTION RETRACT_LENGTH=0.0 UNRETRACT_EXTRA_LENGTH=0.0 Z_HOP_HEIGHT=0.0 +G10 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=0.0 +G11 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=0.0 + +############# CHECK RETRACTION CLEAR ON STEPPER DISABLE EVENT WITH ZHOP DISABLED +SET_RETRACTION RETRACT_LENGTH=2.5 UNRETRACT_EXTRA_LENGTH=1.0 Z_HOP_HEIGHT=0.0 +G10 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-2.5 +M84 +CHECK_RECTRACTION_CLEARED + +###################### CHECK RETRACTION CLEAR ON HOMING EVENT WITH ZHOP DISABLED +G28 +SET_RETRACTION RETRACT_LENGTH=2.5 UNRETRACT_EXTRA_LENGTH=1.0 Z_HOP_HEIGHT=0.0 +G10 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-5.0 +G28 +CHECK_RECTRACTION_CLEARED + +############## CHECK RETRACTION CLEAR ON STEPPER DISABLE EVENT WITH ZHOP ENABLED +SET_RETRACTION RETRACT_LENGTH=2.5 UNRETRACT_EXTRA_LENGTH=1.0 Z_HOP_HEIGHT=2.0 +G10 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-7.5 +M84 +CHECK_RECTRACTION_CLEARED + +####################### CHECK RETRACTION CLEAR ON HOMING EVENT WITH ZHOP ENABLED +G28 +SET_RETRACTION RETRACT_LENGTH=2.5 UNRETRACT_EXTRA_LENGTH=1.0 Z_HOP_HEIGHT=2.0 +G10 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-10.0 +G28 +CHECK_RECTRACTION_CLEARED + +############################################## SET PRINTER UP FOR MOVEMENT TESTS +SET_RETRACTION RETRACT_LENGTH=2.5 UNRETRACT_EXTRA_LENGTH=1.0 Z_HOP_HEIGHT=0.0 +G1 X100.0 Y100.0 Z20.0 +G91 +G1 E10.0 +G90 + +####################################################### TESTING FW WITHOUT Z_HOP + +# Unretract in unretract state +G11 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=0.0 + +# Retract in unretract state +G10 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-2.5 + +# Repeat Retract +G10 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-2.5 + +# Unretract in retract state +G11 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=1.0 + +# Second round: Retract in unretract state +G10 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +# Second round: Unretract in retract state +G11 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=2.0 +# Compensate for second round +G91 +G1 E-1.0 +G90 + +###################################################### TESTING FW Z_HOP STANDARD + +SET_RETRACTION UNRETRACT_EXTRA_LENGTH=0.0 +SET_RETRACTION Z_HOP_HEIGHT=2.0 + +# Retract with Standard zhop +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +# Repeat retract with Standard zhop +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +# Unretract with Standard zhop in retract state +G11 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=20.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=1.0 + +# Second round: Retract with Standard zhop +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +# Second round: Unretract with Standard zhop in retract state +G11 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=20.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=1.0 + +#################################### TESTING CHANGE Z_HOP_HEIGHT WHILE RETRACTED + +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 +SET_RETRACTION Z_HOP_HEIGHT=3.0 +G11 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=20.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=1.0 + +################ TESTING MOVE Z WHILE RETRACTED WITH SWITCH TO RELATIVE AND BACK + +SET_RETRACTION Z_HOP_HEIGHT=2.0 +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +# Switch to relative mode while retracted +G91 +G1 Z-10.0 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=12.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +# Switch back to absolute mode +G90 +G11 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=10.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=1.0 + +################################################ TESTING MOVE XY WHILE RETRACTED + +# Test XY Move in Standard +G1 Z20.0 +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +G1 X90.0 Y90.0 +VERIFY_AXIS_POSITION AXIS=x EXPECTED=90.0 +VERIFY_AXIS_POSITION AXIS=y EXPECTED=90.0 + +G11 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=20.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=1.0 + +G1 X100.0 Y100.0 +VERIFY_AXIS_POSITION AXIS=x EXPECTED=100.0 +VERIFY_AXIS_POSITION AXIS=y EXPECTED=100.0 + +####################################################### TESTING CLEAR RETRACTION +G1 X90.0 Y90.0 Z20.0 + +# Test CLEAR_RETRACTION while unretracted +CLEAR_RETRACTION + +# Test CLEAR_RETRACTION while retracted +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 +CLEAR_RETRACTION +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +# Unretract after clearing retraction +G11 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=22.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-1.5 + +# Test CLEAR_RETRACTION while retracted, 2nd go +SET_RETRACTION Z_HOP_HEIGHT=2.0 +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=24.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-4.5 +CLEAR_RETRACTION +VERIFY_AXIS_POSITION AXIS=z EXPECTED=24.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-4.5 + +# Unretract after clearing retraction and retracting +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=24.4 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-7.5 +G11 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=24.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-4.5 +G10 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=24.4 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-7.5 + +# Test first move with z coordinate after retraction was cleared +G1 X100.0 Y100.0 Z28.0 +VERIFY_AXIS_POSITION AXIS=x EXPECTED=100.0 +VERIFY_AXIS_POSITION AXIS=y EXPECTED=100.0 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=28.4 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-7.5 +G11 +VERIFY_AXIS_POSITION AXIS=z EXPECTED=28.0 +VERIFY_AXIS_POSITION AXIS=e EXPECTED=-4.5 +M118 Test successful!