aboutsummaryrefslogtreecommitdiffstats
path: root/klippy
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2018-04-04 14:13:59 -0400
committerKevin O'Connor <kevin@koconnor.net>2018-04-04 23:14:33 -0400
commit0fc4f0946ed6801de1a3403311f5fc2836559dd9 (patch)
tree5750b7cce9cef41a4905e2f76c2193c7a390e43c /klippy
parent7e78b2665e23f2b6194ff438a39b5440fa514ee3 (diff)
downloadkutter-0fc4f0946ed6801de1a3403311f5fc2836559dd9.tar.gz
kutter-0fc4f0946ed6801de1a3403311f5fc2836559dd9.tar.xz
kutter-0fc4f0946ed6801de1a3403311f5fc2836559dd9.zip
heater: Move adc logic into Thermistor class
The Thermistor (and Linear) class should handle all the details of reading the ADC values and converting them to temperatures. So, move that logic out of the Heater() class. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'klippy')
-rw-r--r--klippy/extras/pid_calibrate.py2
-rw-r--r--klippy/heater.py84
2 files changed, 51 insertions, 35 deletions
diff --git a/klippy/extras/pid_calibrate.py b/klippy/extras/pid_calibrate.py
index 1caffeb7..bd2b29d6 100644
--- a/klippy/extras/pid_calibrate.py
+++ b/klippy/extras/pid_calibrate.py
@@ -62,7 +62,7 @@ class ControlAutoTune:
self.pwm_samples.append((read_time + heater.PWM_DELAY, value))
self.last_pwm = value
self.heater.set_pwm(read_time, value)
- def adc_callback(self, read_time, temp):
+ def temperature_callback(self, read_time, temp):
self.temp_samples.append((read_time, temp))
if self.heating and temp >= self.heater.target_temp:
self.heating = False
diff --git a/klippy/heater.py b/klippy/heater.py
index f8031538..b8f2a276 100644
--- a/klippy/heater.py
+++ b/klippy/heater.py
@@ -11,11 +11,18 @@ import math, logging, threading
######################################################################
KELVIN_TO_CELCIUS = -273.15
+SAMPLE_TIME = 0.001
+SAMPLE_COUNT = 8
+REPORT_TIME = 0.300
# Analog voltage to temperature converter for thermistors
class Thermistor:
def __init__(self, config, params):
self.pullup = config.getfloat('pullup_resistor', 4700., above=0.)
+ ppins = config.get_printer().lookup_object('pins')
+ self.mcu_adc = ppins.setup_pin('adc', config.get('sensor_pin'))
+ self.mcu_adc.setup_adc_callback(REPORT_TIME, self.adc_callback)
+ self.temperature_callback = None
self.c1 = self.c2 = self.c3 = 0.
if 'beta' in params:
self.calc_coefficients_beta(params)
@@ -47,12 +54,20 @@ class Thermistor:
self.c3 = 0.
self.c2 = 1. / params['beta']
self.c1 = inv_t1 - self.c2 * ln_r1
- def calc_temp(self, adc):
- adc = max(.00001, min(.99999, adc))
+ def setup_minmax(self, min_temp, max_temp):
+ adc_range = [self.calc_adc(min_temp), self.calc_adc(max_temp)]
+ self.mcu_adc.setup_minmax(SAMPLE_TIME, SAMPLE_COUNT,
+ minval=min(adc_range), maxval=max(adc_range))
+ def setup_callback(self, temperature_callback):
+ self.temperature_callback = temperature_callback
+ def adc_callback(self, read_time, read_value):
+ # Calculate temperature from adc
+ adc = max(.00001, min(.99999, read_value))
r = self.pullup * adc / (1.0 - adc)
ln_r = math.log(r)
inv_t = self.c1 + self.c2 * ln_r + self.c3 * ln_r**3
- return 1.0/inv_t + KELVIN_TO_CELCIUS
+ temp = 1.0/inv_t + KELVIN_TO_CELCIUS
+ self.temperature_callback(read_time, temp)
def calc_adc(self, temp):
inv_t = 1. / (temp - KELVIN_TO_CELCIUS)
if self.c3:
@@ -69,11 +84,22 @@ class Thermistor:
class Linear:
def __init__(self, config, params):
adc_voltage = config.getfloat('adc_voltage', 5., above=0.)
+ ppins = config.get_printer().lookup_object('pins')
+ self.mcu_adc = ppins.setup_pin('adc', config.get('sensor_pin'))
+ self.mcu_adc.setup_adc_callback(REPORT_TIME, self.adc_callback)
+ self.temperature_callback = None
slope = (params['t2'] - params['t1']) / (params['v2'] - params['v1'])
self.gain = adc_voltage * slope
self.offset = params['t1'] - params['v1'] * slope
- def calc_temp(self, adc):
- return adc * self.gain + self.offset
+ def setup_minmax(self, min_temp, max_temp):
+ adc_range = [self.calc_adc(min_temp), self.calc_adc(max_temp)]
+ self.mcu_adc.setup_minmax(SAMPLE_TIME, SAMPLE_COUNT,
+ minval=min(adc_range), maxval=max(adc_range))
+ def setup_callback(self, temperature_callback):
+ self.temperature_callback = temperature_callback
+ def adc_callback(self, read_time, read_value):
+ temp = read_value * self.gain + self.offset
+ self.temperature_callback(read_time, temp)
def calc_adc(self, temp):
return (temp - self.offset) / self.gain
@@ -95,9 +121,6 @@ Sensors = {
# Heater
######################################################################
-SAMPLE_TIME = 0.001
-SAMPLE_COUNT = 8
-REPORT_TIME = 0.300
MAX_HEAT_TIME = 5.0
AMBIENT_TEMP = 25.
PID_PARAM_BASE = 255.
@@ -108,14 +131,14 @@ class error(Exception):
class Heater:
error = error
- def __init__(self, config):
- printer = config.get_printer()
+ def __init__(self, config, sensor):
+ self.sensor = sensor
self.name = config.get_name()
- sensor_type = config.get('sensor_type')
- pheater = printer.lookup_object('heater')
- self.sensor = pheater.setup_sensor(sensor_type, config)
+ printer = config.get_printer()
self.min_temp = config.getfloat('min_temp', minval=KELVIN_TO_CELCIUS)
self.max_temp = config.getfloat('max_temp', above=self.min_temp)
+ self.sensor.setup_minmax(self.min_temp, self.max_temp)
+ self.sensor.setup_callback(self.temperature_callback)
self.min_extrude_temp = config.getfloat(
'min_extrude_temp', 170., minval=self.min_temp, maxval=self.max_temp)
self.max_power = config.getfloat('max_power', 1., above=0., maxval=1.)
@@ -135,13 +158,7 @@ class Heater:
'pwm_cycle_time', 0.100, above=0., maxval=REPORT_TIME)
self.mcu_pwm.setup_cycle_time(pwm_cycle_time)
self.mcu_pwm.setup_max_duration(MAX_HEAT_TIME)
- self.mcu_adc = ppins.setup_pin('adc', config.get('sensor_pin'))
- adc_range = [self.sensor.calc_adc(self.min_temp),
- self.sensor.calc_adc(self.max_temp)]
- self.mcu_adc.setup_minmax(SAMPLE_TIME, SAMPLE_COUNT,
- minval=min(adc_range), maxval=max(adc_range))
- self.mcu_adc.setup_adc_callback(REPORT_TIME, self.adc_callback)
- is_fileoutput = self.mcu_adc.get_mcu().is_fileoutput()
+ is_fileoutput = self.mcu_pwm.get_mcu().is_fileoutput()
self.can_extrude = self.min_extrude_temp <= 0. or is_fileoutput
self.control = algo(self, config)
# pwm caching
@@ -164,14 +181,13 @@ class Heater:
self.name, value, pwm_time,
self.last_temp, self.last_temp_time, self.target_temp)
self.mcu_pwm.set_pwm(pwm_time, value)
- def adc_callback(self, read_time, read_value):
- temp = self.sensor.calc_temp(read_value)
+ def temperature_callback(self, read_time, temp):
with self.lock:
self.last_temp = temp
self.last_temp_time = read_time
self.can_extrude = (temp >= self.min_extrude_temp)
- self.control.adc_callback(read_time, temp)
- #logging.debug("temp: %.3f %f = %f", read_time, read_value, temp)
+ self.control.temperature_callback(read_time, temp)
+ #logging.debug("temp: %.3f %f = %f", read_time, temp)
# External commands
def set_temp(self, print_time, degrees):
if degrees and (degrees < self.min_temp or degrees > self.max_temp):
@@ -180,7 +196,7 @@ class Heater:
with self.lock:
self.target_temp = degrees
def get_temp(self, eventtime):
- print_time = self.mcu_adc.get_mcu().estimated_print_time(eventtime) - 5.
+ print_time = self.mcu_pwm.get_mcu().estimated_print_time(eventtime) - 5.
with self.lock:
if self.last_temp_time < print_time:
return 0., self.target_temp
@@ -218,7 +234,7 @@ class ControlBangBang:
self.heater = heater
self.max_delta = config.getfloat('max_delta', 2.0, above=0.)
self.heating = False
- def adc_callback(self, read_time, temp):
+ def temperature_callback(self, read_time, temp):
if self.heating and temp >= self.heater.target_temp+self.max_delta:
self.heating = False
elif not self.heating and temp <= self.heater.target_temp-self.max_delta:
@@ -251,7 +267,7 @@ class ControlPID:
self.prev_temp_time = 0.
self.prev_temp_deriv = 0.
self.prev_temp_integ = 0.
- def adc_callback(self, read_time, temp):
+ def temperature_callback(self, read_time, temp):
time_diff = read_time - self.prev_temp_time
# Calculate change of temperature
temp_diff = temp - self.prev_temp
@@ -293,19 +309,19 @@ class PrinterHeaters:
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)
+ sensor_type = config.get('sensor_type')
+ if sensor_type not in self.sensors:
+ raise self.printer.config_error("Unknown temperature sensor '%s'" % (
+ sensor_type,))
+ params = self.sensors[sensor_type]
+ sensor = params['class'](config, params)
+ self.heaters[heater_name] = heater = Heater(config, sensor)
return heater
def lookup_heater(self, heater_name):
if heater_name == 'extruder':