Skip to content

Commit

Permalink
heater -> feeder
Browse files Browse the repository at this point in the history
  • Loading branch information
G authored and G committed Jan 11, 2024
1 parent 4c0aabc commit 1bc41c3
Showing 1 changed file with 63 additions and 63 deletions.
126 changes: 63 additions & 63 deletions klippy/extras/filafeeders.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Tracking of PWM controlled heaters and their temperature control
# Feed filament by step motor, control by switch or holl senser.
#
# Copyright (C) 2016-2020 Kevin O'Connor <[email protected]>
# Copyright (C) 2024 guoge
#
# This file may be distributed under the terms of the GNU GPLv3 license.
import os, logging, threading
Expand All @@ -10,12 +10,12 @@
# Heater
######################################################################

KELVIN_TO_CELSIUS = -273.15
MAX_HEAT_TIME = 5.0
AMBIENT_TEMP = 25.
PID_PARAM_BASE = 255.
# KELVIN_TO_CELSIUS = -273.15
# MAX_HEAT_TIME = 5.0
# AMBIENT_TEMP = 25.
# PID_PARAM_BASE = 255.

class Heater:
class Feeder: #Heater:
def __init__(self, config, sensor):
self.printer = config.get_printer()
self.reactor = self.printer.get_reactor() #add by guoge 20231130.
Expand Down Expand Up @@ -47,16 +47,16 @@ def __init__(self, config, sensor):
algos = {'watermark': ControlBangBang, 'pid': ControlPID}
algo = config.getchoice('control', algos)
self.control = algo(self, config)
# Setup output heater pin
heater_pin = config.get('heater_pin')
# Setup output feeder motor
feeder_pin = config.get('feeder_pin')
ppins = self.printer.lookup_object('pins')
self.mcu_pwm = ppins.setup_pin('pwm', heater_pin)
self.mcu_pwm = ppins.setup_pin('pwm', feeder_pin)
pwm_cycle_time = config.getfloat('pwm_cycle_time', 0.100, above=0.,
maxval=self.pwm_delay)
self.mcu_pwm.setup_cycle_time(pwm_cycle_time)
self.mcu_pwm.setup_max_duration(MAX_HEAT_TIME)
# Load additional modules
self.printer.load_object(config, "verify_heater %s" % (self.name,))
self.printer.load_object(config, "verify_feeder %s" % (self.name,))
self.printer.load_object(config, "pid_calibrate")
gcode = self.printer.lookup_object("gcode")
gcode.register_mux_command("SET_HEATER_TEMPERATURE", "HEATER",
Expand Down Expand Up @@ -88,11 +88,11 @@ def temperature_callback(self, read_time, temp):
adj_time = min(time_diff * self.inv_smooth_time, 1.)
self.smoothed_temp += temp_diff * adj_time
if self.smoothed_temp > 500 :
logging.info(" *** Temp callbacke Error @ %.3f, heater: %s temp:%.3f/%.3f @ read time:%.3f - %.3f, timeDiff:%.2f, tempDiff:%.3f, too high",
logging.info(" *** Temp callbacke Error @ %.3f, feeder: %s temp:%.3f/%.3f @ read time:%.3f - %.3f, timeDiff:%.2f, tempDiff:%.3f, too high",
curtime, self.name, self.smoothed_temp, temp, read_time, last_time, time_diff, temp_diff)
self.smoothed_temp = 500;
if self.smoothed_temp < -100 :
logging.info(" *** Temp callbacke Error @% .3f, heater: %s temp:%.3f/%.3f @ read time:%.3f - %.3f, timeDiff:%.2f, tempDiff:%.3f, too low",
logging.info(" *** Temp callbacke Error @% .3f, feeder: %s temp:%.3f/%.3f @ read time:%.3f - %.3f, timeDiff:%.2f, tempDiff:%.3f, too low",
curtime, self.name, self.smoothed_temp, temp, read_time, last_time, time_diff, temp_diff)
self.smoothed_temp = -100
self.can_extrude = (self.smoothed_temp >= self.min_extrude_temp)
Expand Down Expand Up @@ -146,21 +146,21 @@ def get_status(self, eventtime):
last_pwm_value = self.last_pwm_value
return {'temperature': round(smoothed_temp, 2), 'target': target_temp,
'power': last_pwm_value}
cmd_SET_HEATER_TEMPERATURE_help = "Sets a heater temperature"
cmd_SET_HEATER_TEMPERATURE_help = "Sets a feeder temperature"
def cmd_SET_HEATER_TEMPERATURE(self, gcmd):
temp = gcmd.get_float('TARGET', 0.)
pheaters = self.printer.lookup_object('heaters')
pheaters.set_temperature(self, temp)
pfeeders = self.printer.lookup_object('feeders')
pfeeders.set_temperature(self, temp)


######################################################################
# Bang-bang control algo
######################################################################

class ControlBangBang:
def __init__(self, heater, config):
self.heater = heater
self.heater_max_power = heater.get_max_power()
def __init__(self, feeder, config):
self.feeder = feeder
self.feeder_max_power = feeder.get_max_power()
self.max_delta = config.getfloat('max_delta', 2.0, above=0.)
self.heating = False
def temperature_update(self, read_time, temp, target_temp):
Expand All @@ -169,9 +169,9 @@ def temperature_update(self, read_time, temp, target_temp):
elif not self.heating and temp <= target_temp-self.max_delta:
self.heating = True
if self.heating:
self.heater.set_pwm(read_time, self.heater_max_power)
self.feeder.set_pwm(read_time, self.feeder_max_power)
else:
self.heater.set_pwm(read_time, 0.)
self.feeder.set_pwm(read_time, 0.)
def check_busy(self, eventtime, smoothed_temp, target_temp):
return smoothed_temp < target_temp-self.max_delta

Expand All @@ -184,16 +184,16 @@ def check_busy(self, eventtime, smoothed_temp, target_temp):
PID_SETTLE_SLOPE = .1

class ControlPID:
def __init__(self, heater, config):
self.heater = heater
self.heater_max_power = heater.get_max_power()
def __init__(self, feeder, config):
self.feeder = feeder
self.feeder_max_power = feeder.get_max_power()
self.Kp = config.getfloat('pid_Kp') / PID_PARAM_BASE
self.Ki = config.getfloat('pid_Ki') / PID_PARAM_BASE
self.Kd = config.getfloat('pid_Kd') / PID_PARAM_BASE
self.min_deriv_time = heater.get_smooth_time()
self.min_deriv_time = feeder.get_smooth_time()
self.temp_integ_max = 0.
if self.Ki:
self.temp_integ_max = self.heater_max_power / self.Ki
self.temp_integ_max = self.feeder_max_power / self.Ki
self.prev_temp = AMBIENT_TEMP
self.prev_temp_time = 0.
self.prev_temp_deriv = 0.
Expand All @@ -215,8 +215,8 @@ def temperature_update(self, read_time, temp, target_temp):
co = self.Kp*temp_err + self.Ki*temp_integ - self.Kd*temp_deriv
#logging.debug("pid: %f@%.3f -> diff=%f deriv=%f err=%f integ=%f co=%d",
# temp, read_time, temp_diff, temp_deriv, temp_err, temp_integ, co)
bounded_co = max(0., min(self.heater_max_power, co))
self.heater.set_pwm(read_time, bounded_co)
bounded_co = max(0., min(self.feeder_max_power, co))
self.feeder.set_pwm(read_time, bounded_co)
# Store state for next measurement
self.prev_temp = temp
self.prev_temp_time = read_time
Expand All @@ -230,22 +230,22 @@ def check_busy(self, eventtime, smoothed_temp, target_temp):


######################################################################
# Sensor and heater lookup
# Sensor and feeder lookup
######################################################################

class PrinterHeaters:
class FilaFeeders: #PrinterHeaters:
def __init__(self, config):
self.printer = config.get_printer()
self.sensor_factories = {}
self.heaters = {}
self.feeders = {}
self.gcode_id_to_sensor = {}
self.available_heaters = []
self.available_feeders = []
self.available_sensors = []
self.available_monitors = []
self.has_started = self.have_load_sensors = False
self.printer.register_event_handler("klippy:ready", self._handle_ready)
self.printer.register_event_handler("gcode:request_restart",
self.turn_off_all_heaters)
self.turn_off_all_feeders)
# Register commands
gcode = self.printer.lookup_object('gcode')
gcode.register_command("TURN_OFF_HEATERS", self.cmd_TURN_OFF_HEATERS,
Expand All @@ -267,24 +267,24 @@ def load_config(self, config):
self.printer.load_object(dconfig, c.get_name())
def add_sensor_factory(self, sensor_type, sensor_factory):
self.sensor_factories[sensor_type] = sensor_factory
def setup_heater(self, config, gcode_id=None):
heater_name = config.get_name().split()[-1]
if heater_name in self.heaters:
raise config.error("Heater %s already registered" % (heater_name,))
def setup_feeder(self, config, gcode_id=None):
feeder_name = config.get_name().split()[-1]
if feeder_name in self.feeders:
raise config.error("Heater %s already registered" % (feeder_name,))
# Setup sensor
sensor = self.setup_sensor(config)
# Create heater
self.heaters[heater_name] = heater = Heater(config, sensor)
self.register_sensor(config, heater, gcode_id)
self.available_heaters.append(config.get_name())
return heater
def get_all_heaters(self):
return self.available_heaters
def lookup_heater(self, heater_name):
if heater_name not in self.heaters:
# Create feeder
self.feeders[feeder_name] = feeder = Feeder(config, sensor)
self.register_sensor(config, feeder, gcode_id)
self.available_feeders.append(config.get_name())
return feeder
def get_all_feeders(self):
return self.available_feeders
def lookup_feeder(self, feeder_name):
if feeder_name not in self.feeders:
raise self.printer.config_error(
"Unknown heater '%s'" % (heater_name,))
return self.heaters[heater_name]
"Unknown feeder '%s'" % (feeder_name,))
return self.feeders[feeder_name]
def setup_sensor(self, config):
if not self.have_load_sensors:
self.load_config(config)
Expand All @@ -308,15 +308,15 @@ def register_sensor(self, config, psensor, gcode_id=None):
def register_monitor(self, config):
self.available_monitors.append(config.get_name())
def get_status(self, eventtime):
return {'available_heaters': self.available_heaters,
return {'available_feeders': self.available_feeders,
'available_sensors': self.available_sensors,
'available_monitors': self.available_monitors}
def turn_off_all_heaters(self, print_time=0.):
for heater in self.heaters.values():
heater.set_temp(0.)
cmd_TURN_OFF_HEATERS_help = "Turn off all heaters"
def turn_off_all_feeders(self, print_time=0.):
for feeder in self.feeders.values():
feeder.set_temp(0.)
cmd_TURN_OFF_HEATERS_help = "Turn off all feeders"
def cmd_TURN_OFF_HEATERS(self, gcmd):
self.turn_off_all_heaters()
self.turn_off_all_feeders()
# G-Code M105 temperature reporting
def _handle_ready(self):
self.has_started = True
Expand All @@ -337,24 +337,24 @@ def cmd_M105(self, gcmd):
did_ack = gcmd.ack(msg)
if not did_ack:
gcmd.respond_raw(msg)
def _wait_for_temperature(self, heater):
# Helper to wait on heater.check_busy() and report M105 temperatures
def _wait_for_temperature(self, feeder):
# Helper to wait on feeder.check_busy() and report M105 temperatures
if self.printer.get_start_args().get('debugoutput') is not None:
return
toolhead = self.printer.lookup_object("toolhead")
gcode = self.printer.lookup_object("gcode")
reactor = self.printer.get_reactor()
eventtime = reactor.monotonic()
while not self.printer.is_shutdown() and heater.check_busy(eventtime):
while not self.printer.is_shutdown() and feeder.check_busy(eventtime):
print_time = toolhead.get_last_move_time()
gcode.respond_raw(self._get_temp(eventtime))
eventtime = reactor.pause(eventtime + 1.)
def set_temperature(self, heater, temp, wait=False):
def set_temperature(self, feeder, temp, wait=False):
toolhead = self.printer.lookup_object('toolhead')
toolhead.register_lookahead_callback((lambda pt: None))
heater.set_temp(temp)
feeder.set_temp(temp)
if wait and temp:
self._wait_for_temperature(heater)
self._wait_for_temperature(feeder)
cmd_TEMPERATURE_WAIT_help = "Wait for a temperature on a sensor"
def cmd_TEMPERATURE_WAIT(self, gcmd):
sensor_name = gcmd.get('SENSOR')
Expand All @@ -367,8 +367,8 @@ def cmd_TEMPERATURE_WAIT(self, gcmd):
"Error on 'TEMPERATURE_WAIT': missing MINIMUM or MAXIMUM.")
if self.printer.get_start_args().get('debugoutput') is not None:
return
if sensor_name in self.heaters:
sensor = self.heaters[sensor_name]
if sensor_name in self.feeders:
sensor = self.feeders[sensor_name]
else:
sensor = self.printer.lookup_object(sensor_name)
toolhead = self.printer.lookup_object("toolhead")
Expand All @@ -383,4 +383,4 @@ def cmd_TEMPERATURE_WAIT(self, gcmd):
eventtime = reactor.pause(eventtime + 1.)

def load_config(config):
return PrinterHeaters(config)
return FilaFeeders(config) #PrinterHeaters(config)

0 comments on commit 1bc41c3

Please sign in to comment.