extruder: Create a new class and python file to track the printer extruder
Create a new python file (extruder.py) to control the extruder heater and stepper motors. This separates the extruder control logic from the cartesian robot code - making it easier to customize both the kinematic control of the robot as well as the extruder. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
4a527a46ce
commit
af99ab1645
|
@ -42,7 +42,7 @@ position_min: 0.1
|
||||||
position_endstop: 0.5
|
position_endstop: 0.5
|
||||||
position_max: 200
|
position_max: 200
|
||||||
|
|
||||||
[stepper_e]
|
[extruder]
|
||||||
# Pins: PC3, PC2
|
# Pins: PC3, PC2
|
||||||
step_pin: ar19
|
step_pin: ar19
|
||||||
dir_pin: ar18
|
dir_pin: ar18
|
||||||
|
@ -50,8 +50,6 @@ enable_pin: ar25
|
||||||
step_distance: .004242
|
step_distance: .004242
|
||||||
max_velocity: 200000
|
max_velocity: 200000
|
||||||
max_accel: 3000
|
max_accel: 3000
|
||||||
|
|
||||||
[heater_nozzle]
|
|
||||||
heater_pin: ar4
|
heater_pin: ar4
|
||||||
thermistor_pin: analog1
|
thermistor_pin: analog1
|
||||||
thermistor_type: EPCOS 100K B57560G104F
|
thermistor_type: EPCOS 100K B57560G104F
|
||||||
|
|
|
@ -77,19 +77,19 @@ position_min: 0.1
|
||||||
position_endstop: 0.5
|
position_endstop: 0.5
|
||||||
position_max: 200
|
position_max: 200
|
||||||
|
|
||||||
# The stepper_e section is used to describe the stepper controlling
|
# The extruder section is used to describe both the stepper
|
||||||
# the printer extruder. It has the same settings as the stepper_x
|
# controlling the printer extruder and the heater parameters for the
|
||||||
# section
|
# nozzle. The stepper configuration has the same settings as the
|
||||||
[stepper_e]
|
# stepper_x section and the heater configuration has the same settings
|
||||||
|
# as the heater_bed section
|
||||||
|
[extruder]
|
||||||
step_pin: ar19
|
step_pin: ar19
|
||||||
dir_pin: ar18
|
dir_pin: ar18
|
||||||
enable_pin: !ar25
|
enable_pin: !ar25
|
||||||
step_distance: .004242
|
step_distance: .004242
|
||||||
max_velocity: 200000
|
max_velocity: 200000
|
||||||
max_accel: 3000
|
max_accel: 3000
|
||||||
|
# The remaining variables describe the extruder heater
|
||||||
# The heater_nozzle section describes the extruder and extruder heater
|
|
||||||
[heater_nozzle]
|
|
||||||
heater_pin: ar4
|
heater_pin: ar4
|
||||||
# PWM output pin controlling the heater
|
# PWM output pin controlling the heater
|
||||||
thermistor_pin: analog1
|
thermistor_pin: analog1
|
||||||
|
@ -118,8 +118,7 @@ max_temp: 210
|
||||||
# this value)
|
# this value)
|
||||||
|
|
||||||
# The heater_bed section describes a heated bed (if present - omit
|
# The heater_bed section describes a heated bed (if present - omit
|
||||||
# section if not present). It has the same settings as the
|
# section if not present).
|
||||||
# heater_nozzle section
|
|
||||||
[heater_bed]
|
[heater_bed]
|
||||||
heater_pin: ar3
|
heater_pin: ar3
|
||||||
thermistor_pin: analog0
|
thermistor_pin: analog0
|
||||||
|
|
|
@ -43,15 +43,13 @@ position_min: 0.1
|
||||||
position_endstop: 0.7
|
position_endstop: 0.7
|
||||||
position_max: 200
|
position_max: 200
|
||||||
|
|
||||||
[stepper_e]
|
[extruder]
|
||||||
step_pin: PC3
|
step_pin: PC3
|
||||||
dir_pin: !PL6
|
dir_pin: !PL6
|
||||||
enable_pin: !PA4
|
enable_pin: !PA4
|
||||||
step_distance: .004242
|
step_distance: .004242
|
||||||
max_velocity: 200000
|
max_velocity: 200000
|
||||||
max_accel: 3000
|
max_accel: 3000
|
||||||
|
|
||||||
[heater_nozzle]
|
|
||||||
heater_pin: PH6
|
heater_pin: PH6
|
||||||
thermistor_pin: PF0
|
thermistor_pin: PF0
|
||||||
thermistor_type: EPCOS 100K B57560G104F
|
thermistor_type: EPCOS 100K B57560G104F
|
||||||
|
|
|
@ -6,14 +6,14 @@
|
||||||
import logging
|
import logging
|
||||||
import stepper, homing
|
import stepper, homing
|
||||||
|
|
||||||
StepList = (0, 1, 2, 3)
|
StepList = (0, 1, 2)
|
||||||
|
|
||||||
class CartKinematics:
|
class CartKinematics:
|
||||||
def __init__(self, printer, config):
|
def __init__(self, printer, config):
|
||||||
steppers = ['stepper_x', 'stepper_y', 'stepper_z', 'stepper_e']
|
steppers = ['stepper_x', 'stepper_y', 'stepper_z']
|
||||||
self.steppers = [stepper.PrinterStepper(printer, config.getsection(n))
|
self.steppers = [stepper.PrinterStepper(printer, config.getsection(n))
|
||||||
for n in steppers]
|
for n in steppers]
|
||||||
self.stepper_pos = [0, 0, 0, 0]
|
self.stepper_pos = [0, 0, 0]
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
for stepper in self.steppers:
|
for stepper in self.steppers:
|
||||||
stepper.build_config()
|
stepper.build_config()
|
||||||
|
@ -31,9 +31,6 @@ class CartKinematics:
|
||||||
accel_factor = min([self.steppers[i].max_accel / abs(axes_d[i])
|
accel_factor = min([self.steppers[i].max_accel / abs(axes_d[i])
|
||||||
for i in StepList if axes_d[i]])
|
for i in StepList if axes_d[i]])
|
||||||
return velocity_factor * move_d, accel_factor * move_d
|
return velocity_factor * move_d, accel_factor * move_d
|
||||||
def get_max_e_speed(self):
|
|
||||||
s = self.steppers[3]
|
|
||||||
return s.max_velocity, s.max_accel
|
|
||||||
def home(self, toolhead, axis):
|
def home(self, toolhead, axis):
|
||||||
# Each axis is homed independently and in order
|
# Each axis is homed independently and in order
|
||||||
homing_state = homing.Homing(toolhead, self.steppers) # XXX
|
homing_state = homing.Homing(toolhead, self.steppers) # XXX
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
# Code for handling printer nozzle extruders
|
||||||
|
#
|
||||||
|
# Copyright (C) 2016 Kevin O'Connor <kevin@koconnor.net>
|
||||||
|
#
|
||||||
|
# This file may be distributed under the terms of the GNU GPLv3 license.
|
||||||
|
import logging
|
||||||
|
import stepper, heater
|
||||||
|
|
||||||
|
class PrinterExtruder:
|
||||||
|
def __init__(self, printer, config):
|
||||||
|
cfg = config.getsection('extruder')
|
||||||
|
self.heater = heater.PrinterHeater(printer, cfg)
|
||||||
|
self.stepper = stepper.PrinterStepper(printer, cfg)
|
||||||
|
self.stepper_pos = 0
|
||||||
|
def build_config(self):
|
||||||
|
self.heater.build_config()
|
||||||
|
self.stepper.build_config()
|
||||||
|
def get_max_speed(self):
|
||||||
|
return self.stepper.max_velocity, self.stepper.max_accel
|
||||||
|
def motor_off(self, move_time):
|
||||||
|
self.stepper.motor_enable(move_time, 0)
|
||||||
|
def move(self, move_time, move):
|
||||||
|
inv_accel = 1. / move.accel
|
||||||
|
new_step_pos = int(move.pos[3]*self.stepper.inv_step_dist + 0.5)
|
||||||
|
steps = new_step_pos - self.stepper_pos
|
||||||
|
if not steps:
|
||||||
|
return
|
||||||
|
self.stepper_pos = new_step_pos
|
||||||
|
sdir = 0
|
||||||
|
if steps < 0:
|
||||||
|
sdir = 1
|
||||||
|
steps = -steps
|
||||||
|
clock_offset, clock_freq, so = self.stepper.prep_move(sdir, move_time)
|
||||||
|
|
||||||
|
step_dist = move.move_d / steps
|
||||||
|
step_offset = 0.5
|
||||||
|
|
||||||
|
# Acceleration steps
|
||||||
|
#t = sqrt(2*pos/accel + (start_v/accel)**2) - start_v/accel
|
||||||
|
accel_clock_offset = move.start_v * inv_accel * clock_freq
|
||||||
|
accel_sqrt_offset = accel_clock_offset**2
|
||||||
|
accel_multiplier = 2.0 * step_dist * inv_accel * clock_freq**2
|
||||||
|
accel_steps = move.accel_r * steps
|
||||||
|
step_offset = so.step_sqrt(
|
||||||
|
accel_steps, step_offset, clock_offset - accel_clock_offset
|
||||||
|
, accel_sqrt_offset, accel_multiplier)
|
||||||
|
clock_offset += move.accel_t * clock_freq
|
||||||
|
# Cruising steps
|
||||||
|
#t = pos/cruise_v
|
||||||
|
cruise_multiplier = step_dist * clock_freq / move.cruise_v
|
||||||
|
cruise_steps = move.cruise_r * steps
|
||||||
|
step_offset = so.step_factor(
|
||||||
|
cruise_steps, step_offset, clock_offset, cruise_multiplier)
|
||||||
|
clock_offset += move.cruise_t * clock_freq
|
||||||
|
# Deceleration steps
|
||||||
|
#t = cruise_v/accel - sqrt((cruise_v/accel)**2 - 2*pos/accel)
|
||||||
|
decel_clock_offset = move.cruise_v * inv_accel * clock_freq
|
||||||
|
decel_sqrt_offset = decel_clock_offset**2
|
||||||
|
decel_steps = move.decel_r * steps
|
||||||
|
so.step_sqrt(
|
||||||
|
decel_steps, step_offset, clock_offset + decel_clock_offset
|
||||||
|
, decel_sqrt_offset, -accel_multiplier)
|
|
@ -35,7 +35,10 @@ class GCodeParser:
|
||||||
self.axis2pos = {'X': 0, 'Y': 1, 'Z': 2, 'E': 3}
|
self.axis2pos = {'X': 0, 'Y': 1, 'Z': 2, 'E': 3}
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
self.toolhead = self.printer.objects['toolhead']
|
self.toolhead = self.printer.objects['toolhead']
|
||||||
self.heater_nozzle = self.printer.objects.get('heater_nozzle')
|
self.heater_nozzle = None
|
||||||
|
extruder = self.printer.objects.get('extruder')
|
||||||
|
if extruder:
|
||||||
|
self.heater_nozzle = extruder.heater
|
||||||
self.heater_bed = self.printer.objects.get('heater_bed')
|
self.heater_bed = self.printer.objects.get('heater_bed')
|
||||||
self.fan = self.printer.objects.get('fan')
|
self.fan = self.printer.objects.get('fan')
|
||||||
self.build_handlers()
|
self.build_handlers()
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#
|
#
|
||||||
# This file may be distributed under the terms of the GNU GPLv3 license.
|
# This file may be distributed under the terms of the GNU GPLv3 license.
|
||||||
import sys, optparse, ConfigParser, logging, time, threading
|
import sys, optparse, ConfigParser, logging, time, threading
|
||||||
import gcode, toolhead, util, mcu, fan, heater, reactor
|
import gcode, toolhead, util, mcu, fan, heater, extruder, reactor
|
||||||
|
|
||||||
class ConfigWrapper:
|
class ConfigWrapper:
|
||||||
def __init__(self, printer, section):
|
def __init__(self, printer, section):
|
||||||
|
@ -52,9 +52,9 @@ class Printer:
|
||||||
if self.fileconfig.has_section('fan'):
|
if self.fileconfig.has_section('fan'):
|
||||||
self.objects['fan'] = fan.PrinterFan(
|
self.objects['fan'] = fan.PrinterFan(
|
||||||
self, ConfigWrapper(self, 'fan'))
|
self, ConfigWrapper(self, 'fan'))
|
||||||
if self.fileconfig.has_section('heater_nozzle'):
|
if self.fileconfig.has_section('extruder'):
|
||||||
self.objects['heater_nozzle'] = heater.PrinterHeater(
|
self.objects['extruder'] = extruder.PrinterExtruder(
|
||||||
self, ConfigWrapper(self, 'heater_nozzle'))
|
self, ConfigWrapper(self, 'extruder'))
|
||||||
if self.fileconfig.has_section('heater_bed'):
|
if self.fileconfig.has_section('heater_bed'):
|
||||||
self.objects['heater_bed'] = heater.PrinterHeater(
|
self.objects['heater_bed'] = heater.PrinterHeater(
|
||||||
self, ConfigWrapper(self, 'heater_bed'))
|
self, ConfigWrapper(self, 'heater_bed'))
|
||||||
|
|
|
@ -61,6 +61,8 @@ class Move:
|
||||||
# Generate step times for the move
|
# Generate step times for the move
|
||||||
next_move_time = self.toolhead.get_next_move_time()
|
next_move_time = self.toolhead.get_next_move_time()
|
||||||
self.toolhead.kin.move(next_move_time, self)
|
self.toolhead.kin.move(next_move_time, self)
|
||||||
|
if self.axes_d[3]:
|
||||||
|
self.toolhead.extruder.move(next_move_time, self)
|
||||||
self.toolhead.update_move_time(accel_t + cruise_t + decel_t)
|
self.toolhead.update_move_time(accel_t + cruise_t + decel_t)
|
||||||
|
|
||||||
# Class to track a list of pending move requests and to facilitate
|
# Class to track a list of pending move requests and to facilitate
|
||||||
|
@ -113,6 +115,7 @@ class ToolHead:
|
||||||
def __init__(self, printer, config):
|
def __init__(self, printer, config):
|
||||||
self.printer = printer
|
self.printer = printer
|
||||||
self.reactor = printer.reactor
|
self.reactor = printer.reactor
|
||||||
|
self.extruder = printer.objects.get('extruder')
|
||||||
self.kin = cartesian.CartKinematics(printer, config)
|
self.kin = cartesian.CartKinematics(printer, config)
|
||||||
self.max_xy_speed, self.max_xy_accel = self.kin.get_max_xy_speed()
|
self.max_xy_speed, self.max_xy_accel = self.kin.get_max_xy_speed()
|
||||||
self.junction_deviation = config.getfloat('junction_deviation', 0.02)
|
self.junction_deviation = config.getfloat('junction_deviation', 0.02)
|
||||||
|
@ -208,7 +211,7 @@ class ToolHead:
|
||||||
move.process(0., 0.)
|
move.process(0., 0.)
|
||||||
def _move_only_e(self, newpos, axes_d, speed):
|
def _move_only_e(self, newpos, axes_d, speed):
|
||||||
self.move_queue.flush()
|
self.move_queue.flush()
|
||||||
kin_speed, kin_accel = self.kin.get_max_e_speed()
|
kin_speed, kin_accel = self.extruder.get_max_speed()
|
||||||
speed = min(speed, self.max_xy_speed, kin_speed)
|
speed = min(speed, self.max_xy_speed, kin_speed)
|
||||||
accel = min(self.max_xy_accel, kin_accel)
|
accel = min(self.max_xy_accel, kin_accel)
|
||||||
move = Move(self, newpos, abs(axes_d[3]), axes_d, speed, accel)
|
move = Move(self, newpos, abs(axes_d[3]), axes_d, speed, accel)
|
||||||
|
@ -238,5 +241,6 @@ class ToolHead:
|
||||||
self.dwell(STALL_TIME)
|
self.dwell(STALL_TIME)
|
||||||
last_move_time = self.get_last_move_time()
|
last_move_time = self.get_last_move_time()
|
||||||
self.kin.motor_off(last_move_time)
|
self.kin.motor_off(last_move_time)
|
||||||
|
self.extruder.motor_off(last_move_time)
|
||||||
self.dwell(STALL_TIME)
|
self.dwell(STALL_TIME)
|
||||||
logging.debug('; Max time of %f' % (last_move_time,))
|
logging.debug('; Max time of %f' % (last_move_time,))
|
||||||
|
|
Loading…
Reference in New Issue