klippy: Eliminate high-level build_config phase

Now that the mcu objects can be created prior to connecting to the
mcu, it is no longer necessary to separate the init and build_config
phases in the high-level code.  Move the mcu objection creation from
the build_config phase to the init phase and eliminate the
build_config phase.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2017-03-12 22:43:05 -04:00
parent 92649332ce
commit d21b9280f0
9 changed files with 47 additions and 81 deletions

View File

@ -21,9 +21,6 @@ class CartKinematics:
self.steppers[0].set_max_jerk(max_xy_halt_velocity, max_accel) self.steppers[0].set_max_jerk(max_xy_halt_velocity, max_accel)
self.steppers[1].set_max_jerk(max_xy_halt_velocity, max_accel) self.steppers[1].set_max_jerk(max_xy_halt_velocity, max_accel)
self.steppers[2].set_max_jerk(0., self.max_z_accel) self.steppers[2].set_max_jerk(0., self.max_z_accel)
def build_config(self):
for stepper in self.steppers:
stepper.build_config()
def set_position(self, newpos): def set_position(self, newpos):
for i in StepList: for i in StepList:
s = self.steppers[i] s = self.steppers[i]

View File

@ -50,6 +50,7 @@ class DeltaKinematics:
"Delta max build radius %.2fmm (moves slowed past %.2fmm and %.2fmm)" "Delta max build radius %.2fmm (moves slowed past %.2fmm and %.2fmm)"
% (math.sqrt(self.max_xy2), math.sqrt(self.slow_xy2), % (math.sqrt(self.max_xy2), math.sqrt(self.slow_xy2),
math.sqrt(self.very_slow_xy2))) math.sqrt(self.very_slow_xy2)))
self.set_position([0., 0., 0.])
def set_max_jerk(self, max_xy_halt_velocity, max_velocity, max_accel): def set_max_jerk(self, max_xy_halt_velocity, max_velocity, max_accel):
self.max_velocity = max_velocity self.max_velocity = max_velocity
max_z_velocity = self.config.getfloat('max_z_velocity', max_velocity) max_z_velocity = self.config.getfloat('max_z_velocity', max_velocity)
@ -57,10 +58,6 @@ class DeltaKinematics:
self.max_accel = max_accel self.max_accel = max_accel
for stepper in self.steppers: for stepper in self.steppers:
stepper.set_max_jerk(max_xy_halt_velocity, max_accel) stepper.set_max_jerk(max_xy_halt_velocity, max_accel)
def build_config(self):
for stepper in self.steppers:
stepper.build_config()
self.set_position([0., 0., 0.])
def _cartesian_to_actuator(self, coord): def _cartesian_to_actuator(self, coord):
return [int((math.sqrt(self.arm_length2 return [int((math.sqrt(self.arm_length2
- (self.towers[i][0] - coord[0])**2 - (self.towers[i][0] - coord[0])**2

View File

@ -33,10 +33,7 @@ class PrinterExtruder:
'max_extrude_only_velocity', max_velocity * self.max_extrude_ratio) 'max_extrude_only_velocity', max_velocity * self.max_extrude_ratio)
self.max_e_accel = self.config.getfloat( self.max_e_accel = self.config.getfloat(
'max_extrude_only_accel', max_accel * self.max_extrude_ratio) 'max_extrude_only_accel', max_accel * self.max_extrude_ratio)
def build_config(self):
self.heater.build_config()
self.stepper.set_max_jerk(9999999.9, 9999999.9) self.stepper.set_max_jerk(9999999.9, 9999999.9)
self.stepper.build_config()
def motor_off(self, move_time): def motor_off(self, move_time):
self.stepper.motor_enable(move_time, 0) self.stepper.motor_enable(move_time, 0)
self.need_motor_enable = True self.need_motor_enable = True

View File

@ -9,17 +9,12 @@ PWM_CYCLE_TIME = 0.010
class PrinterFan: class PrinterFan:
def __init__(self, printer, config): def __init__(self, printer, config):
self.printer = printer
self.config = config
self.mcu_fan = None
self.last_fan_value = 0. self.last_fan_value = 0.
self.last_fan_time = 0. self.last_fan_time = 0.
self.kick_start_time = config.getfloat('kick_start_time', 0.1) self.kick_start_time = config.getfloat('kick_start_time', 0.1)
def build_config(self): pin = config.get('pin')
pin = self.config.get('pin') hard_pwm = config.getint('hard_pwm', 0)
hard_pwm = self.config.getint('hard_pwm', 0) self.mcu_fan = printer.mcu.create_pwm(pin, PWM_CYCLE_TIME, hard_pwm, 0.)
self.mcu_fan = self.printer.mcu.create_pwm(
pin, PWM_CYCLE_TIME, hard_pwm, 0.)
# External commands # External commands
def set_speed(self, print_time, value): def set_speed(self, print_time, value):
value = max(0., min(1., value)) value = max(0., min(1., value))

View File

@ -28,44 +28,39 @@ class error(Exception):
class PrinterHeater: class PrinterHeater:
error = error error = error
def __init__(self, printer, config): def __init__(self, printer, config):
self.printer = printer self.name = config.section
self.config = config
self.mcu_pwm = self.mcu_adc = None
self.thermistor_c = config.getchoice('thermistor_type', Thermistors) self.thermistor_c = config.getchoice('thermistor_type', Thermistors)
self.pullup_r = config.getfloat('pullup_resistor', 4700.) self.pullup_r = config.getfloat('pullup_resistor', 4700.)
self.min_extrude_temp = config.getfloat('min_extrude_temp', 170.) self.min_extrude_temp = config.getfloat('min_extrude_temp', 170.)
self.min_temp = self.config.getfloat('min_temp') self.min_temp = config.getfloat('min_temp')
self.max_temp = self.config.getfloat('max_temp') self.max_temp = config.getfloat('max_temp')
self.max_power = max(0., min(1., self.config.getfloat('max_power', 1.))) self.max_power = max(0., min(1., config.getfloat('max_power', 1.)))
self.can_extrude = (self.min_extrude_temp <= 0.) self.can_extrude = (self.min_extrude_temp <= 0.
or printer.mcu.is_fileoutput())
self.lock = threading.Lock() self.lock = threading.Lock()
self.last_temp = 0. self.last_temp = 0.
self.last_temp_time = 0. self.last_temp_time = 0.
self.target_temp = 0. self.target_temp = 0.
self.control = None
# pwm caching
self.next_pwm_time = 0.
self.last_pwm_value = 0
def build_config(self):
algos = {'watermark': ControlBangBang, 'pid': ControlPID} algos = {'watermark': ControlBangBang, 'pid': ControlPID}
algo = self.config.getchoice('control', algos) algo = config.getchoice('control', algos)
heater_pin = self.config.get('heater_pin') heater_pin = config.get('heater_pin')
thermistor_pin = self.config.get('thermistor_pin') thermistor_pin = config.get('thermistor_pin')
if algo is ControlBangBang and self.max_power == 1.: if algo is ControlBangBang and self.max_power == 1.:
self.mcu_pwm = self.printer.mcu.create_digital_out( self.mcu_pwm = printer.mcu.create_digital_out(
heater_pin, MAX_HEAT_TIME) heater_pin, MAX_HEAT_TIME)
else: else:
self.mcu_pwm = self.printer.mcu.create_pwm( self.mcu_pwm = printer.mcu.create_pwm(
heater_pin, PWM_CYCLE_TIME, 0, MAX_HEAT_TIME) heater_pin, PWM_CYCLE_TIME, 0, MAX_HEAT_TIME)
self.mcu_adc = self.printer.mcu.create_adc(thermistor_pin) self.mcu_adc = printer.mcu.create_adc(thermistor_pin)
min_adc = self.calc_adc(self.max_temp) min_adc = self.calc_adc(self.max_temp)
max_adc = self.calc_adc(self.min_temp) max_adc = self.calc_adc(self.min_temp)
self.mcu_adc.set_minmax( self.mcu_adc.set_minmax(
SAMPLE_TIME, SAMPLE_COUNT, minval=min_adc, maxval=max_adc) SAMPLE_TIME, SAMPLE_COUNT, minval=min_adc, maxval=max_adc)
self.mcu_adc.set_adc_callback(REPORT_TIME, self.adc_callback) self.mcu_adc.set_adc_callback(REPORT_TIME, self.adc_callback)
self.control = algo(self, self.config) self.control = algo(self, config)
if self.printer.mcu.is_fileoutput(): # pwm caching
self.can_extrude = True self.next_pwm_time = 0.
self.last_pwm_value = 0
def set_pwm(self, read_time, value): def set_pwm(self, read_time, value):
if value: if value:
if self.target_temp <= 0.: if self.target_temp <= 0.:
@ -80,7 +75,7 @@ class PrinterHeater:
self.next_pwm_time = pwm_time + 0.75 * MAX_HEAT_TIME self.next_pwm_time = pwm_time + 0.75 * MAX_HEAT_TIME
self.last_pwm_value = value self.last_pwm_value = value
logging.debug("%s: pwm=%.3f@%.3f (from %.3f@%.3f [%.3f])" % ( logging.debug("%s: pwm=%.3f@%.3f (from %.3f@%.3f [%.3f])" % (
self.config.section, value, pwm_time, self.name, value, pwm_time,
self.last_temp, self.last_temp_time, self.target_temp)) self.last_temp, self.last_temp_time, self.target_temp))
self.mcu_pwm.set_pwm(pwm_time, value) self.mcu_pwm.set_pwm(pwm_time, value)
# Temperature calculation # Temperature calculation

View File

@ -138,22 +138,20 @@ class Printer:
if self.debugoutput is None: if self.debugoutput is None:
ConfigLogger(self.fileconfig) ConfigLogger(self.fileconfig)
self.mcu = mcu.MCU(self, ConfigWrapper(self, 'mcu')) self.mcu = mcu.MCU(self, ConfigWrapper(self, 'mcu'))
if self.fileconfig.has_section('fan'): if self.debugoutput is not None:
self.objects['fan'] = fan.PrinterFan( self.mcu.connect_file(self.debugoutput, self.dictionary)
self, ConfigWrapper(self, 'fan'))
if self.fileconfig.has_section('extruder'): if self.fileconfig.has_section('extruder'):
self.objects['extruder'] = extruder.PrinterExtruder( self.objects['extruder'] = extruder.PrinterExtruder(
self, ConfigWrapper(self, 'extruder')) self, ConfigWrapper(self, 'extruder'))
if self.fileconfig.has_section('fan'):
self.objects['fan'] = fan.PrinterFan(
self, ConfigWrapper(self, 'fan'))
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'))
self.objects['toolhead'] = toolhead.ToolHead( self.objects['toolhead'] = toolhead.ToolHead(
self, ConfigWrapper(self, 'printer')) self, ConfigWrapper(self, 'printer'))
def build_config(self): # Validate that there are no undefined parameters in the config file
for oname in sorted(self.objects.keys()):
self.objects[oname].build_config()
self.mcu.build_config()
def validate_config(self):
valid_sections = dict([(s, 1) for s, o in self.all_config_options]) valid_sections = dict([(s, 1) for s, o in self.all_config_options])
for section in self.fileconfig.sections(): for section in self.fileconfig.sections():
section = section.lower() section = section.lower()
@ -171,11 +169,7 @@ class Printer:
self.load_config() self.load_config()
if self.debugoutput is None: if self.debugoutput is None:
self.reactor.update_timer(self.stats_timer, self.reactor.NOW) self.reactor.update_timer(self.stats_timer, self.reactor.NOW)
else:
self.mcu.connect_file(self.debugoutput, self.dictionary)
self.mcu.connect() self.mcu.connect()
self.build_config()
self.validate_config()
self.gcode.set_printer_ready(True) self.gcode.set_printer_ready(True)
self.state_message = message_ready self.state_message = message_ready
except ConfigParser.Error, e: except ConfigParser.Error, e:

View File

@ -385,6 +385,7 @@ class MCU:
self._config_crc = None self._config_crc = None
self._init_callbacks = [] self._init_callbacks = []
self._pin_map = config.get('pin_map', None) self._pin_map = config.get('pin_map', None)
self._custom = config.get('custom', '')
# Move command queuing # Move command queuing
ffi_main, self.ffi_lib = chelper.get_ffi() ffi_main, self.ffi_lib = chelper.get_ffi()
self._max_stepper_error = config.getfloat('max_stepper_error', 0.000025) self._max_stepper_error = config.getfloat('max_stepper_error', 0.000025)
@ -427,6 +428,8 @@ class MCU:
self.register_msg(self.handle_shutdown, 'shutdown') self.register_msg(self.handle_shutdown, 'shutdown')
self.register_msg(self.handle_shutdown, 'is_shutdown') self.register_msg(self.handle_shutdown, 'is_shutdown')
self.register_msg(self.handle_mcu_stats, 'stats') self.register_msg(self.handle_mcu_stats, 'stats')
self._build_config()
self._send_config()
def connect_file(self, debugoutput, dictionary, pace=False): def connect_file(self, debugoutput, dictionary, pace=False):
self._is_fileoutput = True self._is_fileoutput = True
self.serial.connect_file(debugoutput, dictionary) self.serial.connect_file(debugoutput, dictionary)
@ -468,8 +471,7 @@ class MCU:
return self._is_fileoutput return self._is_fileoutput
# Configuration phase # Configuration phase
def _add_custom(self): def _add_custom(self):
data = self._config.get('custom', '') for line in self._custom.split('\n'):
for line in data.split('\n'):
line = line.strip() line = line.strip()
cpos = line.find('#') cpos = line.find('#')
if cpos >= 0: if cpos >= 0:
@ -477,7 +479,7 @@ class MCU:
if not line: if not line:
continue continue
self.add_config_cmd(line) self.add_config_cmd(line)
def build_config(self): def _build_config(self):
# Build config commands # Build config commands
for oid in self._oids: for oid in self._oids:
oid.build_config() oid.build_config()
@ -501,8 +503,6 @@ class MCU:
# Calculate config CRC # Calculate config CRC
self._config_crc = zlib.crc32('\n'.join(self._config_cmds)) & 0xffffffff self._config_crc = zlib.crc32('\n'.join(self._config_cmds)) & 0xffffffff
self.add_config_cmd("finalize_config crc=%d" % (self._config_crc,)) self.add_config_cmd("finalize_config crc=%d" % (self._config_crc,))
self._send_config()
def _send_config(self): def _send_config(self):
msg = self.create_command("get_config") msg = self.create_command("get_config")
if self._is_fileoutput: if self._is_fileoutput:

View File

@ -8,10 +8,7 @@ import homing
class PrinterStepper: class PrinterStepper:
def __init__(self, printer, config, name): def __init__(self, printer, config, name):
self.printer = printer
self.config = config
self.name = name self.name = name
self.mcu_stepper = self.mcu_enable = self.mcu_endstop = None
self.step_dist = config.getfloat('step_distance') self.step_dist = config.getfloat('step_distance')
self.inv_step_dist = 1. / self.step_dist self.inv_step_dist = 1. / self.step_dist
@ -36,32 +33,29 @@ class PrinterStepper:
endstop_accuracy * self.inv_step_dist)) endstop_accuracy * self.inv_step_dist))
if self.homing_endstop_accuracy >= self.homing_stepper_phases/2: if self.homing_endstop_accuracy >= self.homing_stepper_phases/2:
logging.info("Endstop for %s is not accurate enough for stepper" logging.info("Endstop for %s is not accurate enough for stepper"
" phase adjustment" % (self.config.section,)) " phase adjustment" % (name,))
self.homing_stepper_phases = None self.homing_stepper_phases = None
self.position_min = self.position_endstop = self.position_max = None self.position_min = self.position_endstop = self.position_max = None
if config.get('endstop_pin', None) is not None: endstop_pin = config.get('endstop_pin', None)
step_pin = config.get('step_pin')
dir_pin = config.get('dir_pin')
mcu = printer.mcu
self.mcu_stepper = mcu.create_stepper(step_pin, dir_pin)
enable_pin = config.get('enable_pin', None)
if enable_pin is not None:
self.mcu_enable = mcu.create_digital_out(enable_pin, 0)
if endstop_pin is not None:
self.mcu_endstop = mcu.create_endstop(endstop_pin, self.mcu_stepper)
self.position_min = config.getfloat('position_min', 0.) self.position_min = config.getfloat('position_min', 0.)
self.position_endstop = config.getfloat('position_endstop') self.position_endstop = config.getfloat('position_endstop')
self.position_max = config.getfloat('position_max', 0.) self.position_max = config.getfloat('position_max', 0.)
self.need_motor_enable = True self.need_motor_enable = True
def set_max_jerk(self, max_halt_velocity, max_accel): def set_max_jerk(self, max_halt_velocity, max_accel):
jc = max_halt_velocity / max_accel jc = max_halt_velocity / max_accel
inv_max_step_accel = self.step_dist / max_accel inv_max_step_accel = self.step_dist / max_accel
self.min_stop_interval = (math.sqrt(3.*inv_max_step_accel + jc**2) min_stop_interval = (math.sqrt(3.*inv_max_step_accel + jc**2)
- math.sqrt(inv_max_step_accel + jc**2)) - math.sqrt(inv_max_step_accel + jc**2))
def build_config(self): self.mcu_stepper.set_min_stop_interval(min_stop_interval)
step_pin = self.config.get('step_pin')
dir_pin = self.config.get('dir_pin')
mcu = self.printer.mcu
self.mcu_stepper = mcu.create_stepper(step_pin, dir_pin)
self.mcu_stepper.set_min_stop_interval(self.min_stop_interval)
enable_pin = self.config.get('enable_pin', None)
if enable_pin is not None:
self.mcu_enable = mcu.create_digital_out(enable_pin, 0)
endstop_pin = self.config.get('endstop_pin', None)
if endstop_pin is not None:
self.mcu_endstop = mcu.create_endstop(endstop_pin, self.mcu_stepper)
def motor_enable(self, move_time, enable=0): def motor_enable(self, move_time, enable=0):
if enable and self.need_motor_enable: if enable and self.need_motor_enable:
mcu_time = self.mcu_stepper.print_to_mcu_time(move_time) mcu_time = self.mcu_stepper.print_to_mcu_time(move_time)
@ -85,8 +79,7 @@ class PrinterStepper:
pos = self.mcu_stepper.get_mcu_position() pos = self.mcu_stepper.get_mcu_position()
pos %= self.homing_stepper_phases pos %= self.homing_stepper_phases
if self.homing_endstop_phase is None: if self.homing_endstop_phase is None:
logging.info("Setting %s endstop phase to %d" % ( logging.info("Setting %s endstop phase to %d" % (self.name, pos))
self.config.section, pos))
self.homing_endstop_phase = pos self.homing_endstop_phase = pos
return 0 return 0
delta = (pos - self.homing_endstop_phase) % self.homing_stepper_phases delta = (pos - self.homing_endstop_phase) % self.homing_stepper_phases

View File

@ -210,13 +210,11 @@ class ToolHead:
self.motor_off_time = config.getfloat('motor_off_time', 60.000) self.motor_off_time = config.getfloat('motor_off_time', 60.000)
self.motor_off_timer = self.reactor.register_timer( self.motor_off_timer = self.reactor.register_timer(
self._motor_off_handler) self._motor_off_handler)
def build_config(self):
# Determine the maximum velocity a cartesian axis could have # Determine the maximum velocity a cartesian axis could have
# before cornering. The 8. was determined experimentally. # before cornering. The 8. was determined experimentally.
xy_halt = math.sqrt(8. * self.junction_deviation * self.max_accel) 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.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) self.extruder.set_max_jerk(xy_halt, self.max_speed, self.max_accel)
self.kin.build_config()
# Print time tracking # Print time tracking
def update_move_time(self, movetime): def update_move_time(self, movetime):
self.print_time += movetime self.print_time += movetime