From ffbd2698fe906dbfc4b21923989b9679adf8561b Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Tue, 11 Jan 2022 14:21:57 -0500 Subject: [PATCH] extruder: Separate extruder stepper tracking to new ExtruderStepper class Move the stepper handling (including pressure advance handling) to a new class. Signed-off-by: Kevin O'Connor --- klippy/kinematics/extruder.py | 172 +++++++++++++++++++--------------- 1 file changed, 97 insertions(+), 75 deletions(-) diff --git a/klippy/kinematics/extruder.py b/klippy/kinematics/extruder.py index 852f576f..c042a2dd 100644 --- a/klippy/kinematics/extruder.py +++ b/klippy/kinematics/extruder.py @@ -1,15 +1,94 @@ # Code for handling printer nozzle extruders # -# Copyright (C) 2016-2019 Kevin O'Connor +# Copyright (C) 2016-2022 Kevin O'Connor # # This file may be distributed under the terms of the GNU GPLv3 license. import math, logging import stepper, chelper +class ExtruderStepper: + def __init__(self, config): + self.printer = config.get_printer() + self.name = config.get_name() + self.pressure_advance = self.pressure_advance_smooth_time = 0. + # Setup stepper + self.stepper = stepper.PrinterStepper(config) + ffi_main, ffi_lib = chelper.get_ffi() + self.sk_extruder = ffi_main.gc(ffi_lib.extruder_stepper_alloc(), + ffi_lib.free) + self.stepper.set_stepper_kinematics(self.sk_extruder) + toolhead = self.printer.lookup_object('toolhead') + toolhead.register_step_generator(self.stepper.generate_steps) + # Register commands + gcode = self.printer.lookup_object('gcode') + if self.name == 'extruder': + gcode.register_mux_command("SET_PRESSURE_ADVANCE", "EXTRUDER", None, + self.cmd_default_SET_PRESSURE_ADVANCE, + desc=self.cmd_SET_PRESSURE_ADVANCE_help) + gcode.register_mux_command("SET_PRESSURE_ADVANCE", "EXTRUDER", + self.name, self.cmd_SET_PRESSURE_ADVANCE, + desc=self.cmd_SET_PRESSURE_ADVANCE_help) + gcode.register_mux_command("SET_EXTRUDER_STEP_DISTANCE", "EXTRUDER", + self.name, self.cmd_SET_E_STEP_DISTANCE, + desc=self.cmd_SET_E_STEP_DISTANCE_help) + def get_status(self, eventtime): + return {'pressure_advance': self.pressure_advance, + 'smooth_time': self.pressure_advance_smooth_time} + def find_past_position(self, print_time): + mcu_pos = self.stepper.get_past_mcu_position(print_time) + return self.stepper.mcu_to_commanded_position(mcu_pos) + def _set_pressure_advance(self, pressure_advance, smooth_time): + old_smooth_time = self.pressure_advance_smooth_time + if not self.pressure_advance: + old_smooth_time = 0. + new_smooth_time = smooth_time + if not pressure_advance: + new_smooth_time = 0. + toolhead = self.printer.lookup_object("toolhead") + toolhead.note_step_generation_scan_time(new_smooth_time * .5, + old_delay=old_smooth_time * .5) + ffi_main, ffi_lib = chelper.get_ffi() + espa = ffi_lib.extruder_set_pressure_advance + espa(self.sk_extruder, pressure_advance, new_smooth_time) + self.pressure_advance = pressure_advance + self.pressure_advance_smooth_time = smooth_time + cmd_SET_PRESSURE_ADVANCE_help = "Set pressure advance parameters" + def cmd_default_SET_PRESSURE_ADVANCE(self, gcmd): + extruder = self.printer.lookup_object('toolhead').get_extruder() + extruder.extruder_stepper.cmd_SET_PRESSURE_ADVANCE(gcmd) + def cmd_SET_PRESSURE_ADVANCE(self, gcmd): + pressure_advance = gcmd.get_float('ADVANCE', self.pressure_advance, + minval=0.) + smooth_time = gcmd.get_float('SMOOTH_TIME', + self.pressure_advance_smooth_time, + minval=0., maxval=.200) + self._set_pressure_advance(pressure_advance, smooth_time) + msg = ("pressure_advance: %.6f\n" + "pressure_advance_smooth_time: %.6f" + % (pressure_advance, smooth_time)) + self.printer.set_rollover_info(self.name, "%s: %s" % (self.name, msg)) + gcmd.respond_info(msg, log=False) + cmd_SET_E_STEP_DISTANCE_help = "Set extruder step distance" + def cmd_SET_E_STEP_DISTANCE(self, gcmd): + toolhead = self.printer.lookup_object('toolhead') + dist = gcmd.get_float('DISTANCE', None, above=0.) + if dist is None: + step_dist = self.stepper.get_step_dist() + gcmd.respond_info("Extruder '%s' step distance is %0.6f" + % (self.name, step_dist)) + return + toolhead.flush_step_generation() + self.stepper.set_step_dist(dist) + gcmd.respond_info("Extruder '%s' step distance set to %0.6f" + % (self.name, dist)) + +# Tracking for hotend heater, extrusion motion queue, and extruder stepper class PrinterExtruder: def __init__(self, config, extruder_num): self.printer = config.get_printer() self.name = config.get_name() + self.last_position = 0. + # Setup hotend heater shared_heater = config.get('shared_heater', None) pheaters = self.printer.load_object(config, 'heaters') gcode_id = 'T%d' % (extruder_num,) @@ -17,7 +96,7 @@ class PrinterExtruder: self.heater = pheaters.setup_heater(config, gcode_id) else: self.heater = pheaters.lookup_heater(shared_heater) - self.stepper = stepper.PrinterStepper(config) + # Setup kinematic checks self.nozzle_diameter = config.getfloat('nozzle_diameter', above=0.) filament_diameter = config.getfloat( 'filament_diameter', minval=self.nozzle_diameter) @@ -40,61 +119,34 @@ class PrinterExtruder: 'max_extrude_only_distance', 50., minval=0.) self.instant_corner_v = config.getfloat( 'instantaneous_corner_velocity', 1., minval=0.) - self.pressure_advance = self.pressure_advance_smooth_time = 0. - pressure_advance = config.getfloat('pressure_advance', 0., minval=0.) - smooth_time = config.getfloat('pressure_advance_smooth_time', - 0.040, above=0., maxval=.200) - # Setup iterative solver + # Setup extruder trapq (trapezoidal motion queue) ffi_main, ffi_lib = chelper.get_ffi() self.trapq = ffi_main.gc(ffi_lib.trapq_alloc(), ffi_lib.trapq_free) self.trapq_append = ffi_lib.trapq_append self.trapq_finalize_moves = ffi_lib.trapq_finalize_moves - self.sk_extruder = ffi_main.gc(ffi_lib.extruder_stepper_alloc(), - ffi_lib.free) - self.stepper.set_stepper_kinematics(self.sk_extruder) - self.stepper.set_trapq(self.trapq) - toolhead.register_step_generator(self.stepper.generate_steps) - self._set_pressure_advance(pressure_advance, smooth_time) + # Setup extruder stepper + self.extruder_stepper = ExtruderStepper(config) + self.extruder_stepper.stepper.set_trapq(self.trapq) + pa = config.getfloat('pressure_advance', 0., minval=0.) + smooth_time = config.getfloat('pressure_advance_smooth_time', + 0.040, above=0., maxval=.200) + self.extruder_stepper._set_pressure_advance(pa, smooth_time) # Register commands gcode = self.printer.lookup_object('gcode') if self.name == 'extruder': toolhead.set_extruder(self, 0.) gcode.register_command("M104", self.cmd_M104) gcode.register_command("M109", self.cmd_M109) - gcode.register_mux_command("SET_PRESSURE_ADVANCE", "EXTRUDER", None, - self.cmd_default_SET_PRESSURE_ADVANCE, - desc=self.cmd_SET_PRESSURE_ADVANCE_help) - gcode.register_mux_command("SET_PRESSURE_ADVANCE", "EXTRUDER", - self.name, self.cmd_SET_PRESSURE_ADVANCE, - desc=self.cmd_SET_PRESSURE_ADVANCE_help) gcode.register_mux_command("ACTIVATE_EXTRUDER", "EXTRUDER", self.name, self.cmd_ACTIVATE_EXTRUDER, desc=self.cmd_ACTIVATE_EXTRUDER_help) - gcode.register_mux_command("SET_EXTRUDER_STEP_DISTANCE", "EXTRUDER", - self.name, self.cmd_SET_E_STEP_DISTANCE, - desc=self.cmd_SET_E_STEP_DISTANCE_help) def update_move_time(self, flush_time): self.trapq_finalize_moves(self.trapq, flush_time) - def _set_pressure_advance(self, pressure_advance, smooth_time): - old_smooth_time = self.pressure_advance_smooth_time - if not self.pressure_advance: - old_smooth_time = 0. - new_smooth_time = smooth_time - if not pressure_advance: - new_smooth_time = 0. - toolhead = self.printer.lookup_object("toolhead") - toolhead.note_step_generation_scan_time(new_smooth_time * .5, - old_delay=old_smooth_time * .5) - ffi_main, ffi_lib = chelper.get_ffi() - espa = ffi_lib.extruder_set_pressure_advance - espa(self.sk_extruder, pressure_advance, new_smooth_time) - self.pressure_advance = pressure_advance - self.pressure_advance_smooth_time = smooth_time def get_status(self, eventtime): - return dict(self.heater.get_status(eventtime), - can_extrude=self.heater.can_extrude, - pressure_advance=self.pressure_advance, - smooth_time=self.pressure_advance_smooth_time) + sts = self.heater.get_status(eventtime) + sts['can_extrude'] = self.heater.can_extrude + sts.update(self.extruder_stepper.get_status(eventtime)) + return sts def get_name(self): return self.name def get_heater(self): @@ -104,8 +156,7 @@ class PrinterExtruder: def sync_stepper(self, stepper): toolhead = self.printer.lookup_object('toolhead') toolhead.flush_step_generation() - epos = self.stepper.get_commanded_position() - stepper.set_position([epos, 0., 0.]) + stepper.set_position([self.last_position, 0., 0.]) stepper.set_trapq(self.trapq) def stats(self, eventtime): return self.heater.stats(eventtime) @@ -155,9 +206,9 @@ class PrinterExtruder: move.start_pos[3], 0., 0., 1., can_pressure_advance, 0., start_v, cruise_v, accel) + self.last_position = move.end_pos[3] def find_past_position(self, print_time): - mcu_pos = self.stepper.get_past_mcu_position(print_time) - return self.stepper.mcu_to_commanded_position(mcu_pos) + return self.extruder_stepper.find_past_position(print_time) def cmd_M104(self, gcmd, wait=False): # Set Extruder Temperature temp = gcmd.get_float('S', 0.) @@ -178,35 +229,6 @@ class PrinterExtruder: def cmd_M109(self, gcmd): # Set Extruder Temperature and Wait self.cmd_M104(gcmd, wait=True) - cmd_SET_PRESSURE_ADVANCE_help = "Set pressure advance parameters" - def cmd_default_SET_PRESSURE_ADVANCE(self, gcmd): - extruder = self.printer.lookup_object('toolhead').get_extruder() - extruder.cmd_SET_PRESSURE_ADVANCE(gcmd) - def cmd_SET_PRESSURE_ADVANCE(self, gcmd): - pressure_advance = gcmd.get_float('ADVANCE', self.pressure_advance, - minval=0.) - smooth_time = gcmd.get_float('SMOOTH_TIME', - self.pressure_advance_smooth_time, - minval=0., maxval=.200) - self._set_pressure_advance(pressure_advance, smooth_time) - msg = ("pressure_advance: %.6f\n" - "pressure_advance_smooth_time: %.6f" - % (pressure_advance, smooth_time)) - self.printer.set_rollover_info(self.name, "%s: %s" % (self.name, msg)) - gcmd.respond_info(msg, log=False) - cmd_SET_E_STEP_DISTANCE_help = "Set extruder step distance" - def cmd_SET_E_STEP_DISTANCE(self, gcmd): - toolhead = self.printer.lookup_object('toolhead') - dist = gcmd.get_float('DISTANCE', None, above=0.) - if dist is None: - step_dist = self.stepper.get_step_dist() - gcmd.respond_info("Extruder '%s' step distance is %0.6f" - % (self.name, step_dist)) - return - toolhead.flush_step_generation() - self.stepper.set_step_dist(dist) - gcmd.respond_info("Extruder '%s' step distance set to %0.6f" - % (self.name, dist)) cmd_ACTIVATE_EXTRUDER_help = "Change the active extruder" def cmd_ACTIVATE_EXTRUDER(self, gcmd): toolhead = self.printer.lookup_object('toolhead') @@ -215,7 +237,7 @@ class PrinterExtruder: return gcmd.respond_info("Activating extruder %s" % (self.name,)) toolhead.flush_step_generation() - toolhead.set_extruder(self, self.stepper.get_commanded_position()) + toolhead.set_extruder(self, self.last_position) self.printer.send_event("extruder:activate_extruder") # Dummy extruder class used when a printer has no extruder at all