adxl345: Add new start_internal_client() function and use in callers

Introduce a new start_internal_client() function and change all client
code to use that instead of manually calling start_measurements() and
finish_measurements().

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
Kevin O'Connor 2021-08-11 23:09:49 -04:00
parent 8cfaed441d
commit d87f7a77c3
2 changed files with 58 additions and 45 deletions

View File

@ -28,23 +28,28 @@ SCALE = 0.0039 * FREEFALL_ACCEL # 3.9mg/LSB * Earth gravity in mm/s**2
Accel_Measurement = collections.namedtuple( Accel_Measurement = collections.namedtuple(
'Accel_Measurement', ('time', 'accel_x', 'accel_y', 'accel_z')) 'Accel_Measurement', ('time', 'accel_x', 'accel_y', 'accel_z'))
# Sample results # Helper class to obtain measurements
class ADXL345Results: class ADXL345QueryHelper:
def __init__(self): def __init__(self, printer, chip, axes_map):
self.printer = printer
self.chip = chip
self.axes_map = axes_map
self.raw_samples = None self.raw_samples = None
self.samples = [] self.samples = []
self.drops = self.overflows = 0 self.drops = self.overflows = 0
self.time_per_sample = self.start_range = self.end_range = 0. self.time_per_sample = self.start_range = self.end_range = 0.
def finish_measurements(self):
self.chip._finish_measurements()
self._setup_data(*self.chip.final_results) # XXX
def get_stats(self): def get_stats(self):
return ("drops=%d,overflows=%d" return ("drops=%d,overflows=%d"
",time_per_sample=%.9f,start_range=%.6f,end_range=%.6f" ",time_per_sample=%.9f,start_range=%.6f,end_range=%.6f"
% (self.drops, self.overflows, % (self.drops, self.overflows,
self.time_per_sample, self.start_range, self.end_range)) self.time_per_sample, self.start_range, self.end_range))
def setup_data(self, axes_map, raw_samples, end_sequence, overflows, def _setup_data(self, raw_samples, end_sequence, overflows,
start1_time, start2_time, end1_time, end2_time): start1_time, start2_time, end1_time, end2_time):
if not raw_samples or not end_sequence: if not raw_samples or not end_sequence:
return return
self.axes_map = axes_map
self.raw_samples = raw_samples self.raw_samples = raw_samples
self.overflows = overflows self.overflows = overflows
self.start2_time = start2_time self.start2_time = start2_time
@ -101,6 +106,7 @@ class ADXLCommandHelper:
def __init__(self, config, chip): def __init__(self, config, chip):
self.printer = config.get_printer() self.printer = config.get_printer()
self.chip = chip self.chip = chip
self.bg_client = None
self.name = "default" self.name = "default"
if len(config.get_name().split()) > 1: if len(config.get_name().split()) > 1:
self.name = config.get_name().split()[1] self.name = config.get_name().split()[1]
@ -126,30 +132,34 @@ class ADXLCommandHelper:
def cmd_ACCELEROMETER_MEASURE(self, gcmd): def cmd_ACCELEROMETER_MEASURE(self, gcmd):
if not self.chip.is_measuring(): if not self.chip.is_measuring():
# Start measurements # Start measurements
self.chip.start_measurements() self.bg_client = self.chip.start_internal_client()
gcmd.respond_info("adxl345 measurements started") gcmd.respond_info("adxl345 measurements started")
return return
if self.bg_client is None:
raise gcmd.error("adxl345 measurements in progress")
# End measurements # End measurements
name = gcmd.get("NAME", time.strftime("%Y%m%d_%H%M%S")) name = gcmd.get("NAME", time.strftime("%Y%m%d_%H%M%S"))
if not name.replace('-', '').replace('_', '').isalnum(): if not name.replace('-', '').replace('_', '').isalnum():
raise gcmd.error("Invalid adxl345 NAME parameter") raise gcmd.error("Invalid adxl345 NAME parameter")
res = self.chip.finish_measurements() bg_client = self.bg_client
self.bg_client = None
bg_client.finish_measurements()
# Write data to file # Write data to file
if self.name == "default": if self.name == "default":
filename = "/tmp/adxl345-%s.csv" % (name,) filename = "/tmp/adxl345-%s.csv" % (name,)
else: else:
filename = "/tmp/adxl345-%s-%s.csv" % (self.name, name,) filename = "/tmp/adxl345-%s-%s.csv" % (self.name, name,)
res.write_to_file(filename) bg_client.write_to_file(filename)
gcmd.respond_info("Writing raw accelerometer data to %s file" gcmd.respond_info("Writing raw accelerometer data to %s file"
% (filename,)) % (filename,))
cmd_ACCELEROMETER_QUERY_help = "Query accelerometer for the current values" cmd_ACCELEROMETER_QUERY_help = "Query accelerometer for the current values"
def cmd_ACCELEROMETER_QUERY(self, gcmd): def cmd_ACCELEROMETER_QUERY(self, gcmd):
if self.chip.is_measuring(): if self.chip.is_measuring():
raise gcmd.error("adxl345 measurements in progress") raise gcmd.error("adxl345 measurements in progress")
self.chip.start_measurements() aclient = self.chip.start_internal_client()
self.printer.lookup_object('toolhead').dwell(1.) self.printer.lookup_object('toolhead').dwell(1.)
result = self.chip.finish_measurements() aclient.finish_measurements()
values = result.decode_samples() values = aclient.decode_samples()
if not values: if not values:
raise gcmd.error("No adxl345 measurements found") raise gcmd.error("No adxl345 measurements found")
_, accel_x, accel_y, accel_z = values[-1] _, accel_x, accel_y, accel_z = values[-1]
@ -247,7 +257,7 @@ class ADXL345:
reg, val, stored_val)) reg, val, stored_val))
def is_measuring(self): def is_measuring(self):
return self.query_rate > 0 return self.query_rate > 0
def start_measurements(self): def _start_measurements(self):
if self.is_measuring(): if self.is_measuring():
return return
# In case of miswiring, testing ADXL345 device ID prevents treating # In case of miswiring, testing ADXL345 device ID prevents treating
@ -277,9 +287,10 @@ class ADXL345:
self.query_rate = self.data_rate self.query_rate = self.data_rate
self.query_adxl345_cmd.send([self.oid, reqclock, rest_ticks], self.query_adxl345_cmd.send([self.oid, reqclock, rest_ticks],
reqclock=reqclock) reqclock=reqclock)
def finish_measurements(self): logging.info("ADXL345 starting measurements")
def _finish_measurements(self):
if not self.is_measuring(): if not self.is_measuring():
return ADXL345Results() return
# Halt bulk reading # Halt bulk reading
print_time = self.printer.lookup_object('toolhead').get_last_move_time() print_time = self.printer.lookup_object('toolhead').get_last_move_time()
clock = self.mcu.print_time_to_clock(print_time) clock = self.mcu.print_time_to_clock(print_time)
@ -294,13 +305,16 @@ class ADXL345:
end2_time = self._clock_to_print_time(params['end2_clock']) end2_time = self._clock_to_print_time(params['end2_clock'])
end_sequence = self._convert_sequence(params['sequence']) end_sequence = self._convert_sequence(params['sequence'])
overflows = params['limit_count'] overflows = params['limit_count']
res = ADXL345Results() logging.info("ADXL345 finished measurements")
res.setup_data(self.axes_map, raw_samples, end_sequence, overflows, self.final_results = (raw_samples, end_sequence, overflows,
self.samples_start1, self.samples_start2, self.samples_start1, self.samples_start2,
end1_time, end2_time) end1_time, end2_time) # XXX
logging.info("ADXL345 finished %d measurements: %s", def start_internal_client(self):
res.total_count, res.get_stats()) if self.is_measuring():
return res raise self.printer.command_error(
"ADXL345 measurement already in progress")
self._start_measurements()
return ADXL345QueryHelper(self.printer, self, self.axes_map)
def load_config(config): def load_config(config):
return ADXL345(config) return ADXL345(config)

