heater: Add PrinterHeaters class that stores all sensors and heaters

Add a PrinterHeaters class that can stores references to available
temperature sensors and stores references to instantiated heaters.

Add a extras/heater_bed.py file and delay instantiation of the
heater_bed object.  This allows the heater.py module to be imported
earlier during the setup phase, and allows the PrinterHeaters class to
be available for registering sensors and heaters.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2018-04-03 17:01:10 -04:00
parent 4eeb43b191
commit aed958eb5c
7 changed files with 67 additions and 31 deletions

View File

@ -0,0 +1,8 @@
# Support for a heated bed
#
# Copyright (C) 2018 Kevin O'Connor <kevin@koconnor.net>
#
# This file may be distributed under the terms of the GNU GPLv3 license.
def load_config(config):
return config.get_printer().lookup_object('heater').setup_heater(config)

View File

@ -3,7 +3,7 @@
# Copyright (C) 2016-2018 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 fan, extruder import fan
PIN_MIN_TIME = 0.100 PIN_MIN_TIME = 0.100
@ -20,8 +20,8 @@ class PrinterHeaterFan:
self.fan.mcu_fan.setup_start_value(0., max_power) self.fan.mcu_fan.setup_start_value(0., max_power)
def printer_state(self, state): def printer_state(self, state):
if state == 'ready': if state == 'ready':
self.heater = extruder.get_printer_heater( pheater = self.printer.lookup_object('heater')
self.printer, self.heater_name) self.heater = pheater.lookup_heater(self.heater_name)
reactor = self.printer.get_reactor() reactor = self.printer.get_reactor()
reactor.register_timer(self.callback, reactor.NOW) reactor.register_timer(self.callback, reactor.NOW)
def callback(self, eventtime): def callback(self, eventtime):

View File

@ -4,7 +4,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 math, logging import math, logging
import extruder, heater import heater
class PIDCalibrate: class PIDCalibrate:
def __init__(self, config): def __init__(self, config):
@ -18,8 +18,9 @@ class PIDCalibrate:
heater_name = self.gcode.get_str('HEATER', params) heater_name = self.gcode.get_str('HEATER', params)
target = self.gcode.get_float('TARGET', params) target = self.gcode.get_float('TARGET', params)
write_file = self.gcode.get_int('WRITE_FILE', params, 0) write_file = self.gcode.get_int('WRITE_FILE', params, 0)
pheater = self.printer.lookup_object('heater')
try: try:
heater = extruder.get_printer_heater(self.printer, heater_name) heater = pheater.lookup_heater(heater_name)
except self.printer.config_error as e: except self.printer.config_error as e:
raise self.gcode.error(str(e)) raise self.gcode.error(str(e))
print_time = self.printer.lookup_object('toolhead').get_last_move_time() print_time = self.printer.lookup_object('toolhead').get_last_move_time()

View File

@ -4,7 +4,6 @@
# #
# 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 logging import logging
import extruder
HINT_THERMAL = """ HINT_THERMAL = """
See the 'verify_heater' section in config/example-extras.cfg See the 'verify_heater' section in config/example-extras.cfg
@ -29,8 +28,8 @@ class HeaterCheck:
self.fault_systime = self.printer.get_reactor().NEVER self.fault_systime = self.printer.get_reactor().NEVER
def printer_state(self, state): def printer_state(self, state):
if state == 'connect': if state == 'connect':
self.heater = extruder.get_printer_heater( pheater = self.printer.lookup_object('heater')
self.printer, self.heater_name) self.heater = pheater.lookup_heater(self.heater_name)
logging.info("Starting heater checks for %s", self.heater_name) logging.info("Starting heater checks for %s", self.heater_name)
reactor = self.printer.get_reactor() reactor = self.printer.get_reactor()
reactor.register_timer(self.check_event, reactor.NOW) reactor.register_timer(self.check_event, reactor.NOW)

View File

@ -4,7 +4,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 math, logging import math, logging
import stepper, heater, homing import stepper, homing
EXTRUDE_DIFF_IGNORE = 1.02 EXTRUDE_DIFF_IGNORE = 1.02
@ -13,10 +13,11 @@ class PrinterExtruder:
self.printer = printer self.printer = printer
self.name = config.get_name() self.name = config.get_name()
shared_heater = config.get('shared_heater', None) shared_heater = config.get('shared_heater', None)
pheater = printer.lookup_object('heater')
if shared_heater is None: if shared_heater is None:
self.heater = heater.PrinterHeater(printer, config) self.heater = pheater.setup_heater(config)
else: else:
self.heater = get_printer_heater(printer, shared_heater) self.heater = pheater.lookup_heater(shared_heater)
self.stepper = stepper.PrinterStepper(printer, config) self.stepper = stepper.PrinterStepper(printer, config)
self.nozzle_diameter = config.getfloat('nozzle_diameter', above=0.) self.nozzle_diameter = config.getfloat('nozzle_diameter', above=0.)
filament_diameter = config.getfloat( filament_diameter = config.getfloat(
@ -274,12 +275,3 @@ def get_printer_extruders(printer):
break break
out.append(extruder) out.append(extruder)
return out return out
def get_printer_heater(printer, name):
if name == 'heater_bed':
return printer.lookup_object(name)
if name == 'extruder':
name = 'extruder0'
if name.startswith('extruder'):
return printer.lookup_object(name).get_heater()
raise printer.config_error("Unknown heater '%s'" % (name,))

View File

@ -104,13 +104,14 @@ PWM_DELAY = REPORT_TIME + SAMPLE_TIME*SAMPLE_COUNT
class error(Exception): class error(Exception):
pass pass
class PrinterHeater: class Heater:
error = error error = error
def __init__(self, printer, config): def __init__(self, config):
self.printer = printer printer = config.get_printer()
self.name = config.get_name() self.name = config.get_name()
sensor_params = config.getchoice('sensor_type', Sensors) sensor_type = config.get('sensor_type')
self.sensor = sensor_params['class'](config, sensor_params) pheater = printer.lookup_object('heater')
self.sensor = pheater.setup_sensor(sensor_type, config)
self.min_temp = config.getfloat('min_temp', minval=KELVIN_TO_CELCIUS) self.min_temp = config.getfloat('min_temp', minval=KELVIN_TO_CELCIUS)
self.max_temp = config.getfloat('max_temp', above=self.min_temp) self.max_temp = config.getfloat('max_temp', above=self.min_temp)
self.min_extrude_temp = config.getfloat( self.min_extrude_temp = config.getfloat(
@ -278,7 +279,42 @@ class ControlPID:
return (abs(temp_diff) > PID_SETTLE_DELTA return (abs(temp_diff) > PID_SETTLE_DELTA
or abs(self.prev_temp_deriv) > PID_SETTLE_SLOPE) or abs(self.prev_temp_deriv) > PID_SETTLE_SLOPE)
######################################################################
# Sensor and heater lookup
######################################################################
class PrinterHeaters:
def __init__(self, printer, config):
self.printer = printer
self.sensors = {}
self.heaters = {}
def add_sensor(self, sensor_type, params):
self.sensors[sensor_type] = params
def setup_sensor(self, sensor_type, config):
if sensor_type not in self.sensors:
raise self.printer.config_error("Unknown temperature sensor '%s'" % (
sensor_type,))
params = self.sensors[sensor_type]
return params['class'](config, params)
def setup_heater(self, config):
heater_name = config.get_name()
if heater_name == 'extruder':
heater_name = 'extruder0'
if heater_name in self.heaters:
raise config.error("Heater %s already registered" % (heater_name,))
self.heaters[heater_name] = heater = Heater(config)
return heater
def lookup_heater(self, heater_name):
if heater_name == 'extruder':
heater_name = 'extruder0'
if heater_name not in self.heaters:
raise self.printer.config_error(
"Unknown heater '%s'" % (heater_name,))
return self.heaters[heater_name]
def add_printer_objects(printer, config): def add_printer_objects(printer, config):
if config.has_section('heater_bed'): ph = PrinterHeaters(printer, config)
printer.add_object('heater_bed', PrinterHeater( printer.add_object('heater', ph)
printer, config.getsection('heater_bed'))) for sensor_type, params in Sensors.items():
ph.add_sensor(sensor_type, params)

View File

@ -7,7 +7,7 @@
import sys, os, optparse, logging, time, threading import sys, os, optparse, logging, time, threading
import collections, ConfigParser, importlib import collections, ConfigParser, importlib
import util, reactor, queuelogger, msgproto import util, reactor, queuelogger, msgproto
import gcode, pins, mcu, toolhead, extruder, heater import gcode, pins, heater, mcu, toolhead, extruder
message_ready = "Printer is ready" message_ready = "Printer is ready"
@ -204,11 +204,11 @@ class Printer:
ConfigLogger(fileconfig, self.bglogger) ConfigLogger(fileconfig, self.bglogger)
# Create printer components # Create printer components
config = ConfigWrapper(self, fileconfig, 'printer') config = ConfigWrapper(self, fileconfig, 'printer')
for m in [pins, mcu]: for m in [pins, heater, mcu]:
m.add_printer_objects(self, config) m.add_printer_objects(self, config)
for section in fileconfig.sections(): for section in fileconfig.sections():
self.try_load_module(config, section) self.try_load_module(config, section)
for m in [toolhead, extruder, heater]: for m in [toolhead, extruder]:
m.add_printer_objects(self, config) m.add_printer_objects(self, config)
# 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 }