diff --git a/docs/G-Codes.md b/docs/G-Codes.md index e0fef5ad..d52294e2 100644 --- a/docs/G-Codes.md +++ b/docs/G-Codes.md @@ -303,11 +303,13 @@ extruder. #### SET_EXTRUDER_ROTATION_DISTANCE `SET_EXTRUDER_ROTATION_DISTANCE EXTRUDER= [DISTANCE=]`: Set a new value for the provided extruder's -"rotation distance". Value is not retained on Klipper reset. Use with -caution as small changes can result in excessive pressure between -extruder and hot end. Do proper calibration with filament before use. -If 'DISTANCE' value is not included command will return current -rotation distance. +"rotation distance". If the rotation distance is a negative number +then the stepper motion will be inverted (relative to the stepper +direction specified in the config file). Changed settings are not +retained on Klipper reset. Use with caution as small changes can +result in excessive pressure between extruder and hot end. Do proper +calibration with filament before use. If 'DISTANCE' value is not +included command will return current rotation distance. #### SET_EXTRUDER_STEP_DISTANCE `SET_EXTRUDER_STEP_DISTANCE EXTRUDER= diff --git a/klippy/chelper/__init__.py b/klippy/chelper/__init__.py index e04d431d..c7e2155c 100644 --- a/klippy/chelper/__init__.py +++ b/klippy/chelper/__init__.py @@ -38,8 +38,9 @@ defs_stepcompress = """ struct stepcompress *stepcompress_alloc(uint32_t oid); void stepcompress_fill(struct stepcompress *sc, uint32_t max_error - , uint32_t invert_sdir, int32_t queue_step_msgtag - , int32_t set_next_step_dir_msgtag); + , int32_t queue_step_msgtag, int32_t set_next_step_dir_msgtag); + void stepcompress_set_invert_sdir(struct stepcompress *sc + , uint32_t invert_sdir); void stepcompress_free(struct stepcompress *sc); int stepcompress_reset(struct stepcompress *sc, uint64_t last_step_clock); int stepcompress_set_last_position(struct stepcompress *sc diff --git a/klippy/chelper/stepcompress.c b/klippy/chelper/stepcompress.c index b38b72ad..e261f1d3 100644 --- a/klippy/chelper/stepcompress.c +++ b/klippy/chelper/stepcompress.c @@ -259,15 +259,25 @@ stepcompress_alloc(uint32_t oid) // Fill message id information void __visible stepcompress_fill(struct stepcompress *sc, uint32_t max_error - , uint32_t invert_sdir, int32_t queue_step_msgtag - , int32_t set_next_step_dir_msgtag) + , int32_t queue_step_msgtag, int32_t set_next_step_dir_msgtag) { sc->max_error = max_error; - sc->invert_sdir = !!invert_sdir; sc->queue_step_msgtag = queue_step_msgtag; sc->set_next_step_dir_msgtag = set_next_step_dir_msgtag; } +// Set the inverted stepper direction flag +void __visible +stepcompress_set_invert_sdir(struct stepcompress *sc, uint32_t invert_sdir) +{ + invert_sdir = !!invert_sdir; + if (invert_sdir != sc->invert_sdir) { + sc->invert_sdir = invert_sdir; + if (sc->sdir >= 0) + sc->sdir ^= 1; + } +} + // Helper to free items from the history_list static void free_history(struct stepcompress *sc, uint64_t end_clock) diff --git a/klippy/chelper/stepcompress.h b/klippy/chelper/stepcompress.h index 5bca39a5..b8a95057 100644 --- a/klippy/chelper/stepcompress.h +++ b/klippy/chelper/stepcompress.h @@ -13,8 +13,10 @@ struct pull_history_steps { struct stepcompress *stepcompress_alloc(uint32_t oid); void stepcompress_fill(struct stepcompress *sc, uint32_t max_error - , uint32_t invert_sdir, int32_t queue_step_msgtag + , int32_t queue_step_msgtag , int32_t set_next_step_dir_msgtag); +void stepcompress_set_invert_sdir(struct stepcompress *sc + , uint32_t invert_sdir); void stepcompress_free(struct stepcompress *sc); uint32_t stepcompress_get_oid(struct stepcompress *sc); int stepcompress_get_step_dir(struct stepcompress *sc); diff --git a/klippy/extras/motion_report.py b/klippy/extras/motion_report.py index 10cf3583..34fc455d 100644 --- a/klippy/extras/motion_report.py +++ b/klippy/extras/motion_report.py @@ -139,7 +139,7 @@ class DumpStepper: mcu_pos = first.start_position start_position = self.mcu_stepper.mcu_to_commanded_position(mcu_pos) step_dist = self.mcu_stepper.get_step_dist() - if self.mcu_stepper.is_dir_inverted(): + if self.mcu_stepper.get_dir_inverted()[0]: step_dist = -step_dist d = [(s.interval, s.step_count, s.add) for s in data] return {"data": d, "start_position": start_position, diff --git a/klippy/extras/tmc.py b/klippy/extras/tmc.py index 767ada39..18aad419 100644 --- a/klippy/extras/tmc.py +++ b/klippy/extras/tmc.py @@ -224,6 +224,8 @@ class TMCCommandHelper: self.stepper_enable = self.printer.load_object(config, "stepper_enable") self.printer.register_event_handler("stepper:sync_mcu_position", self._handle_sync_mcu_pos) + self.printer.register_event_handler("stepper:set_sdir_inverted", + self._handle_sync_mcu_pos) self.printer.register_event_handler("klippy:mcu_identify", self._handle_mcu_identify) self.printer.register_event_handler("klippy:connect", @@ -306,7 +308,7 @@ class TMCCommandHelper: if enable_line.is_motor_enabled(): raise return - if not stepper.is_dir_inverted(): + if not stepper.get_dir_inverted()[0]: driver_phase = 1023 - driver_phase phases = self._get_phases() phase = int(float(driver_phase) / 1024 * phases + .5) % phases diff --git a/klippy/kinematics/extruder.py b/klippy/kinematics/extruder.py index 52c2e187..2749f63c 100644 --- a/klippy/kinematics/extruder.py +++ b/klippy/kinematics/extruder.py @@ -91,13 +91,24 @@ class ExtruderStepper: gcmd.respond_info(msg, log=False) cmd_SET_E_ROTATION_DISTANCE_help = "Set extruder rotation distance" def cmd_SET_E_ROTATION_DISTANCE(self, gcmd): - rotation_dist = gcmd.get_float('DISTANCE', None, above=0.) + rotation_dist = gcmd.get_float('DISTANCE', None) if rotation_dist is not None: + if not rotation_dist: + raise gcmd.error("Rotation distance can not be zero") + invert_dir, orig_invert_dir = self.stepper.get_dir_inverted() + next_invert_dir = orig_invert_dir + if rotation_dist < 0.: + next_invert_dir = not orig_invert_dir + rotation_dist = -rotation_dist toolhead = self.printer.lookup_object('toolhead') toolhead.flush_step_generation() self.stepper.set_rotation_distance(rotation_dist) + self.stepper.set_dir_inverted(next_invert_dir) else: rotation_dist, spr = self.stepper.get_rotation_distance() + invert_dir, orig_invert_dir = self.stepper.get_dir_inverted() + if invert_dir != orig_invert_dir: + rotation_dist = -rotation_dist gcmd.respond_info("Extruder '%s' rotation distance set to %0.6f" % (self.name, rotation_dist)) cmd_SET_E_STEP_DISTANCE_help = "Set extruder step distance" diff --git a/klippy/stepper.py b/klippy/stepper.py index 9ef3fcc4..e009d7b6 100644 --- a/klippy/stepper.py +++ b/klippy/stepper.py @@ -36,7 +36,7 @@ class MCU_stepper: raise self._mcu.get_printer().config_error( "Stepper dir pin must be on same mcu as step pin") self._dir_pin = dir_pin_params['pin'] - self._invert_dir = dir_pin_params['invert'] + self._invert_dir = self._orig_invert_dir = dir_pin_params['invert'] self._step_both_edge = self._req_step_both_edge = False self._mcu_position_offset = 0. self._reset_cmd_tag = self._get_position_cmd = None @@ -44,6 +44,7 @@ class MCU_stepper: ffi_main, ffi_lib = chelper.get_ffi() self._stepqueue = ffi_main.gc(ffi_lib.stepcompress_alloc(oid), ffi_lib.stepcompress_free) + ffi_lib.stepcompress_set_invert_sdir(self._stepqueue, self._invert_dir) self._mcu.register_stepqueue(self._stepqueue) self._stepper_kinematics = None self._itersolve_generate_steps = ffi_lib.itersolve_generate_steps @@ -101,7 +102,7 @@ class MCU_stepper: max_error_ticks = self._mcu.seconds_to_clock(max_error) ffi_main, ffi_lib = chelper.get_ffi() ffi_lib.stepcompress_fill(self._stepqueue, max_error_ticks, - self._invert_dir, step_cmd_tag, dir_cmd_tag) + step_cmd_tag, dir_cmd_tag) def get_oid(self): return self._oid def get_step_dist(self): @@ -114,8 +115,16 @@ class MCU_stepper: self._step_dist = rotation_dist / self._steps_per_rotation self.set_stepper_kinematics(self._stepper_kinematics) self._set_mcu_position(mcu_pos) - def is_dir_inverted(self): - return self._invert_dir + def get_dir_inverted(self): + return self._invert_dir, self._orig_invert_dir + def set_dir_inverted(self, invert_dir): + invert_dir = not not invert_dir + if invert_dir == self._invert_dir: + return + self._invert_dir = invert_dir + ffi_main, ffi_lib = chelper.get_ffi() + ffi_lib.stepcompress_set_invert_sdir(self._stepqueue, invert_dir) + self._mcu.get_printer().send_event("stepper:set_dir_inverted", self) def calc_position_from_coord(self, coord): ffi_main, ffi_lib = chelper.get_ffi() return ffi_lib.itersolve_calc_position_from_coord( diff --git a/test/klippy/extruders.test b/test/klippy/extruders.test index ff7c5917..889d5e34 100644 --- a/test/klippy/extruders.test +++ b/test/klippy/extruders.test @@ -13,9 +13,13 @@ G1 X20 Y20 Z1 G1 X25 Y25 E7.5 # Update step_distance -SET_EXTRUDER_STEP_DISTANCE EXTRUDER=extruder DISTANCE=.005 +SET_EXTRUDER_ROTATION_DISTANCE EXTRUDER=extruder DISTANCE=33.2 G1 X30 Y30 E8.0 +# Reverse step_distance +SET_EXTRUDER_ROTATION_DISTANCE EXTRUDER=extruder DISTANCE=-33.1 +G1 X30 Y30 E8.2 + # Disable extruder stepper motor SYNC_STEPPER_TO_EXTRUDER STEPPER=extruder EXTRUDER= G1 X35 Y35 E8.5