klippy: Add access methods and avoid peeking into the printer classes
Add get_reactor(), lookup_object(), lookup_module_objects(), and set_rollover_info() to the main Printer class so that callers do not need to peek into the class' members. Similarly, add get_printer() and get_name() methods to the ConfigWrapper class. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
f0a754e496
commit
81013ba5c8
|
@ -1,6 +1,6 @@
|
||||||
# Code to configure miscellaneous chips
|
# Code to configure miscellaneous chips
|
||||||
#
|
#
|
||||||
# Copyright (C) 2017 Kevin O'Connor <kevin@koconnor.net>
|
# Copyright (C) 2017,2018 Kevin O'Connor <kevin@koconnor.net>
|
||||||
#
|
#
|
||||||
# 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 pins, mcu
|
import pins, mcu
|
||||||
|
@ -22,7 +22,7 @@ PIN_MIN_TIME = 0.100
|
||||||
class PrinterPin:
|
class PrinterPin:
|
||||||
def __init__(self, printer, config):
|
def __init__(self, printer, config):
|
||||||
self.printer = printer
|
self.printer = printer
|
||||||
self.is_pwm = 'pwm' in config.section.split()[0]
|
self.is_pwm = 'pwm' in config.get_name().split()[0]
|
||||||
if self.is_pwm:
|
if self.is_pwm:
|
||||||
self.mcu_pin = pins.setup_pin(printer, 'pwm', config.get('pin'))
|
self.mcu_pin = pins.setup_pin(printer, 'pwm', config.get('pin'))
|
||||||
hard_pwm = config.getint('hard_pwm', None, minval=1)
|
hard_pwm = config.getint('hard_pwm', None, minval=1)
|
||||||
|
@ -40,7 +40,7 @@ class PrinterPin:
|
||||||
self.last_value_time = 0.
|
self.last_value_time = 0.
|
||||||
self.last_value = config.getfloat(
|
self.last_value = config.getfloat(
|
||||||
'value', 0., minval=0., maxval=self.scale) / self.scale
|
'value', 0., minval=0., maxval=self.scale) / self.scale
|
||||||
self.is_static = config.section.startswith('static_')
|
self.is_static = config.get_name().startswith('static_')
|
||||||
if self.is_static:
|
if self.is_static:
|
||||||
self.mcu_pin.setup_start_value(
|
self.mcu_pin.setup_start_value(
|
||||||
self.last_value, self.last_value, True)
|
self.last_value, self.last_value, True)
|
||||||
|
@ -48,13 +48,13 @@ class PrinterPin:
|
||||||
shutdown_value = config.getfloat(
|
shutdown_value = config.getfloat(
|
||||||
'shutdown_value', 0., minval=0., maxval=self.scale) / self.scale
|
'shutdown_value', 0., minval=0., maxval=self.scale) / self.scale
|
||||||
self.mcu_pin.setup_start_value(self.last_value, shutdown_value)
|
self.mcu_pin.setup_start_value(self.last_value, shutdown_value)
|
||||||
self.gcode = printer.objects['gcode']
|
self.gcode = printer.lookup_object('gcode')
|
||||||
self.gcode.register_command("SET_PIN", self.cmd_SET_PIN,
|
self.gcode.register_command("SET_PIN", self.cmd_SET_PIN,
|
||||||
desc=self.cmd_SET_PIN_help)
|
desc=self.cmd_SET_PIN_help)
|
||||||
cmd_SET_PIN_help = "Set the value of an output pin"
|
cmd_SET_PIN_help = "Set the value of an output pin"
|
||||||
def cmd_SET_PIN(self, params):
|
def cmd_SET_PIN(self, params):
|
||||||
pin_name = self.gcode.get_str('PIN', params)
|
pin_name = self.gcode.get_str('PIN', params)
|
||||||
pin = self.printer.objects.get('pin ' + pin_name)
|
pin = self.printer.lookup_object('pin ' + pin_name, None)
|
||||||
if pin is not self:
|
if pin is not self:
|
||||||
if pin is None:
|
if pin is None:
|
||||||
raise self.gcode.error("Pin not configured")
|
raise self.gcode.error("Pin not configured")
|
||||||
|
@ -64,7 +64,7 @@ class PrinterPin:
|
||||||
value = self.gcode.get_float('VALUE', params) / self.scale
|
value = self.gcode.get_float('VALUE', params) / self.scale
|
||||||
if value == self.last_value:
|
if value == self.last_value:
|
||||||
return
|
return
|
||||||
print_time = self.printer.objects['toolhead'].get_last_move_time()
|
print_time = self.printer.lookup_object('toolhead').get_last_move_time()
|
||||||
print_time = max(print_time, self.last_value_time + PIN_MIN_TIME)
|
print_time = max(print_time, self.last_value_time + PIN_MIN_TIME)
|
||||||
if self.is_pwm:
|
if self.is_pwm:
|
||||||
if value < 0. or value > 1.:
|
if value < 0. or value > 1.:
|
||||||
|
@ -89,7 +89,7 @@ class PrinterMultiPin:
|
||||||
self.mcu_pins = []
|
self.mcu_pins = []
|
||||||
def setup_pin(self, pin_params):
|
def setup_pin(self, pin_params):
|
||||||
pin_name = pin_params['pin']
|
pin_name = pin_params['pin']
|
||||||
pin = self.printer.objects.get('multi_pin ' + pin_name)
|
pin = self.printer.lookup_object('multi_pin ' + pin_name, None)
|
||||||
if pin is not self:
|
if pin is not self:
|
||||||
if pin is None:
|
if pin is None:
|
||||||
raise pins.error("multi_pin %s not configured" % (pin_name,))
|
raise pins.error("multi_pin %s not configured" % (pin_name,))
|
||||||
|
@ -147,7 +147,7 @@ class PrinterServo:
|
||||||
self.angle_to_width = (self.max_width - self.min_width) / self.max_angle
|
self.angle_to_width = (self.max_width - self.min_width) / self.max_angle
|
||||||
self.width_to_value = 1. / SERVO_SIGNAL_PERIOD
|
self.width_to_value = 1. / SERVO_SIGNAL_PERIOD
|
||||||
self.last_value = self.last_value_time = 0.
|
self.last_value = self.last_value_time = 0.
|
||||||
self.gcode = printer.objects['gcode']
|
self.gcode = printer.lookup_object('gcode')
|
||||||
self.gcode.register_command("SET_SERVO", self.cmd_SET_SERVO,
|
self.gcode.register_command("SET_SERVO", self.cmd_SET_SERVO,
|
||||||
desc=self.cmd_SET_SERVO_help)
|
desc=self.cmd_SET_SERVO_help)
|
||||||
def set_pwm(self, print_time, value):
|
def set_pwm(self, print_time, value):
|
||||||
|
@ -167,12 +167,12 @@ class PrinterServo:
|
||||||
cmd_SET_SERVO_help = "Set servo angle"
|
cmd_SET_SERVO_help = "Set servo angle"
|
||||||
def cmd_SET_SERVO(self, params):
|
def cmd_SET_SERVO(self, params):
|
||||||
servo_name = self.gcode.get_str('SERVO', params)
|
servo_name = self.gcode.get_str('SERVO', params)
|
||||||
servo = self.printer.objects.get('servo ' + servo_name)
|
servo = self.printer.lookup_object('servo ' + servo_name, None)
|
||||||
if servo is not self:
|
if servo is not self:
|
||||||
if servo is None:
|
if servo is None:
|
||||||
raise self.gcode.error("Servo not configured")
|
raise self.gcode.error("Servo not configured")
|
||||||
return servo.cmd_SET_SERVO(params)
|
return servo.cmd_SET_SERVO(params)
|
||||||
print_time = self.printer.objects['toolhead'].get_last_move_time()
|
print_time = self.printer.lookup_object('toolhead').get_last_move_time()
|
||||||
if 'WIDTH' in params:
|
if 'WIDTH' in params:
|
||||||
self.set_pulse_width(print_time,
|
self.set_pulse_width(print_time,
|
||||||
self.gcode.get_float('WIDTH', params))
|
self.gcode.get_float('WIDTH', params))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Code for handling printer nozzle extruders
|
# Code for handling printer nozzle extruders
|
||||||
#
|
#
|
||||||
# Copyright (C) 2016 Kevin O'Connor <kevin@koconnor.net>
|
# Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net>
|
||||||
#
|
#
|
||||||
# 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 math, logging
|
import math, logging
|
||||||
|
@ -24,7 +24,7 @@ class PrinterExtruder:
|
||||||
'max_extrude_cross_section', 4. * self.nozzle_diameter**2
|
'max_extrude_cross_section', 4. * self.nozzle_diameter**2
|
||||||
, above=0.)
|
, above=0.)
|
||||||
self.max_extrude_ratio = max_cross_section / self.filament_area
|
self.max_extrude_ratio = max_cross_section / self.filament_area
|
||||||
toolhead = printer.objects['toolhead']
|
toolhead = printer.lookup_object('toolhead')
|
||||||
max_velocity, max_accel = toolhead.get_max_velocity()
|
max_velocity, max_accel = toolhead.get_max_velocity()
|
||||||
self.max_e_velocity = config.getfloat(
|
self.max_e_velocity = config.getfloat(
|
||||||
'max_extrude_only_velocity', max_velocity * self.max_extrude_ratio
|
'max_extrude_only_velocity', max_velocity * self.max_extrude_ratio
|
||||||
|
@ -248,17 +248,17 @@ def add_printer_objects(printer, config):
|
||||||
def get_printer_extruders(printer):
|
def get_printer_extruders(printer):
|
||||||
out = []
|
out = []
|
||||||
for i in range(99):
|
for i in range(99):
|
||||||
extruder = printer.objects.get('extruder%d' % (i,))
|
extruder = printer.lookup_object('extruder%d' % (i,), None)
|
||||||
if extruder is None:
|
if extruder is None:
|
||||||
break
|
break
|
||||||
out.append(extruder)
|
out.append(extruder)
|
||||||
return out
|
return out
|
||||||
|
|
||||||
def get_printer_heater(printer, name):
|
def get_printer_heater(printer, name):
|
||||||
if name == 'heater_bed' and name in printer.objects:
|
if name == 'heater_bed':
|
||||||
return printer.objects[name]
|
return printer.lookup_object(name)
|
||||||
if name == 'extruder':
|
if name == 'extruder':
|
||||||
name = 'extruder0'
|
name = 'extruder0'
|
||||||
if name.startswith('extruder') and name in printer.objects:
|
if name.startswith('extruder'):
|
||||||
return printer.objects[name].get_heater()
|
return printer.lookup_object(name).get_heater()
|
||||||
raise printer.config_error("Unknown heater '%s'" % (name,))
|
raise printer.config_error("Unknown heater '%s'" % (name,))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Printer fan support
|
# Printer fan support
|
||||||
#
|
#
|
||||||
# Copyright (C) 2016,2017 Kevin O'Connor <kevin@koconnor.net>
|
# Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net>
|
||||||
#
|
#
|
||||||
# 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 extruder, pins
|
import extruder, pins
|
||||||
|
@ -35,7 +35,7 @@ class PrinterFan:
|
||||||
class PrinterHeaterFan:
|
class PrinterHeaterFan:
|
||||||
def __init__(self, printer, config):
|
def __init__(self, printer, config):
|
||||||
self.fan = PrinterFan(printer, config)
|
self.fan = PrinterFan(printer, config)
|
||||||
self.mcu = printer.objects['mcu']
|
self.mcu = printer.lookup_object('mcu')
|
||||||
heater = config.get("heater", "extruder0")
|
heater = config.get("heater", "extruder0")
|
||||||
self.heater = extruder.get_printer_heater(printer, heater)
|
self.heater = extruder.get_printer_heater(printer, heater)
|
||||||
self.heater_temp = config.getfloat("heater_temp", 50.0)
|
self.heater_temp = config.getfloat("heater_temp", 50.0)
|
||||||
|
@ -43,7 +43,8 @@ class PrinterHeaterFan:
|
||||||
self.fan_speed = config.getfloat(
|
self.fan_speed = config.getfloat(
|
||||||
"fan_speed", max_power, minval=0., maxval=max_power)
|
"fan_speed", max_power, minval=0., maxval=max_power)
|
||||||
self.fan.mcu_fan.setup_start_value(0., max_power)
|
self.fan.mcu_fan.setup_start_value(0., max_power)
|
||||||
printer.reactor.register_timer(self.callback, printer.reactor.NOW)
|
reactor = printer.get_reactor()
|
||||||
|
reactor.register_timer(self.callback, reactor.NOW)
|
||||||
def callback(self, eventtime):
|
def callback(self, eventtime):
|
||||||
current_temp, target_temp = self.heater.get_temp(eventtime)
|
current_temp, target_temp = self.heater.get_temp(eventtime)
|
||||||
if not current_temp and not target_temp and not self.fan.last_fan_time:
|
if not current_temp and not target_temp and not self.fan.last_fan_time:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Parse gcode commands
|
# Parse gcode commands
|
||||||
#
|
#
|
||||||
# Copyright (C) 2016,2017 Kevin O'Connor <kevin@koconnor.net>
|
# Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net>
|
||||||
#
|
#
|
||||||
# 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 os, re, logging, collections
|
import os, re, logging, collections
|
||||||
|
@ -17,7 +17,7 @@ class GCodeParser:
|
||||||
self.printer = printer
|
self.printer = printer
|
||||||
self.fd = fd
|
self.fd = fd
|
||||||
# Input handling
|
# Input handling
|
||||||
self.reactor = printer.reactor
|
self.reactor = printer.get_reactor()
|
||||||
self.is_processing_data = False
|
self.is_processing_data = False
|
||||||
self.is_fileinput = not not printer.get_start_args().get("debuginput")
|
self.is_fileinput = not not printer.get_start_args().get("debuginput")
|
||||||
self.fd_handle = None
|
self.fd_handle = None
|
||||||
|
@ -72,14 +72,14 @@ class GCodeParser:
|
||||||
self.is_printer_ready = True
|
self.is_printer_ready = True
|
||||||
self.gcode_handlers = self.ready_gcode_handlers
|
self.gcode_handlers = self.ready_gcode_handlers
|
||||||
# Lookup printer components
|
# Lookup printer components
|
||||||
self.toolhead = self.printer.objects.get('toolhead')
|
self.toolhead = self.printer.lookup_object('toolhead')
|
||||||
extruders = extruder.get_printer_extruders(self.printer)
|
extruders = extruder.get_printer_extruders(self.printer)
|
||||||
if extruders:
|
if extruders:
|
||||||
self.extruder = extruders[0]
|
self.extruder = extruders[0]
|
||||||
self.toolhead.set_extruder(self.extruder)
|
self.toolhead.set_extruder(self.extruder)
|
||||||
self.heaters = [ e.get_heater() for e in extruders ]
|
self.heaters = [ e.get_heater() for e in extruders ]
|
||||||
self.heaters.append(self.printer.objects.get('heater_bed'))
|
self.heaters.append(self.printer.lookup_object('heater_bed', None))
|
||||||
self.fan = self.printer.objects.get('fan')
|
self.fan = self.printer.lookup_object('fan', None)
|
||||||
if self.is_fileinput and self.fd_handle is None:
|
if self.is_fileinput and self.fd_handle is None:
|
||||||
self.fd_handle = self.reactor.register_fd(self.fd, self.process_data)
|
self.fd_handle = self.reactor.register_fd(self.fd, self.process_data)
|
||||||
def reset_last_position(self):
|
def reset_last_position(self):
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Printer heater support
|
# Printer heater support
|
||||||
#
|
#
|
||||||
# Copyright (C) 2016,2017 Kevin O'Connor <kevin@koconnor.net>
|
# Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net>
|
||||||
#
|
#
|
||||||
# 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 math, logging, threading
|
import math, logging, threading
|
||||||
|
@ -106,7 +106,7 @@ class PrinterHeater:
|
||||||
error = error
|
error = error
|
||||||
def __init__(self, printer, config):
|
def __init__(self, printer, config):
|
||||||
self.printer = printer
|
self.printer = printer
|
||||||
self.name = config.section
|
self.name = config.get_name()
|
||||||
sensor_params = config.getchoice('sensor_type', Sensors)
|
sensor_params = config.getchoice('sensor_type', Sensors)
|
||||||
self.sensor = sensor_params['class'](config, sensor_params)
|
self.sensor = sensor_params['class'](config, sensor_params)
|
||||||
self.min_temp = config.getfloat('min_temp', minval=0.)
|
self.min_temp = config.getfloat('min_temp', minval=0.)
|
||||||
|
@ -326,7 +326,7 @@ class ControlAutoTune:
|
||||||
midpoint_pos = sorted(cycle_times)[len(cycle_times)/2][1]
|
midpoint_pos = sorted(cycle_times)[len(cycle_times)/2][1]
|
||||||
Kp, Ki, Kd = self.calc_pid(midpoint_pos)
|
Kp, Ki, Kd = self.calc_pid(midpoint_pos)
|
||||||
logging.info("Autotune: final: Kp=%f Ki=%f Kd=%f", Kp, Ki, Kd)
|
logging.info("Autotune: final: Kp=%f Ki=%f Kd=%f", Kp, Ki, Kd)
|
||||||
gcode = self.heater.printer.objects['gcode']
|
gcode = self.heater.printer.lookup_object('gcode')
|
||||||
gcode.respond_info(
|
gcode.respond_info(
|
||||||
"PID parameters: pid_Kp=%.3f pid_Ki=%.3f pid_Kd=%.3f\n"
|
"PID parameters: pid_Kp=%.3f pid_Ki=%.3f pid_Kd=%.3f\n"
|
||||||
"To use these parameters, update the printer config file with\n"
|
"To use these parameters, update the printer config file with\n"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python2
|
||||||
# Main code for host side printer firmware
|
# Main code for host side printer firmware
|
||||||
#
|
#
|
||||||
# Copyright (C) 2016,2017 Kevin O'Connor <kevin@koconnor.net>
|
# Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net>
|
||||||
#
|
#
|
||||||
# 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
|
||||||
|
@ -52,8 +52,12 @@ class ConfigWrapper:
|
||||||
def __init__(self, printer, section):
|
def __init__(self, printer, section):
|
||||||
self.printer = printer
|
self.printer = printer
|
||||||
self.section = section
|
self.section = section
|
||||||
def get_wrapper(self, parser, option, default
|
def get_printer(self):
|
||||||
, minval=None, maxval=None, above=None, below=None):
|
return self.printer
|
||||||
|
def get_name(self):
|
||||||
|
return self.section
|
||||||
|
def _get_wrapper(self, parser, option, default,
|
||||||
|
minval=None, maxval=None, above=None, below=None):
|
||||||
if (default is not self.sentinel
|
if (default is not self.sentinel
|
||||||
and not self.printer.fileconfig.has_option(self.section, option)):
|
and not self.printer.fileconfig.has_option(self.section, option)):
|
||||||
return default
|
return default
|
||||||
|
@ -84,17 +88,17 @@ class ConfigWrapper:
|
||||||
option, self.section, below))
|
option, self.section, below))
|
||||||
return v
|
return v
|
||||||
def get(self, option, default=sentinel):
|
def get(self, option, default=sentinel):
|
||||||
return self.get_wrapper(self.printer.fileconfig.get, option, default)
|
return self._get_wrapper(self.printer.fileconfig.get, option, default)
|
||||||
def getint(self, option, default=sentinel, minval=None, maxval=None):
|
def getint(self, option, default=sentinel, minval=None, maxval=None):
|
||||||
return self.get_wrapper(
|
return self._get_wrapper(
|
||||||
self.printer.fileconfig.getint, option, default, minval, maxval)
|
self.printer.fileconfig.getint, option, default, minval, maxval)
|
||||||
def getfloat(self, option, default=sentinel
|
def getfloat(self, option, default=sentinel
|
||||||
, minval=None, maxval=None, above=None, below=None):
|
, minval=None, maxval=None, above=None, below=None):
|
||||||
return self.get_wrapper(
|
return self._get_wrapper(
|
||||||
self.printer.fileconfig.getfloat, option, default
|
self.printer.fileconfig.getfloat, option, default
|
||||||
, minval, maxval, above, below)
|
, minval, maxval, above, below)
|
||||||
def getboolean(self, option, default=sentinel):
|
def getboolean(self, option, default=sentinel):
|
||||||
return self.get_wrapper(
|
return self._get_wrapper(
|
||||||
self.printer.fileconfig.getboolean, option, default)
|
self.printer.fileconfig.getboolean, option, default)
|
||||||
def getchoice(self, option, choices, default=sentinel):
|
def getchoice(self, option, choices, default=sentinel):
|
||||||
c = self.get(option, default)
|
c = self.get(option, default)
|
||||||
|
@ -144,6 +148,31 @@ class Printer:
|
||||||
self.mcus = []
|
self.mcus = []
|
||||||
def get_start_args(self):
|
def get_start_args(self):
|
||||||
return self.start_args
|
return self.start_args
|
||||||
|
def get_reactor(self):
|
||||||
|
return self.reactor
|
||||||
|
def get_state_message(self):
|
||||||
|
return self.state_message
|
||||||
|
def add_object(self, name, obj):
|
||||||
|
if obj in self.objects:
|
||||||
|
raise self.config_error(
|
||||||
|
"Printer object '%s' already created" % (name,))
|
||||||
|
self.objects[name] = obj
|
||||||
|
def lookup_object(self, name, default=ConfigWrapper.sentinel):
|
||||||
|
if name in self.objects:
|
||||||
|
return self.objects[name]
|
||||||
|
if default is ConfigWrapper.sentinel:
|
||||||
|
raise self.config_error("Unknown config object '%s'" % (name,))
|
||||||
|
return default
|
||||||
|
def lookup_module_objects(self, module_name):
|
||||||
|
prefix = module_name + ' '
|
||||||
|
objs = [self.objects[n]
|
||||||
|
for n in sorted(self.objects) if n.startswith(prefix)]
|
||||||
|
if module_name in self.objects:
|
||||||
|
return [self.objects[module_name]] + objs
|
||||||
|
return objs
|
||||||
|
def set_rollover_info(self, name, info):
|
||||||
|
if self.bglogger is not None:
|
||||||
|
self.bglogger.set_rollover_info(name, info)
|
||||||
def _stats(self, eventtime, force_output=False):
|
def _stats(self, eventtime, force_output=False):
|
||||||
toolhead = self.objects.get('toolhead')
|
toolhead = self.objects.get('toolhead')
|
||||||
if toolhead is None:
|
if toolhead is None:
|
||||||
|
@ -158,8 +187,6 @@ class Printer:
|
||||||
out.append(m.stats(eventtime))
|
out.append(m.stats(eventtime))
|
||||||
logging.info("Stats %.1f: %s", eventtime, ' '.join(out))
|
logging.info("Stats %.1f: %s", eventtime, ' '.join(out))
|
||||||
return eventtime + 1.
|
return eventtime + 1.
|
||||||
def add_object(self, name, obj):
|
|
||||||
self.objects[name] = obj
|
|
||||||
def _load_config(self):
|
def _load_config(self):
|
||||||
self.fileconfig = ConfigParser.RawConfigParser()
|
self.fileconfig = ConfigParser.RawConfigParser()
|
||||||
config_file = self.start_args['config_file']
|
config_file = self.start_args['config_file']
|
||||||
|
@ -173,7 +200,7 @@ class Printer:
|
||||||
config = ConfigWrapper(self, 'printer')
|
config = ConfigWrapper(self, 'printer')
|
||||||
for m in [pins, mcu, chipmisc, toolhead, extruder, heater, fan]:
|
for m in [pins, mcu, chipmisc, toolhead, extruder, heater, fan]:
|
||||||
m.add_printer_objects(self, config)
|
m.add_printer_objects(self, config)
|
||||||
self.mcus = mcu.get_printer_mcus(self)
|
self.mcus = self.lookup_module_objects('mcu')
|
||||||
# Validate that there are no undefined parameters in the config file
|
# Validate that there are no undefined parameters in the config file
|
||||||
valid_sections = { s: 1 for s, o in self.all_config_options }
|
valid_sections = { s: 1 for s, o in self.all_config_options }
|
||||||
for section in self.fileconfig.sections():
|
for section in self.fileconfig.sections():
|
||||||
|
@ -237,8 +264,6 @@ class Printer:
|
||||||
except:
|
except:
|
||||||
logging.exception("Unhandled exception during post run")
|
logging.exception("Unhandled exception during post run")
|
||||||
return run_result
|
return run_result
|
||||||
def get_state_message(self):
|
|
||||||
return self.state_message
|
|
||||||
def invoke_shutdown(self, msg):
|
def invoke_shutdown(self, msg):
|
||||||
if self.is_shutdown:
|
if self.is_shutdown:
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Interface to Klipper micro-controller code
|
# Interface to Klipper micro-controller code
|
||||||
#
|
#
|
||||||
# Copyright (C) 2016,2017 Kevin O'Connor <kevin@koconnor.net>
|
# Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net>
|
||||||
#
|
#
|
||||||
# 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, os, zlib, logging, math
|
import sys, os, zlib, logging, math
|
||||||
|
@ -409,7 +409,8 @@ class MCU:
|
||||||
def __init__(self, printer, config, clocksync):
|
def __init__(self, printer, config, clocksync):
|
||||||
self._printer = printer
|
self._printer = printer
|
||||||
self._clocksync = clocksync
|
self._clocksync = clocksync
|
||||||
self._name = config.section
|
self._reactor = printer.get_reactor()
|
||||||
|
self._name = config.get_name()
|
||||||
if self._name.startswith('mcu '):
|
if self._name.startswith('mcu '):
|
||||||
self._name = self._name[4:]
|
self._name = self._name[4:]
|
||||||
# Serial port
|
# Serial port
|
||||||
|
@ -419,7 +420,7 @@ class MCU:
|
||||||
or self._serialport.startswith("/tmp/klipper_host_")):
|
or self._serialport.startswith("/tmp/klipper_host_")):
|
||||||
baud = config.getint('baud', 250000, minval=2400)
|
baud = config.getint('baud', 250000, minval=2400)
|
||||||
self._serial = serialhdl.SerialReader(
|
self._serial = serialhdl.SerialReader(
|
||||||
printer.reactor, self._serialport, baud)
|
self._reactor, self._serialport, baud)
|
||||||
# Restarts
|
# Restarts
|
||||||
self._restart_method = 'command'
|
self._restart_method = 'command'
|
||||||
if baud:
|
if baud:
|
||||||
|
@ -430,8 +431,7 @@ class MCU:
|
||||||
self._emergency_stop_cmd = None
|
self._emergency_stop_cmd = None
|
||||||
self._is_shutdown = self._is_timeout = False
|
self._is_shutdown = self._is_timeout = False
|
||||||
self._shutdown_msg = ""
|
self._shutdown_msg = ""
|
||||||
if printer.bglogger is not None:
|
printer.set_rollover_info(self._name, None)
|
||||||
printer.bglogger.set_rollover_info(self._name, None)
|
|
||||||
# Config building
|
# Config building
|
||||||
pins.get_printer_pins(printer).register_chip(self._name, self)
|
pins.get_printer_pins(printer).register_chip(self._name, self)
|
||||||
self._oid_count = 0
|
self._oid_count = 0
|
||||||
|
@ -482,7 +482,7 @@ class MCU:
|
||||||
logging.info("Attempting automated MCU '%s' restart: %s",
|
logging.info("Attempting automated MCU '%s' restart: %s",
|
||||||
self._name, reason)
|
self._name, reason)
|
||||||
self._printer.request_exit('firmware_restart')
|
self._printer.request_exit('firmware_restart')
|
||||||
self._printer.reactor.pause(self._printer.reactor.monotonic() + 2.000)
|
self._reactor.pause(self._reactor.monotonic() + 2.000)
|
||||||
raise error("Attempt MCU '%s' restart failed" % (self._name,))
|
raise error("Attempt MCU '%s' restart failed" % (self._name,))
|
||||||
def _connect_file(self, pace=False):
|
def _connect_file(self, pace=False):
|
||||||
# In a debugging mode. Open debug output file and read data dictionary
|
# In a debugging mode. Open debug output file and read data dictionary
|
||||||
|
@ -566,16 +566,15 @@ class MCU:
|
||||||
raise error("MCU '%s' CRC does not match config" % (self._name,))
|
raise error("MCU '%s' CRC does not match config" % (self._name,))
|
||||||
move_count = config_params['move_count']
|
move_count = config_params['move_count']
|
||||||
logging.info("Configured MCU '%s' (%d moves)", self._name, move_count)
|
logging.info("Configured MCU '%s' (%d moves)", self._name, move_count)
|
||||||
if self._printer.bglogger is not None:
|
msgparser = self._serial.msgparser
|
||||||
msgparser = self._serial.msgparser
|
info = [
|
||||||
info = [
|
"Configured MCU '%s' (%d moves)" % (self._name, move_count),
|
||||||
"Configured MCU '%s' (%d moves)" % (self._name, move_count),
|
"Loaded MCU '%s' %d commands (%s / %s)" % (
|
||||||
"Loaded MCU '%s' %d commands (%s / %s)" % (
|
self._name, len(msgparser.messages_by_id),
|
||||||
self._name, len(msgparser.messages_by_id),
|
msgparser.version, msgparser.build_versions),
|
||||||
msgparser.version, msgparser.build_versions),
|
"MCU '%s' config: %s" % (self._name, " ".join(
|
||||||
"MCU '%s' config: %s" % (self._name, " ".join(
|
["%s=%s" % (k, v) for k, v in msgparser.config.items()]))]
|
||||||
["%s=%s" % (k, v) for k, v in msgparser.config.items()]))]
|
self._printer.set_rollover_info(self._name, "\n".join(info))
|
||||||
self._printer.bglogger.set_rollover_info(self._name, "\n".join(info))
|
|
||||||
self._steppersync = self._ffi_lib.steppersync_alloc(
|
self._steppersync = self._ffi_lib.steppersync_alloc(
|
||||||
self._serial.serialqueue, self._stepqueues, len(self._stepqueues),
|
self._serial.serialqueue, self._stepqueues, len(self._stepqueues),
|
||||||
move_count)
|
move_count)
|
||||||
|
@ -663,18 +662,17 @@ class MCU:
|
||||||
def clock32_to_clock64(self, clock32):
|
def clock32_to_clock64(self, clock32):
|
||||||
return self._clocksync.clock32_to_clock64(clock32)
|
return self._clocksync.clock32_to_clock64(clock32)
|
||||||
def pause(self, waketime):
|
def pause(self, waketime):
|
||||||
return self._printer.reactor.pause(waketime)
|
return self._reactor.pause(waketime)
|
||||||
def monotonic(self):
|
def monotonic(self):
|
||||||
return self._printer.reactor.monotonic()
|
return self._reactor.monotonic()
|
||||||
# Restarts
|
# Restarts
|
||||||
def _restart_arduino(self):
|
def _restart_arduino(self):
|
||||||
logging.info("Attempting MCU '%s' reset", self._name)
|
logging.info("Attempting MCU '%s' reset", self._name)
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
serialhdl.arduino_reset(self._serialport, self._printer.reactor)
|
serialhdl.arduino_reset(self._serialport, self._reactor)
|
||||||
def _restart_via_command(self):
|
def _restart_via_command(self):
|
||||||
reactor = self._printer.reactor
|
|
||||||
if ((self._reset_cmd is None and self._config_reset_cmd is None)
|
if ((self._reset_cmd is None and self._config_reset_cmd is None)
|
||||||
or not self._clocksync.is_active(reactor.monotonic())):
|
or not self._clocksync.is_active(self._reactor.monotonic())):
|
||||||
logging.info("Unable to issue reset command on MCU '%s'", self._name)
|
logging.info("Unable to issue reset command on MCU '%s'", self._name)
|
||||||
return
|
return
|
||||||
if self._reset_cmd is None:
|
if self._reset_cmd is None:
|
||||||
|
@ -682,19 +680,19 @@ class MCU:
|
||||||
logging.info("Attempting MCU '%s' config_reset command", self._name)
|
logging.info("Attempting MCU '%s' config_reset command", self._name)
|
||||||
self._is_shutdown = True
|
self._is_shutdown = True
|
||||||
self.do_shutdown(force=True)
|
self.do_shutdown(force=True)
|
||||||
reactor.pause(reactor.monotonic() + 0.015)
|
self._reactor.pause(self._reactor.monotonic() + 0.015)
|
||||||
self.send(self._config_reset_cmd.encode())
|
self.send(self._config_reset_cmd.encode())
|
||||||
else:
|
else:
|
||||||
# Attempt reset via reset command
|
# Attempt reset via reset command
|
||||||
logging.info("Attempting MCU '%s' reset command", self._name)
|
logging.info("Attempting MCU '%s' reset command", self._name)
|
||||||
self.send(self._reset_cmd.encode())
|
self.send(self._reset_cmd.encode())
|
||||||
reactor.pause(reactor.monotonic() + 0.015)
|
self._reactor.pause(self._reactor.monotonic() + 0.015)
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
def _restart_rpi_usb(self):
|
def _restart_rpi_usb(self):
|
||||||
logging.info("Attempting MCU '%s' reset via rpi usb power", self._name)
|
logging.info("Attempting MCU '%s' reset via rpi usb power", self._name)
|
||||||
self.disconnect()
|
self.disconnect()
|
||||||
chelper.run_hub_ctrl(0)
|
chelper.run_hub_ctrl(0)
|
||||||
self._printer.reactor.pause(self._printer.reactor.monotonic() + 2.)
|
self._reactor.pause(self._reactor.monotonic() + 2.)
|
||||||
chelper.run_hub_ctrl(1)
|
chelper.run_hub_ctrl(1)
|
||||||
def microcontroller_restart(self):
|
def microcontroller_restart(self):
|
||||||
if self._restart_method == 'rpi_usb':
|
if self._restart_method == 'rpi_usb':
|
||||||
|
@ -773,20 +771,14 @@ def error_help(msg):
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
def add_printer_objects(printer, config):
|
def add_printer_objects(printer, config):
|
||||||
mainsync = clocksync.ClockSync(printer.reactor)
|
reactor = printer.get_reactor()
|
||||||
|
mainsync = clocksync.ClockSync(reactor)
|
||||||
printer.add_object('mcu', MCU(printer, config.getsection('mcu'), mainsync))
|
printer.add_object('mcu', MCU(printer, config.getsection('mcu'), mainsync))
|
||||||
for s in config.get_prefix_sections('mcu '):
|
for s in config.get_prefix_sections('mcu '):
|
||||||
printer.add_object(s.section, MCU(
|
printer.add_object(s.section, MCU(
|
||||||
printer, s, clocksync.SecondarySync(printer.reactor, mainsync)))
|
printer, s, clocksync.SecondarySync(reactor, mainsync)))
|
||||||
|
|
||||||
def get_printer_mcus(printer):
|
|
||||||
return [printer.objects[n] for n in sorted(printer.objects)
|
|
||||||
if n.startswith('mcu')]
|
|
||||||
|
|
||||||
def get_printer_mcu(printer, name):
|
def get_printer_mcu(printer, name):
|
||||||
mcu_name = name
|
if name == 'mcu':
|
||||||
if name != 'mcu':
|
return printer.lookup_object(name)
|
||||||
mcu_name = 'mcu ' + name
|
return printer.lookup_object('mcu ' + name)
|
||||||
if mcu_name not in printer.objects:
|
|
||||||
raise printer.config_error("Unknown MCU %s" % (name,))
|
|
||||||
return printer.objects[mcu_name]
|
|
||||||
|
|
|
@ -234,7 +234,7 @@ def add_printer_objects(printer, config):
|
||||||
printer.add_object('pins', PrinterPins())
|
printer.add_object('pins', PrinterPins())
|
||||||
|
|
||||||
def get_printer_pins(printer):
|
def get_printer_pins(printer):
|
||||||
return printer.objects['pins']
|
return printer.lookup_object('pins')
|
||||||
|
|
||||||
def setup_pin(printer, pin_type, pin_desc):
|
def setup_pin(printer, pin_type, pin_desc):
|
||||||
return get_printer_pins(printer).setup_pin(pin_type, pin_desc)
|
return get_printer_pins(printer).setup_pin(pin_type, pin_desc)
|
||||||
|
|
|
@ -36,7 +36,7 @@ def lookup_enable_pin(printer, pin):
|
||||||
# Code storing the definitions for a stepper motor
|
# Code storing the definitions for a stepper motor
|
||||||
class PrinterStepper:
|
class PrinterStepper:
|
||||||
def __init__(self, printer, config):
|
def __init__(self, printer, config):
|
||||||
self.name = config.section
|
self.name = config.get_name()
|
||||||
if self.name.startswith('stepper_'):
|
if self.name.startswith('stepper_'):
|
||||||
self.name = self.name[8:]
|
self.name = self.name[8:]
|
||||||
self.need_motor_enable = True
|
self.need_motor_enable = True
|
||||||
|
@ -101,7 +101,7 @@ class PrinterHomingStepper(PrinterStepper):
|
||||||
else:
|
else:
|
||||||
raise config.error(
|
raise config.error(
|
||||||
"Unable to infer homing_positive_dir in section '%s'" % (
|
"Unable to infer homing_positive_dir in section '%s'" % (
|
||||||
config.section,))
|
config.get_name(),))
|
||||||
# Endstop stepper phase position tracking
|
# Endstop stepper phase position tracking
|
||||||
self.homing_stepper_phases = config.getint(
|
self.homing_stepper_phases = config.getint(
|
||||||
'homing_stepper_phases', None, minval=0)
|
'homing_stepper_phases', None, minval=0)
|
||||||
|
@ -169,9 +169,9 @@ class PrinterMultiStepper(PrinterHomingStepper):
|
||||||
self.extras = []
|
self.extras = []
|
||||||
self.all_step_const = [self.step_const]
|
self.all_step_const = [self.step_const]
|
||||||
for i in range(1, 99):
|
for i in range(1, 99):
|
||||||
if not config.has_section(config.section + str(i)):
|
if not config.has_section(config.get_name() + str(i)):
|
||||||
break
|
break
|
||||||
extraconfig = config.getsection(config.section + str(i))
|
extraconfig = config.getsection(config.get_name() + str(i))
|
||||||
extra = PrinterStepper(printer, extraconfig)
|
extra = PrinterStepper(printer, extraconfig)
|
||||||
self.extras.append(extra)
|
self.extras.append(extra)
|
||||||
self.all_step_const.append(extra.step_const)
|
self.all_step_const.append(extra.step_const)
|
||||||
|
@ -202,6 +202,6 @@ class PrinterMultiStepper(PrinterHomingStepper):
|
||||||
return self.endstops
|
return self.endstops
|
||||||
|
|
||||||
def LookupMultiHomingStepper(printer, config):
|
def LookupMultiHomingStepper(printer, config):
|
||||||
if not config.has_section(config.section + '1'):
|
if not config.has_section(config.get_name() + '1'):
|
||||||
return PrinterHomingStepper(printer, config)
|
return PrinterHomingStepper(printer, config)
|
||||||
return PrinterMultiStepper(printer, config)
|
return PrinterMultiStepper(printer, config)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Code for coordinating events on the printer toolhead
|
# Code for coordinating events on the printer toolhead
|
||||||
#
|
#
|
||||||
# Copyright (C) 2016 Kevin O'Connor <kevin@koconnor.net>
|
# Copyright (C) 2016-2018 Kevin O'Connor <kevin@koconnor.net>
|
||||||
#
|
#
|
||||||
# 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 math, logging
|
import math, logging
|
||||||
|
@ -183,8 +183,8 @@ STALL_TIME = 0.100
|
||||||
class ToolHead:
|
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.get_reactor()
|
||||||
self.all_mcus = mcu.get_printer_mcus(printer)
|
self.all_mcus = printer.lookup_module_objects('mcu')
|
||||||
self.mcu = self.all_mcus[0]
|
self.mcu = self.all_mcus[0]
|
||||||
self.max_velocity = config.getfloat('max_velocity', above=0.)
|
self.max_velocity = config.getfloat('max_velocity', above=0.)
|
||||||
self.max_accel = config.getfloat('max_accel', above=0.)
|
self.max_accel = config.getfloat('max_accel', above=0.)
|
||||||
|
|
Loading…
Reference in New Issue