extruder: Add support for instantaneous corner velocity

Add mechanism to perform look-ahead between moves with different
extrusion ratios.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2019-09-20 19:00:24 -04:00
parent 6d0c55b6c1
commit 5f5896ad71
2 changed files with 16 additions and 22 deletions

View File

@ -111,6 +111,9 @@ filament_diameter: 3.500
# If a move requests an extrusion rate that would exceed this value # If a move requests an extrusion rate that would exceed this value
# it will cause an error to be returned. The default is: 4.0 * # it will cause an error to be returned. The default is: 4.0 *
# nozzle_diameter^2 # nozzle_diameter^2
#instantaneous_corner_velocity: 1.000
# The maximum instantaneous velocity change (in mm/s) of the
# extruder during the junction of two moves. The default is 1mm/s.
#max_extrude_only_distance: 50.0 #max_extrude_only_distance: 50.0
# Maximum length (in mm of raw filament) that a retraction or # Maximum length (in mm of raw filament) that a retraction or
# extrude-only move may have. If a retraction or extrude-only move # extrude-only move may have. If a retraction or extrude-only move

View File

@ -6,8 +6,6 @@
import math, logging import math, logging
import stepper, homing, chelper import stepper, homing, chelper
EXTRUDE_DIFF_IGNORE = 1.02
class PrinterExtruder: class PrinterExtruder:
def __init__(self, config, extruder_num): def __init__(self, config, extruder_num):
self.printer = config.get_printer() self.printer = config.get_printer()
@ -41,6 +39,8 @@ class PrinterExtruder:
self.stepper.set_max_jerk(9999999.9, 9999999.9) self.stepper.set_max_jerk(9999999.9, 9999999.9)
self.max_e_dist = config.getfloat( self.max_e_dist = config.getfloat(
'max_extrude_only_distance', 50., minval=0.) 'max_extrude_only_distance', 50., minval=0.)
self.instant_corner_v = config.getfloat(
'instantaneous_corner_velocity', 1., minval=0.)
gcode_macro = self.printer.try_load_module(config, 'gcode_macro') gcode_macro = self.printer.try_load_module(config, 'gcode_macro')
self.activate_gcode = gcode_macro.load_template( self.activate_gcode = gcode_macro.load_template(
config, 'activate_gcode', '') config, 'activate_gcode', '')
@ -104,45 +104,36 @@ class PrinterExtruder:
def stats(self, eventtime): def stats(self, eventtime):
return self.heater.stats(eventtime) return self.heater.stats(eventtime)
def check_move(self, move): def check_move(self, move):
move.extrude_r = move.axes_r[3] axis_r = move.axes_r[3]
if not self.heater.can_extrude: if not self.heater.can_extrude:
raise homing.EndstopError( raise homing.EndstopError(
"Extrude below minimum temp\n" "Extrude below minimum temp\n"
"See the 'min_extrude_temp' config option for details") "See the 'min_extrude_temp' config option for details")
if (not move.axes_d[0] and not move.axes_d[1]) or move.extrude_r < 0.: if (not move.axes_d[0] and not move.axes_d[1]) or axis_r < 0.:
# Extrude only move (or retraction move) - limit accel and velocity # Extrude only move (or retraction move) - limit accel and velocity
if abs(move.axes_d[3]) > self.max_e_dist: if abs(move.axes_d[3]) > self.max_e_dist:
raise homing.EndstopError( raise homing.EndstopError(
"Extrude only move too long (%.3fmm vs %.3fmm)\n" "Extrude only move too long (%.3fmm vs %.3fmm)\n"
"See the 'max_extrude_only_distance' config" "See the 'max_extrude_only_distance' config"
" option for details" % (move.axes_d[3], self.max_e_dist)) " option for details" % (move.axes_d[3], self.max_e_dist))
inv_extrude_r = 1. / abs(move.extrude_r) inv_extrude_r = 1. / abs(axis_r)
move.limit_speed(self.max_e_velocity * inv_extrude_r move.limit_speed(self.max_e_velocity * inv_extrude_r,
, self.max_e_accel * inv_extrude_r) self.max_e_accel * inv_extrude_r)
elif move.extrude_r > self.max_extrude_ratio: elif axis_r > self.max_extrude_ratio:
if move.axes_d[3] <= self.nozzle_diameter * self.max_extrude_ratio: if move.axes_d[3] <= self.nozzle_diameter * self.max_extrude_ratio:
# Permit extrusion if amount extruded is tiny # Permit extrusion if amount extruded is tiny
return return
area = move.axes_r[3] * self.filament_area area = axis_r * self.filament_area
logging.debug("Overextrude: %s vs %s (area=%.3f dist=%.3f)", logging.debug("Overextrude: %s vs %s (area=%.3f dist=%.3f)",
move.extrude_r, self.max_extrude_ratio, axis_r, self.max_extrude_ratio, area, move.move_d)
area, move.move_d)
raise homing.EndstopError( raise homing.EndstopError(
"Move exceeds maximum extrusion (%.3fmm^2 vs %.3fmm^2)\n" "Move exceeds maximum extrusion (%.3fmm^2 vs %.3fmm^2)\n"
"See the 'max_extrude_cross_section' config option for details" "See the 'max_extrude_cross_section' config option for details"
% (area, self.max_extrude_ratio * self.filament_area)) % (area, self.max_extrude_ratio * self.filament_area))
def calc_junction(self, prev_move, move): def calc_junction(self, prev_move, move):
extrude = move.axes_d[3] diff_r = move.axes_r[3] - prev_move.axes_r[3]
prev_extrude = prev_move.axes_d[3] if diff_r:
if extrude or prev_extrude: return (self.instant_corner_v / abs(diff_r))**2
if not extrude or not prev_extrude:
# Extrude move to non-extrude move - disable lookahead
return 0.
if ((move.extrude_r > prev_move.extrude_r * EXTRUDE_DIFF_IGNORE
or prev_move.extrude_r > move.extrude_r * EXTRUDE_DIFF_IGNORE)
and abs(move.move_d * prev_move.extrude_r - extrude) >= .001):
# Extrude ratio between moves is too different
return 0.
return move.max_cruise_v2 return move.max_cruise_v2
def lookahead(self, moves, flush_count, lazy): def lookahead(self, moves, flush_count, lazy):
return flush_count return flush_count