View File

@ -164,26 +164,25 @@ class ResonanceTester:
if len(axes) > 1: if len(axes) > 1:
gcmd.respond_info("Testing axis %s" % axis.get_name()) gcmd.respond_info("Testing axis %s" % axis.get_name())
for chip_axis, chip in self.accel_chips:
if axis.matches(chip_axis):
chip.start_measurements()
# Generate moves
self.test.run_test(axis, gcmd)
raw_values = [] raw_values = []
for chip_axis, chip in self.accel_chips: for chip_axis, chip in self.accel_chips:
if axis.matches(chip_axis): if axis.matches(chip_axis):
results = chip.finish_measurements() aclient = chip.start_internal_client()
if raw_name_suffix is not None: raw_values.append((chip_axis, aclient))
raw_name = self.get_filename( # Generate moves
'raw_data', raw_name_suffix, axis, self.test.run_test(axis, gcmd)
point if len(test_points) > 1 else None) for chip_axis, aclient in raw_values:
results.write_to_file(raw_name) aclient.finish_measurements()
gcmd.respond_info( if raw_name_suffix is not None:
"Writing raw accelerometer data to " raw_name = self.get_filename(
"%s file" % (raw_name,)) 'raw_data', raw_name_suffix, axis,
raw_values.append((chip_axis, results)) point if len(test_points) > 1 else None)
gcmd.respond_info("%s-axis accelerometer stats: %s" % ( aclient.write_to_file(raw_name)
chip_axis, results.get_stats(),)) gcmd.respond_info(
"Writing raw accelerometer data to "
"%s file" % (raw_name,))
gcmd.respond_info("%s-axis accelerometer stats: %s" % (
chip_axis, aclient.get_stats(),))
if helper is None: if helper is None:
continue continue
for chip_axis, chip_values in raw_values: for chip_axis, chip_values in raw_values:
@ -281,14 +280,14 @@ class ResonanceTester:
"Measures noise of all enabled accelerometer chips") "Measures noise of all enabled accelerometer chips")
def cmd_MEASURE_AXES_NOISE(self, gcmd): def cmd_MEASURE_AXES_NOISE(self, gcmd):
meas_time = gcmd.get_float("MEAS_TIME", 2.) meas_time = gcmd.get_float("MEAS_TIME", 2.)
for _, chip in self.accel_chips: raw_values = [(chip_axis, chip.start_internal_client())
chip.start_measurements()
self.printer.lookup_object('toolhead').dwell(meas_time)
raw_values = [(chip_axis, chip.finish_measurements())
for chip_axis, chip in self.accel_chips] for chip_axis, chip in self.accel_chips]
self.printer.lookup_object('toolhead').dwell(meas_time)
for chip_axis, aclient in raw_values:
aclient.finish_measurements()
helper = shaper_calibrate.ShaperCalibrate(self.printer) helper = shaper_calibrate.ShaperCalibrate(self.printer)
for chip_axis, raw_data in raw_values: for chip_axis, aclient in raw_values:
data = helper.process_accelerometer_data(raw_data) data = helper.process_accelerometer_data(aclient)
vx = data.psd_x.mean() vx = data.psd_x.mean()
vy = data.psd_y.mean() vy = data.psd_y.mean()
vz = data.psd_z.mean() vz = data.psd_z.mean()