diff --git a/README.md b/README.md index 11a20406af0e..a96190078dba 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,8 @@ If you're feeling adventurous, take a peek at the extra features in the bleeding - [input_shaper: new print_ringing_tower utility](https://github.com/DangerKlippers/danger-klipper/pull/69) +- [adxl345: improve ACCELEROMETER_QUERY command](https://github.com/DangerKlippers/danger-klipper/pull/124) + ## Switch to Danger Klipper > [!NOTE] diff --git a/docs/G-Codes.md b/docs/G-Codes.md index eb64894dcfe4..b39551da76c1 100644 --- a/docs/G-Codes.md +++ b/docs/G-Codes.md @@ -88,12 +88,19 @@ accelerometer does not have a name in its config section (simply `[adxl345]`) then `` part of the name is not generated. #### ACCELEROMETER_QUERY -`ACCELEROMETER_QUERY [CHIP=] [RATE=]`: queries +`ACCELEROMETER_QUERY [CHIP=] [RATE=] +[SAMPLES=] [RETURN=]`: queries accelerometer for the current value. If CHIP is not specified it defaults to "adxl345". If RATE is not specified, the default value is used. This command is useful to test the connection to the ADXL345 accelerometer: one of the returned values should be a free-fall -acceleration (+/- some noise of the chip). +acceleration (+/- some noise of the chip). The `SAMPLES` parameter +can be set to sample multiple readings from the sensor. The readings +will be averaged together. The default is to collect a single sample. +The `RETURN` parameter can take on the values `vector`(the default) or +`tilt`. In `vector` mode, the raw free-fall acceleration vector is +returned. In `tilt` mode, X and Y angles of a plane perpendicular to +the free-fall vector are calculated and displayed. #### ACCELEROMETER_DEBUG_READ `ACCELEROMETER_DEBUG_READ [CHIP=] REG=`: diff --git a/klippy/extras/adxl345.py b/klippy/extras/adxl345.py index 03e4d8b4b582..50563a3e205f 100644 --- a/klippy/extras/adxl345.py +++ b/klippy/extras/adxl345.py @@ -3,7 +3,7 @@ # Copyright (C) 2020-2021 Kevin O'Connor # # This file may be distributed under the terms of the GNU GPLv3 license. -import logging, time, collections, threading, multiprocessing, os +import logging, time, collections, threading, multiprocessing, os, math from . import bus, motion_report # ADXL345 registers @@ -37,6 +37,7 @@ "Accel_Measurement", ("time", "accel_x", "accel_y", "accel_z") ) + # Helper class to obtain measurements class AccelQueryHelper: def __init__(self, printer, cconn): @@ -192,17 +193,38 @@ def cmd_ACCELEROMETER_MEASURE(self, gcmd): cmd_ACCELEROMETER_QUERY_help = "Query accelerometer for the current values" def cmd_ACCELEROMETER_QUERY(self, gcmd): - aclient = self.chip.start_internal_client() - self.printer.lookup_object("toolhead").dwell(1.0) - aclient.finish_measurements() - values = aclient.get_samples() - if not values: - raise gcmd.error("No accelerometer measurements found") - _, accel_x, accel_y, accel_z = values[-1] - gcmd.respond_info( - "accelerometer values (x, y, z): %.6f, %.6f, %.6f" - % (accel_x, accel_y, accel_z) - ) + num_samples = gcmd.get_int("SAMPLES", 1) + samples = [] + while num_samples > 0: + aclient = self.chip.start_internal_client() + self.printer.lookup_object("toolhead").dwell(1.0) + aclient.finish_measurements() + values = aclient.get_samples() + if not values: + raise gcmd.error("No accelerometer measurements found") + take = min(len(values), num_samples) + num_samples -= take + samples.extend(values[-take:]) + + accel_x = sum([x for (_, x, y, z) in samples]) / len(samples) + accel_y = sum([y for (_, x, y, z) in samples]) / len(samples) + accel_z = sum([z for (_, x, y, z) in samples]) / len(samples) + + return_type = gcmd.get("RETURN", "vector") + if return_type == "tilt": + tilt_x = math.degrees(math.atan2(accel_x, accel_z)) + tilt_y = math.degrees(math.atan2(accel_y, accel_z)) + gcmd.respond_info( + "accelerometer plane tilt degrees (x, y): %.6f, %.6f" + % (tilt_x, tilt_y) + ) + elif return_type == "vector": + gcmd.respond_info( + "accelerometer values (x, y, z): %.6f, %.6f, %.6f" + % (accel_x, accel_y, accel_z) + ) + else: + raise gcmd.error("Unknown 'return' type '%s'" % (return_type,)) cmd_ACCELEROMETER_DEBUG_READ_help = "Query register (for debugging)" @@ -283,6 +305,7 @@ def get_time_translation(self): BYTES_PER_SAMPLE = 5 SAMPLES_PER_BLOCK = 10 + # Printer class that controls ADXL345 chip class ADXL345: def __init__(self, config):