mirror of
https://github.com/Klipper3d/klipper.git
synced 2026-03-10 04:46:56 -06:00
mcu: Convert ADC callback to pass a list of samples
Support batching multiple samples together and pass those samples to the registered adc callback. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
5a2fd1009d
commit
8ed426b54c
8 changed files with 73 additions and 50 deletions
|
|
@ -19,15 +19,16 @@ class MCU_scaled_adc:
|
|||
self._callback = None
|
||||
self.setup_adc_sample = self._mcu_adc.setup_adc_sample
|
||||
self.get_mcu = self._mcu_adc.get_mcu
|
||||
def _handle_callback(self, read_time, read_value):
|
||||
def _handle_callback(self, samples):
|
||||
max_adc = self._main.last_vref[1]
|
||||
min_adc = self._main.last_vssa[1]
|
||||
scaled_val = (read_value - min_adc) / (max_adc - min_adc)
|
||||
self._last_state = (read_time, scaled_val)
|
||||
self._callback(read_time, scaled_val)
|
||||
def setup_adc_callback(self, report_time, callback):
|
||||
adjsamples = [(t, (read_value - min_adc) / (max_adc - min_adc))
|
||||
for t, read_value in samples]
|
||||
self._last_state = adjsamples[-1]
|
||||
self._callback(adjsamples)
|
||||
def setup_adc_callback(self, callback):
|
||||
self._callback = callback
|
||||
self._mcu_adc.setup_adc_callback(report_time, self._handle_callback)
|
||||
self._mcu_adc.setup_adc_callback(self._handle_callback)
|
||||
def get_last_value(self):
|
||||
return self._last_state
|
||||
|
||||
|
|
@ -52,8 +53,8 @@ class PrinterADCScaled:
|
|||
pin_name = config.get(name + '_pin')
|
||||
ppins = self.printer.lookup_object('pins')
|
||||
mcu_adc = ppins.setup_pin('adc', pin_name)
|
||||
mcu_adc.setup_adc_callback(REPORT_TIME, callback)
|
||||
mcu_adc.setup_adc_sample(SAMPLE_TIME, SAMPLE_COUNT)
|
||||
mcu_adc.setup_adc_callback(callback)
|
||||
mcu_adc.setup_adc_sample(REPORT_TIME, SAMPLE_TIME, SAMPLE_COUNT)
|
||||
query_adc = config.get_printer().load_object(config, 'query_adc')
|
||||
query_adc.register_adc(self.name + ":" + name, mcu_adc)
|
||||
return mcu_adc
|
||||
|
|
@ -68,9 +69,11 @@ class PrinterADCScaled:
|
|||
adj_time = min(time_diff * self.inv_smooth_time, 1.)
|
||||
smoothed_value = last_value + value_diff * adj_time
|
||||
return (read_time, smoothed_value)
|
||||
def vref_callback(self, read_time, read_value):
|
||||
def vref_callback(self, samples):
|
||||
read_time, read_value = samples[-1]
|
||||
self.last_vref = self.calc_smooth(read_time, read_value, self.last_vref)
|
||||
def vssa_callback(self, read_time, read_value):
|
||||
def vssa_callback(self, samples):
|
||||
read_time, read_value = samples[-1]
|
||||
self.last_vssa = self.calc_smooth(read_time, read_value, self.last_vssa)
|
||||
|
||||
def load_config_prefix(config):
|
||||
|
|
|
|||
|
|
@ -21,20 +21,21 @@ class PrinterADCtoTemperature:
|
|||
self.adc_convert = adc_convert
|
||||
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.mcu_adc.setup_adc_callback(self.adc_callback)
|
||||
self.diag_helper = HelperTemperatureDiagnostics(
|
||||
config, self.mcu_adc, adc_convert.calc_temp)
|
||||
def setup_callback(self, temperature_callback):
|
||||
self.temperature_callback = temperature_callback
|
||||
def get_report_time_delta(self):
|
||||
return REPORT_TIME
|
||||
def adc_callback(self, read_time, read_value):
|
||||
def adc_callback(self, samples):
|
||||
read_time, read_value = samples[-1]
|
||||
temp = self.adc_convert.calc_temp(read_value)
|
||||
self.temperature_callback(read_time + SAMPLE_COUNT * SAMPLE_TIME, temp)
|
||||
def setup_minmax(self, min_temp, max_temp):
|
||||
arange = [self.adc_convert.calc_adc(t) for t in [min_temp, max_temp]]
|
||||
min_adc, max_adc = sorted(arange)
|
||||
self.mcu_adc.setup_adc_sample(SAMPLE_TIME, SAMPLE_COUNT,
|
||||
self.mcu_adc.setup_adc_sample(REPORT_TIME, SAMPLE_TIME, SAMPLE_COUNT,
|
||||
minval=min_adc, maxval=max_adc,
|
||||
range_check_count=RANGE_CHECK_COUNT)
|
||||
self.diag_helper.setup_diag_minmax(min_temp, max_temp, min_adc, max_adc)
|
||||
|
|
|
|||
|
|
@ -364,7 +364,7 @@ class ADS1X1X_pin:
|
|||
systime = self._reactor.monotonic()
|
||||
measured_time = self.chip.mcu.estimated_print_time(systime)
|
||||
self._last_state = (measured_time, target_value)
|
||||
self.callback(measured_time, target_value)
|
||||
self.callback([(measured_time, target_value)])
|
||||
else:
|
||||
self.invalid_count = self.invalid_count + 1
|
||||
self.check_invalid()
|
||||
|
|
@ -379,16 +379,17 @@ class ADS1X1X_pin:
|
|||
def get_mcu(self):
|
||||
return self.mcu
|
||||
|
||||
def setup_adc_callback(self, report_time, callback):
|
||||
self.report_time = report_time
|
||||
def setup_adc_callback(self, callback):
|
||||
self.callback = callback
|
||||
self.chip.handle_report_time_update()
|
||||
|
||||
def setup_adc_sample(self, sample_time, sample_count,
|
||||
minval=0., maxval=1., range_check_count=0):
|
||||
def setup_adc_sample(self, report_time, sample_time=0., sample_count=1,
|
||||
batch_num=1, minval=0., maxval=1.,
|
||||
range_check_count=0):
|
||||
self.report_time = report_time
|
||||
self.minval = minval
|
||||
self.maxval = maxval
|
||||
self.range_check_count = range_check_count
|
||||
self.chip.handle_report_time_update()
|
||||
|
||||
def get_last_value(self):
|
||||
return self._last_state
|
||||
|
|
|
|||
|
|
@ -104,8 +104,9 @@ class MCU_ADC_buttons:
|
|||
self.max_value = 0.
|
||||
ppins = printer.lookup_object('pins')
|
||||
self.mcu_adc = ppins.setup_pin('adc', self.pin)
|
||||
self.mcu_adc.setup_adc_sample(ADC_SAMPLE_TIME, ADC_SAMPLE_COUNT)
|
||||
self.mcu_adc.setup_adc_callback(ADC_REPORT_TIME, self.adc_callback)
|
||||
self.mcu_adc.setup_adc_sample(ADC_REPORT_TIME,
|
||||
ADC_SAMPLE_TIME, ADC_SAMPLE_COUNT)
|
||||
self.mcu_adc.setup_adc_callback(self.adc_callback)
|
||||
query_adc = printer.lookup_object('query_adc')
|
||||
query_adc.register_adc('adc_button:' + pin.strip(), self.mcu_adc)
|
||||
|
||||
|
|
@ -114,7 +115,8 @@ class MCU_ADC_buttons:
|
|||
self.max_value = max(self.max_value, max_value)
|
||||
self.buttons.append((min_value, max_value, callback))
|
||||
|
||||
def adc_callback(self, read_time, read_value):
|
||||
def adc_callback(self, samples):
|
||||
read_time, read_value = samples[-1]
|
||||
adc = max(.00001, min(.99999, read_value))
|
||||
value = self.pullup * adc / (1.0 - adc)
|
||||
|
||||
|
|
|
|||
|
|
@ -49,11 +49,13 @@ class HallFilamentWidthSensor:
|
|||
# Start adc
|
||||
self.ppins = self.printer.lookup_object('pins')
|
||||
self.mcu_adc = self.ppins.setup_pin('adc', self.pin1)
|
||||
self.mcu_adc.setup_adc_sample(ADC_SAMPLE_TIME, ADC_SAMPLE_COUNT)
|
||||
self.mcu_adc.setup_adc_callback(ADC_REPORT_TIME, self.adc_callback)
|
||||
self.mcu_adc.setup_adc_sample(ADC_REPORT_TIME,
|
||||
ADC_SAMPLE_TIME, ADC_SAMPLE_COUNT)
|
||||
self.mcu_adc.setup_adc_callback(self.adc_callback)
|
||||
self.mcu_adc2 = self.ppins.setup_pin('adc', self.pin2)
|
||||
self.mcu_adc2.setup_adc_sample(ADC_SAMPLE_TIME, ADC_SAMPLE_COUNT)
|
||||
self.mcu_adc2.setup_adc_callback(ADC_REPORT_TIME, self.adc2_callback)
|
||||
self.mcu_adc2.setup_adc_sample(ADC_REPORT_TIME,
|
||||
ADC_SAMPLE_TIME, ADC_SAMPLE_COUNT)
|
||||
self.mcu_adc2.setup_adc_callback(self.adc2_callback)
|
||||
# extrude factor updating
|
||||
self.extrude_factor_update_timer = self.reactor.register_timer(
|
||||
self.extrude_factor_update_event)
|
||||
|
|
@ -83,12 +85,14 @@ class HallFilamentWidthSensor:
|
|||
self.reactor.update_timer(self.extrude_factor_update_timer,
|
||||
self.reactor.NOW)
|
||||
|
||||
def adc_callback(self, read_time, read_value):
|
||||
def adc_callback(self, samples):
|
||||
# read sensor value
|
||||
read_time, read_value = samples[-1]
|
||||
self.lastFilamentWidthReading = round(read_value * 10000)
|
||||
|
||||
def adc2_callback(self, read_time, read_value):
|
||||
def adc2_callback(self, samples):
|
||||
# read sensor value
|
||||
read_time, read_value = samples[-1]
|
||||
self.lastFilamentWidthReading2 = round(read_value * 10000)
|
||||
# calculate diameter
|
||||
diameter_new = round((self.dia2 - self.dia1)/
|
||||
|
|
|
|||
|
|
@ -31,12 +31,13 @@ class PrinterTemperatureMCU:
|
|||
ppins = config.get_printer().lookup_object('pins')
|
||||
self.mcu_adc = ppins.setup_pin('adc',
|
||||
'%s:ADC_TEMPERATURE' % (mcu_name,))
|
||||
self.mcu_adc.setup_adc_callback(REPORT_TIME, self.adc_callback)
|
||||
self.mcu_adc.setup_adc_callback(self.adc_callback)
|
||||
self.diag_helper = adc_temperature.HelperTemperatureDiagnostics(
|
||||
config, self.mcu_adc, self.calc_temp)
|
||||
# Register callbacks
|
||||
if self.printer.get_start_args().get('debugoutput') is not None:
|
||||
self.mcu_adc.setup_adc_sample(SAMPLE_TIME, SAMPLE_COUNT)
|
||||
self.mcu_adc.setup_adc_sample(REPORT_TIME,
|
||||
SAMPLE_TIME, SAMPLE_COUNT)
|
||||
return
|
||||
self.printer.register_event_handler("klippy:mcu_identify",
|
||||
self.handle_mcu_identify)
|
||||
|
|
@ -49,7 +50,8 @@ class PrinterTemperatureMCU:
|
|||
self.min_temp = min_temp
|
||||
self.max_temp = max_temp
|
||||
# Internal code
|
||||
def adc_callback(self, read_time, read_value):
|
||||
def adc_callback(self, samples):
|
||||
read_time, read_value = samples[-1]
|
||||
temp = self.base_temperature + read_value * self.slope
|
||||
self.temperature_callback(read_time + SAMPLE_COUNT * SAMPLE_TIME, temp)
|
||||
def calc_temp(self, adc):
|
||||
|
|
@ -95,7 +97,7 @@ class PrinterTemperatureMCU:
|
|||
# Setup min/max checks
|
||||
arange = [self.calc_adc(t) for t in [self.min_temp, self.max_temp]]
|
||||
min_adc, max_adc = sorted(arange)
|
||||
self.mcu_adc.setup_adc_sample(SAMPLE_TIME, SAMPLE_COUNT,
|
||||
self.mcu_adc.setup_adc_sample(REPORT_TIME, SAMPLE_TIME, SAMPLE_COUNT,
|
||||
minval=min_adc, maxval=max_adc,
|
||||
range_check_count=RANGE_CHECK_COUNT)
|
||||
self.diag_helper.setup_diag_minmax(self.min_temp, self.max_temp,
|
||||
|
|
|
|||
|
|
@ -33,8 +33,9 @@ class FilamentWidthSensor:
|
|||
# Start adc
|
||||
self.ppins = self.printer.lookup_object('pins')
|
||||
self.mcu_adc = self.ppins.setup_pin('adc', self.pin)
|
||||
self.mcu_adc.setup_adc_sample(ADC_SAMPLE_TIME, ADC_SAMPLE_COUNT)
|
||||
self.mcu_adc.setup_adc_callback(ADC_REPORT_TIME, self.adc_callback)
|
||||
self.mcu_adc.setup_adc_sample(ADC_REPORT_TIME,
|
||||
ADC_SAMPLE_TIME, ADC_SAMPLE_COUNT)
|
||||
self.mcu_adc.setup_adc_callback(self.adc_callback)
|
||||
# extrude factor updating
|
||||
self.extrude_factor_update_timer = self.reactor.register_timer(
|
||||
self.extrude_factor_update_event)
|
||||
|
|
@ -57,8 +58,9 @@ class FilamentWidthSensor:
|
|||
self.reactor.update_timer(self.extrude_factor_update_timer,
|
||||
self.reactor.NOW)
|
||||
|
||||
def adc_callback(self, read_time, read_value):
|
||||
def adc_callback(self, samples):
|
||||
# read sensor value
|
||||
read_time, read_value = samples[-1]
|
||||
self.lastFilamentWidthReading = round(read_value * 5, 2)
|
||||
|
||||
def update_filament_array(self, last_epos):
|
||||
|
|
|
|||
|
|
@ -535,7 +535,7 @@ class MCU_adc:
|
|||
self._pin = pin_params['pin']
|
||||
self._min_sample = self._max_sample = 0.
|
||||
self._sample_time = self._report_time = 0.
|
||||
self._sample_count = self._range_check_count = 0
|
||||
self._sample_count = self._batch_num = self._range_check_count = 0
|
||||
self._report_clock = 0
|
||||
self._last_state = (0., 0.)
|
||||
self._oid = self._callback = None
|
||||
|
|
@ -544,15 +544,17 @@ class MCU_adc:
|
|||
self._unpack_from = struct.Struct('<H').unpack_from
|
||||
def get_mcu(self):
|
||||
return self._mcu
|
||||
def setup_adc_sample(self, sample_time, sample_count,
|
||||
minval=0., maxval=1., range_check_count=0):
|
||||
def setup_adc_sample(self, report_time, sample_time=0., sample_count=1,
|
||||
batch_num=1, minval=0., maxval=1.,
|
||||
range_check_count=0):
|
||||
self._report_time = report_time
|
||||
self._sample_time = sample_time
|
||||
self._sample_count = sample_count
|
||||
self._batch_num = max(1, min(48 // 2, batch_num))
|
||||
self._min_sample = minval
|
||||
self._max_sample = maxval
|
||||
self._range_check_count = range_check_count
|
||||
def setup_adc_callback(self, report_time, callback):
|
||||
self._report_time = report_time
|
||||
def setup_adc_callback(self, callback):
|
||||
self._callback = callback
|
||||
def get_last_value(self):
|
||||
return self._last_state
|
||||
|
|
@ -560,12 +562,15 @@ class MCU_adc:
|
|||
if not self._sample_count:
|
||||
return
|
||||
self._oid = self._mcu.create_oid()
|
||||
self._mcu.add_config_cmd("config_analog_in oid=%d pin=%s" % (
|
||||
self._oid, self._pin))
|
||||
self._mcu.add_config_cmd("config_analog_in oid=%d pin=%s"
|
||||
% (self._oid, self._pin))
|
||||
clock = self._mcu.get_query_slot(self._oid)
|
||||
sample_ticks = self._mcu.seconds_to_clock(self._sample_time)
|
||||
mcu_adc_max = self._mcu.get_constant_float("ADC_MAX")
|
||||
max_adc = self._sample_count * mcu_adc_max
|
||||
if max_adc >= (1<<16):
|
||||
raise self._mcu.get_printer().config_error(
|
||||
"ADC sample_count=%d too large for MCU" % (self._sample_count,))
|
||||
self._inv_max_adc = 1.0 / max_adc
|
||||
self._report_clock = self._mcu.seconds_to_clock(self._report_time)
|
||||
min_sample = max(0, min(0xffff, int(self._min_sample * max_adc)))
|
||||
|
|
@ -575,7 +580,8 @@ class MCU_adc:
|
|||
oldcmd = (
|
||||
"query_analog_in oid=%c clock=%u sample_ticks=%u sample_count=%c"
|
||||
" rest_ticks=%u min_value=%hu max_value=%hu range_check_count=%c")
|
||||
if self._mcu.try_lookup_command(oldcmd) is not None:
|
||||
if (self._batch_num == 1
|
||||
and self._mcu.try_lookup_command(oldcmd) is not None):
|
||||
self._mcu.add_config_cmd(
|
||||
"query_analog_in oid=%d clock=%d sample_ticks=%d"
|
||||
" sample_count=%d rest_ticks=%d"
|
||||
|
|
@ -587,12 +593,13 @@ class MCU_adc:
|
|||
"analog_in_state", self._oid)
|
||||
return
|
||||
BYTES_PER_SAMPLE = 2
|
||||
bytes_per_report = self._batch_num * BYTES_PER_SAMPLE
|
||||
self._mcu.add_config_cmd(
|
||||
"query_analog_in oid=%d clock=%d sample_ticks=%d sample_count=%d"
|
||||
" rest_ticks=%d bytes_per_report=%d"
|
||||
" min_value=%d max_value=%d range_check_count=%d" % (
|
||||
self._oid, clock, sample_ticks, self._sample_count,
|
||||
self._report_clock, BYTES_PER_SAMPLE, min_sample, max_sample,
|
||||
self._report_clock, bytes_per_report, min_sample, max_sample,
|
||||
self._range_check_count), is_init=True)
|
||||
self._mcu.register_response(self._handle_analog_in_state,
|
||||
"analog_in_state", self._oid)
|
||||
|
|
@ -603,16 +610,17 @@ class MCU_adc:
|
|||
last_read_time = self._mcu.clock_to_print_time(last_read_clock)
|
||||
self._last_state = (last_read_time, last_value)
|
||||
if self._callback is not None:
|
||||
self._callback(last_read_time, last_value)
|
||||
self._callback([(last_read_time, last_value)])
|
||||
def _handle_analog_in_state(self, params):
|
||||
values = self._unpack_from(params['values'])
|
||||
last_value = values[0] * self._inv_max_adc
|
||||
next_clock = self._mcu.clock32_to_clock64(params['next_clock'])
|
||||
last_read_clock = next_clock - self._report_clock
|
||||
last_read_time = self._mcu.clock_to_print_time(last_read_clock)
|
||||
self._last_state = (last_read_time, last_value)
|
||||
ctpt = self._mcu.clock_to_print_time
|
||||
num = len(values)
|
||||
samples = [(ctpt(next_clock - (num - i)*self._report_clock),
|
||||
values[i] * self._inv_max_adc) for i in range(num)]
|
||||
self._last_state = samples[-1]
|
||||
if self._callback is not None:
|
||||
self._callback(last_read_time, last_value)
|
||||
self._callback(samples)
|
||||
|
||||
|
||||
######################################################################
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue