extruder: Add initial support for multi-extruders
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
136dccbcdf
commit
24b8f4ebc1
|
@ -204,6 +204,15 @@ max_temp: 210
|
|||
# Maximum temperature (mcu will shutdown if temperature is above
|
||||
# this value). This parameter must be provided.
|
||||
|
||||
# In a multi-extruder printer add an additional extruder section for
|
||||
# each additional extruder. The additional extruder sections should be
|
||||
# named "extruder1", "extruder2", "extruder3", and so on. See the
|
||||
# "extruder" section above for a description of available parameters.
|
||||
#[extruder1]
|
||||
#step_pin: ar20
|
||||
#dir_pin: ar21
|
||||
#...
|
||||
|
||||
# The heater_bed section describes a heated bed (if present - omit
|
||||
# section if not present).
|
||||
[heater_bed]
|
||||
|
|
|
@ -40,6 +40,10 @@ class PrinterExtruder:
|
|||
'max_extrude_only_accel', max_accel * self.max_extrude_ratio
|
||||
, above=0.)
|
||||
self.stepper.set_max_jerk(9999999.9, 9999999.9)
|
||||
def get_heater(self):
|
||||
return self.heater
|
||||
def set_active(self, print_time, is_active):
|
||||
return self.extrude_pos
|
||||
def motor_off(self, move_time):
|
||||
self.stepper.motor_enable(move_time, 0)
|
||||
self.need_motor_enable = True
|
||||
|
@ -201,6 +205,8 @@ class PrinterExtruder:
|
|||
class DummyExtruder:
|
||||
def set_max_jerk(self, max_xy_halt_velocity, max_velocity, max_accel):
|
||||
pass
|
||||
def set_active(self, print_time, is_active):
|
||||
return 0.
|
||||
def motor_off(self, move_time):
|
||||
pass
|
||||
def check_move(self, move):
|
||||
|
@ -212,6 +218,22 @@ class DummyExtruder:
|
|||
return flush_count
|
||||
|
||||
def add_printer_objects(printer, config):
|
||||
if config.has_section('extruder'):
|
||||
printer.add_object('extruder', PrinterExtruder(
|
||||
printer, config.getsection('extruder')))
|
||||
for i in range(99):
|
||||
section = 'extruder%d' % (i,)
|
||||
if not config.has_section(section):
|
||||
if not i and config.has_section('extruder'):
|
||||
printer.add_object('extruder0', PrinterExtruder(
|
||||
printer, config.getsection('extruder')))
|
||||
continue
|
||||
break
|
||||
printer.add_object(section, PrinterExtruder(
|
||||
printer, config.getsection(section)))
|
||||
|
||||
def get_printer_extruders(printer):
|
||||
out = []
|
||||
for i in range(99):
|
||||
extruder = printer.objects.get('extruder%d' % (i,))
|
||||
if extruder is None:
|
||||
break
|
||||
out.append(extruder)
|
||||
return out
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#
|
||||
# This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
import os, re, logging, collections
|
||||
import homing
|
||||
import homing, extruder
|
||||
|
||||
# Parse out incoming GCode and find and translate head movements
|
||||
class GCodeParser:
|
||||
|
@ -27,6 +27,7 @@ class GCodeParser:
|
|||
self.is_printer_ready = False
|
||||
self.need_ack = False
|
||||
self.toolhead = self.heater_nozzle = self.heater_bed = self.fan = None
|
||||
self.extruder = None
|
||||
self.speed = 25.0
|
||||
self.absolutecoord = self.absoluteextrude = True
|
||||
self.base_position = [0.0, 0.0, 0.0, 0.0]
|
||||
|
@ -56,9 +57,11 @@ class GCodeParser:
|
|||
# Lookup printer components
|
||||
self.toolhead = self.printer.objects.get('toolhead')
|
||||
self.heater_nozzle = None
|
||||
extruder = self.printer.objects.get('extruder')
|
||||
if extruder:
|
||||
self.heater_nozzle = extruder.heater
|
||||
extruders = extruder.get_printer_extruders(self.printer)
|
||||
if extruders:
|
||||
self.extruder = extruders[0]
|
||||
self.heater_nozzle = self.extruder.get_heater()
|
||||
self.toolhead.set_extruder(self.extruder)
|
||||
self.heater_bed = self.printer.objects.get('heater_bed')
|
||||
self.fan = self.printer.objects.get('fan')
|
||||
if self.is_fileinput and self.fd_handle is None:
|
||||
|
@ -233,7 +236,28 @@ class GCodeParser:
|
|||
if not cmd:
|
||||
logging.debug(params['#original'])
|
||||
return
|
||||
if cmd[0] == 'T' and len(cmd) > 1 and cmd[1].isdigit():
|
||||
# Tn command has to be handled specially
|
||||
self.cmd_Tn(params)
|
||||
return
|
||||
self.respond('echo:Unknown command:"%s"' % (cmd,))
|
||||
def cmd_Tn(self, params):
|
||||
# Select Tool
|
||||
index = self.get_int('T', params)
|
||||
extruders = extruder.get_printer_extruders(self.printer)
|
||||
if self.extruder is None or index < 0 or index >= len(extruders):
|
||||
self.respond_error("Extruder %d not configured" % (index,))
|
||||
return
|
||||
e = extruders[index]
|
||||
if self.extruder is e:
|
||||
return
|
||||
try:
|
||||
self.toolhead.set_extruder(e)
|
||||
except homing.EndstopError, e:
|
||||
self.respond_error(str(e))
|
||||
return
|
||||
self.extruder = e
|
||||
self.last_position = self.toolhead.get_position()
|
||||
all_handlers = [
|
||||
'G1', 'G4', 'G20', 'G28', 'G90', 'G91', 'G92',
|
||||
'M82', 'M83', 'M18', 'M105', 'M104', 'M109', 'M112', 'M114', 'M115',
|
||||
|
|
|
@ -96,8 +96,8 @@ LOOKAHEAD_FLUSH_TIME = 0.250
|
|||
# Class to track a list of pending move requests and to facilitate
|
||||
# "look-ahead" across moves to reduce acceleration between moves.
|
||||
class MoveQueue:
|
||||
def __init__(self, extruder_lookahead):
|
||||
self.extruder_lookahead = extruder_lookahead
|
||||
def __init__(self):
|
||||
self.extruder_lookahead = None
|
||||
self.queue = []
|
||||
self.leftover = 0
|
||||
self.junction_flush = LOOKAHEAD_FLUSH_TIME
|
||||
|
@ -107,6 +107,8 @@ class MoveQueue:
|
|||
self.junction_flush = LOOKAHEAD_FLUSH_TIME
|
||||
def set_flush_time(self, flush_time):
|
||||
self.junction_flush = flush_time
|
||||
def set_extruder(self, extruder):
|
||||
self.extruder_lookahead = extruder.lookahead
|
||||
def flush(self, lazy=False):
|
||||
self.junction_flush = LOOKAHEAD_FLUSH_TIME
|
||||
update_flush_count = lazy
|
||||
|
@ -181,9 +183,7 @@ class ToolHead:
|
|||
def __init__(self, printer, config):
|
||||
self.printer = printer
|
||||
self.reactor = printer.reactor
|
||||
self.extruder = printer.objects.get('extruder')
|
||||
if self.extruder is None:
|
||||
self.extruder = extruder.DummyExtruder()
|
||||
self.extruder = extruder.DummyExtruder()
|
||||
kintypes = {'cartesian': cartesian.CartKinematics,
|
||||
'corexy': corexy.CoreXYKinematics,
|
||||
'delta': delta.DeltaKinematics}
|
||||
|
@ -195,7 +195,8 @@ class ToolHead:
|
|||
, above=0., maxval=self.max_accel)
|
||||
self.junction_deviation = config.getfloat(
|
||||
'junction_deviation', 0.02, above=0.)
|
||||
self.move_queue = MoveQueue(self.extruder.lookahead)
|
||||
self.move_queue = MoveQueue()
|
||||
self.move_queue.set_extruder(self.extruder)
|
||||
self.commanded_pos = [0., 0., 0., 0.]
|
||||
# Print time tracking
|
||||
self.buffer_time_low = config.getfloat(
|
||||
|
@ -223,7 +224,8 @@ class ToolHead:
|
|||
# before cornering. The 8. was determined experimentally.
|
||||
xy_halt = math.sqrt(8. * self.junction_deviation * self.max_accel)
|
||||
self.kin.set_max_jerk(xy_halt, self.max_speed, self.max_accel)
|
||||
self.extruder.set_max_jerk(xy_halt, self.max_speed, self.max_accel)
|
||||
for e in extruder.get_printer_extruders(printer):
|
||||
e.set_max_jerk(xy_halt, self.max_speed, self.max_accel)
|
||||
# Print time tracking
|
||||
def update_move_time(self, movetime):
|
||||
self.print_time += movetime
|
||||
|
@ -363,6 +365,13 @@ class ToolHead:
|
|||
def query_endstops(self):
|
||||
last_move_time = self.get_last_move_time()
|
||||
return self.kin.query_endstops(last_move_time)
|
||||
def set_extruder(self, extruder):
|
||||
last_move_time = self.get_last_move_time()
|
||||
self.extruder.set_active(last_move_time, False)
|
||||
extrude_pos = extruder.set_active(last_move_time, True)
|
||||
self.extruder = extruder
|
||||
self.move_queue.set_extruder(extruder)
|
||||
self.commanded_pos[3] = extrude_pos
|
||||
# Misc commands
|
||||
def stats(self, eventtime):
|
||||
buffer_time = 0.
|
||||
|
|
Loading…
Reference in New Issue