resonance_tester: Arbitrary AXIS in TEST_RESONANCES command
Signed-off-by: Dmitry Butyugin <dmbutyugin@google.com>
This commit is contained in:
parent
0edcd0bb7b
commit
1128e9179b
|
@ -15,6 +15,45 @@ def _parse_probe_points(config):
|
||||||
raise config.error("Unable to parse probe_points in %s" % (
|
raise config.error("Unable to parse probe_points in %s" % (
|
||||||
config.get_name()))
|
config.get_name()))
|
||||||
|
|
||||||
|
class TestAxis:
|
||||||
|
def __init__(self, axis=None, vib_dir=None):
|
||||||
|
if axis is None:
|
||||||
|
self._name = "axis=%.3f,%.3f" % (vib_dir[0], vib_dir[1])
|
||||||
|
else:
|
||||||
|
self._name = axis
|
||||||
|
if vib_dir is None:
|
||||||
|
self._vib_dir = (1., 0.) if axis == 'x' else (0., 1.)
|
||||||
|
else:
|
||||||
|
s = math.sqrt(sum([d*d for d in vib_dir]))
|
||||||
|
self._vib_dir = [d / s for d in vib_dir]
|
||||||
|
def matches(self, chip_axis):
|
||||||
|
if self._vib_dir[0] and 'x' in chip_axis:
|
||||||
|
return True
|
||||||
|
if self._vib_dir[1] and 'y' in chip_axis:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
def get_name(self):
|
||||||
|
return self._name
|
||||||
|
def get_point(self, l):
|
||||||
|
return (self._vib_dir[0] * l, self._vib_dir[1] * l)
|
||||||
|
|
||||||
|
def _parse_axis(gcmd, raw_axis):
|
||||||
|
if raw_axis is None:
|
||||||
|
return None
|
||||||
|
raw_axis = raw_axis.lower()
|
||||||
|
if raw_axis in ['x', 'y']:
|
||||||
|
return TestAxis(axis=raw_axis)
|
||||||
|
dirs = raw_axis.split(',')
|
||||||
|
if len(dirs) != 2:
|
||||||
|
raise gcmd.error("Invalid format of axis '%s'" % (raw_axis,))
|
||||||
|
try:
|
||||||
|
dir_x = float(dirs[0].strip())
|
||||||
|
dir_y = float(dirs[1].strip())
|
||||||
|
except:
|
||||||
|
raise gcmd.error(
|
||||||
|
"Unable to parse axis direction '%s'" % (raw_axis,))
|
||||||
|
return TestAxis(vib_dir=(dir_x, dir_y))
|
||||||
|
|
||||||
class VibrationPulseTest:
|
class VibrationPulseTest:
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
self.printer = config.get_printer()
|
self.printer = config.get_printer()
|
||||||
|
@ -28,8 +67,6 @@ class VibrationPulseTest:
|
||||||
minval=0.1, maxval=2.)
|
minval=0.1, maxval=2.)
|
||||||
|
|
||||||
self.probe_points = _parse_probe_points(config)
|
self.probe_points = _parse_probe_points(config)
|
||||||
def get_supported_axes(self):
|
|
||||||
return ['x', 'y']
|
|
||||||
def get_start_test_points(self):
|
def get_start_test_points(self):
|
||||||
return self.probe_points
|
return self.probe_points
|
||||||
def prepare_test(self, gcmd):
|
def prepare_test(self, gcmd):
|
||||||
|
@ -41,9 +78,6 @@ class VibrationPulseTest:
|
||||||
def run_test(self, axis, gcmd):
|
def run_test(self, axis, gcmd):
|
||||||
toolhead = self.printer.lookup_object('toolhead')
|
toolhead = self.printer.lookup_object('toolhead')
|
||||||
X, Y, Z, E = toolhead.get_position()
|
X, Y, Z, E = toolhead.get_position()
|
||||||
if axis not in self.get_supported_axes():
|
|
||||||
raise gcmd.error("Test axis '%s' is not supported", axis)
|
|
||||||
vib_dir = (1, 0) if axis == 'x' else (0., 1.)
|
|
||||||
sign = 1.
|
sign = 1.
|
||||||
freq = self.freq_start
|
freq = self.freq_start
|
||||||
# Override maximum acceleration and acceleration to
|
# Override maximum acceleration and acceleration to
|
||||||
|
@ -70,8 +104,9 @@ class VibrationPulseTest:
|
||||||
toolhead.cmd_M204(self.gcode.create_gcode_command(
|
toolhead.cmd_M204(self.gcode.create_gcode_command(
|
||||||
"M204", "M204", {"S": accel}))
|
"M204", "M204", {"S": accel}))
|
||||||
L = .5 * accel * t_seg**2
|
L = .5 * accel * t_seg**2
|
||||||
nX = X + sign * vib_dir[0] * L
|
dX, dY = axis.get_point(L)
|
||||||
nY = Y + sign * vib_dir[1] * L
|
nX = X + sign * dX
|
||||||
|
nY = Y + sign * dY
|
||||||
toolhead.move([nX, nY, Z, E], max_v)
|
toolhead.move([nX, nY, Z, E], max_v)
|
||||||
toolhead.move([X, Y, Z, E], max_v)
|
toolhead.move([X, Y, Z, E], max_v)
|
||||||
sign = -sign
|
sign = -sign
|
||||||
|
@ -117,8 +152,8 @@ class ResonanceTester:
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
self.accel_chips = [
|
self.accel_chips = [
|
||||||
(axis, self.printer.lookup_object(chip_name))
|
(chip_axis, self.printer.lookup_object(chip_name))
|
||||||
for axis, chip_name in self.accel_chip_names]
|
for chip_axis, chip_name in self.accel_chip_names]
|
||||||
|
|
||||||
def _run_test(self, gcmd, axes, helper, raw_name_suffix=None):
|
def _run_test(self, gcmd, axes, helper, raw_name_suffix=None):
|
||||||
toolhead = self.printer.lookup_object('toolhead')
|
toolhead = self.printer.lookup_object('toolhead')
|
||||||
|
@ -135,16 +170,16 @@ class ResonanceTester:
|
||||||
toolhead.wait_moves()
|
toolhead.wait_moves()
|
||||||
toolhead.dwell(0.500)
|
toolhead.dwell(0.500)
|
||||||
if len(axes) > 1:
|
if len(axes) > 1:
|
||||||
gcmd.respond_info("Testing axis %s" % axis.upper())
|
gcmd.respond_info("Testing axis %s" % axis.get_name())
|
||||||
|
|
||||||
for chip_axis, chip in self.accel_chips:
|
for chip_axis, chip in self.accel_chips:
|
||||||
if axis in chip_axis or chip_axis in axis:
|
if axis.matches(chip_axis):
|
||||||
chip.start_measurements()
|
chip.start_measurements()
|
||||||
# Generate moves
|
# Generate moves
|
||||||
self.test.run_test(axis, gcmd)
|
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 in chip_axis or chip_axis in axis:
|
if axis.matches(chip_axis):
|
||||||
results = chip.finish_measurements()
|
results = chip.finish_measurements()
|
||||||
if raw_name_suffix is not None:
|
if raw_name_suffix is not None:
|
||||||
raw_name = self.get_filename(
|
raw_name = self.get_filename(
|
||||||
|
@ -173,12 +208,7 @@ class ResonanceTester:
|
||||||
cmd_TEST_RESONANCES_help = ("Runs the resonance test for a specifed axis")
|
cmd_TEST_RESONANCES_help = ("Runs the resonance test for a specifed axis")
|
||||||
def cmd_TEST_RESONANCES(self, gcmd):
|
def cmd_TEST_RESONANCES(self, gcmd):
|
||||||
# Parse parameters
|
# Parse parameters
|
||||||
if len(self.test.get_supported_axes()) > 1:
|
axis = _parse_axis(gcmd, gcmd.get("AXIS").lower())
|
||||||
axis = gcmd.get("AXIS").lower()
|
|
||||||
else:
|
|
||||||
axis = gcmd.get("AXIS", self.test.get_supported_axes()[0]).lower()
|
|
||||||
if axis not in self.test.get_supported_axes():
|
|
||||||
raise gcmd.error("Unsupported axis '%s'" % (axis,))
|
|
||||||
|
|
||||||
outputs = gcmd.get("OUTPUT", "resonances").lower().split(',')
|
outputs = gcmd.get("OUTPUT", "resonances").lower().split(',')
|
||||||
for output in outputs:
|
for output in outputs:
|
||||||
|
@ -214,11 +244,11 @@ class ResonanceTester:
|
||||||
# Parse parameters
|
# Parse parameters
|
||||||
axis = gcmd.get("AXIS", None)
|
axis = gcmd.get("AXIS", None)
|
||||||
if not axis:
|
if not axis:
|
||||||
calibrate_axes = self.test.get_supported_axes()
|
calibrate_axes = [TestAxis('x'), TestAxis('y')]
|
||||||
elif axis.lower() not in self.test.get_supported_axes():
|
elif axis.lower() not in 'xy':
|
||||||
raise gcmd.error("Unsupported axis '%s'" % (axis,))
|
raise gcmd.error("Unsupported axis '%s'" % (axis,))
|
||||||
else:
|
else:
|
||||||
calibrate_axes = [axis.lower()]
|
calibrate_axes = [TestAxis(axis.lower())]
|
||||||
|
|
||||||
max_smoothing = gcmd.get_float(
|
max_smoothing = gcmd.get_float(
|
||||||
"MAX_SMOOTHING", self.max_smoothing, minval=0.05)
|
"MAX_SMOOTHING", self.max_smoothing, minval=0.05)
|
||||||
|
@ -234,16 +264,18 @@ class ResonanceTester:
|
||||||
|
|
||||||
configfile = self.printer.lookup_object('configfile')
|
configfile = self.printer.lookup_object('configfile')
|
||||||
for axis in calibrate_axes:
|
for axis in calibrate_axes:
|
||||||
|
axis_name = axis.get_name()
|
||||||
gcmd.respond_info(
|
gcmd.respond_info(
|
||||||
"Calculating the best input shaper parameters for %s axis"
|
"Calculating the best input shaper parameters for %s axis"
|
||||||
% (axis,))
|
% (axis_name,))
|
||||||
calibration_data[axis].normalize_to_frequencies()
|
calibration_data[axis].normalize_to_frequencies()
|
||||||
best_shaper, all_shapers = helper.find_best_shaper(
|
best_shaper, all_shapers = helper.find_best_shaper(
|
||||||
calibration_data[axis], max_smoothing, gcmd.respond_info)
|
calibration_data[axis], max_smoothing, gcmd.respond_info)
|
||||||
gcmd.respond_info(
|
gcmd.respond_info(
|
||||||
"Recommended shaper_type_%s = %s, shaper_freq_%s = %.1f Hz"
|
"Recommended shaper_type_%s = %s, shaper_freq_%s = %.1f Hz"
|
||||||
% (axis, best_shaper.name, axis, best_shaper.freq))
|
% (axis_name, best_shaper.name,
|
||||||
helper.save_params(configfile, axis,
|
axis_name, best_shaper.freq))
|
||||||
|
helper.save_params(configfile, axis_name,
|
||||||
best_shaper.name, best_shaper.freq)
|
best_shaper.name, best_shaper.freq)
|
||||||
csv_name = self.save_calibration_data(
|
csv_name = self.save_calibration_data(
|
||||||
'calibration_data', name_suffix, helper, axis,
|
'calibration_data', name_suffix, helper, axis,
|
||||||
|
@ -260,17 +292,17 @@ class ResonanceTester:
|
||||||
for _, chip in self.accel_chips:
|
for _, chip in self.accel_chips:
|
||||||
chip.start_measurements()
|
chip.start_measurements()
|
||||||
self.printer.lookup_object('toolhead').dwell(meas_time)
|
self.printer.lookup_object('toolhead').dwell(meas_time)
|
||||||
raw_values = [(axis, chip.finish_measurements())
|
raw_values = [(chip_axis, chip.finish_measurements())
|
||||||
for axis, chip in self.accel_chips]
|
for chip_axis, chip in self.accel_chips]
|
||||||
helper = shaper_calibrate.ShaperCalibrate(self.printer)
|
helper = shaper_calibrate.ShaperCalibrate(self.printer)
|
||||||
for axis, raw_data in raw_values:
|
for chip_axis, raw_data in raw_values:
|
||||||
data = helper.process_accelerometer_data(raw_data)
|
data = helper.process_accelerometer_data(raw_data)
|
||||||
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()
|
||||||
gcmd.respond_info("Axes noise for %s-axis accelerometer: "
|
gcmd.respond_info("Axes noise for %s-axis accelerometer: "
|
||||||
"%.6f (x), %.6f (y), %.6f (z)" % (
|
"%.6f (x), %.6f (y), %.6f (z)" % (
|
||||||
axis, vx, vy, vz))
|
chip_axis, vx, vy, vz))
|
||||||
|
|
||||||
def is_valid_name_suffix(self, name_suffix):
|
def is_valid_name_suffix(self, name_suffix):
|
||||||
return name_suffix.replace('-', '').replace('_', '').isalnum()
|
return name_suffix.replace('-', '').replace('_', '').isalnum()
|
||||||
|
@ -278,7 +310,7 @@ class ResonanceTester:
|
||||||
def get_filename(self, base, name_suffix, axis=None, point=None):
|
def get_filename(self, base, name_suffix, axis=None, point=None):
|
||||||
name = base
|
name = base
|
||||||
if axis:
|
if axis:
|
||||||
name += '_' + axis
|
name += '_' + axis.get_name()
|
||||||
if point:
|
if point:
|
||||||
name += "_%.3f_%.3f_%.3f" % (point[0], point[1], point[2])
|
name += "_%.3f_%.3f_%.3f" % (point[0], point[1], point[2])
|
||||||
name += '_' + name_suffix
|
name += '_' + name_suffix
|
||||||
|
|
Loading…
Reference in New Issue